Blame view

fs/gfs2/quota.c 38 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
0d0868bde   Bob Peterson   [GFS2] Get rid of...
3
   * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
b3b94faa5   David Teigland   [GFS2] The core o...
4
5
6
   *
   * This copyrighted material is made available to anyone wishing to use,
   * modify, copy, or redistribute it subject to the terms and conditions
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
7
   * of the GNU General Public License version 2.
b3b94faa5   David Teigland   [GFS2] The core o...
8
9
10
11
12
13
14
15
16
17
   */
  
  /*
   * Quota change tags are associated with each transaction that allocates or
   * deallocates space.  Those changes are accumulated locally to each node (in a
   * per-node file) and then are periodically synced to the quota file.  This
   * avoids the bottleneck of constantly touching the quota file, but introduces
   * fuzziness in the current usage value of IDs that are being used on different
   * nodes in the cluster simultaneously.  So, it is possible for a user on
   * multiple nodes to overrun their quota, but that overrun is controlable.
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
18
   * Since quota tags are part of transactions, there is no need for a quota check
b3b94faa5   David Teigland   [GFS2] The core o...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
   * program to be run on node crashes or anything like that.
   *
   * There are couple of knobs that let the administrator manage the quota
   * fuzziness.  "quota_quantum" sets the maximum time a quota change can be
   * sitting on one node before being synced to the quota file.  (The default is
   * 60 seconds.)  Another knob, "quota_scale" controls how quickly the frequency
   * of quota file syncs increases as the user moves closer to their limit.  The
   * more frequent the syncs, the more accurate the quota enforcement, but that
   * means that there is more contention between the nodes for the quota file.
   * The default value is one.  This sets the maximum theoretical quota overrun
   * (with infinite node with infinite bandwidth) to twice the user's limit.  (In
   * practice, the maximum overrun you see should be much less.)  A "quota_scale"
   * number greater than one makes quota syncs more frequent and reduces the
   * maximum overrun.  Numbers less than one (but greater than zero) make quota
   * syncs less frequent.
   *
   * GFS quotas also use per-ID Lock Value Blocks (LVBs) to cache the contents of
   * the quota file, so it is not being constantly read.
   */
  
  #include <linux/sched.h>
  #include <linux/slab.h>
1495f230f   Ying Han   vmscan: change sh...
41
  #include <linux/mm.h>
b3b94faa5   David Teigland   [GFS2] The core o...
42
43
44
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
b3b94faa5   David Teigland   [GFS2] The core o...
45
  #include <linux/sort.h>
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
46
  #include <linux/fs.h>
2e565bb69   Steven Whitehouse   [GFS2] Mark metad...
47
  #include <linux/bio.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
48
  #include <linux/gfs2_ondisk.h>
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
49
50
  #include <linux/kthread.h>
  #include <linux/freezer.h>
2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
51
  #include <linux/quota.h>
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
52
  #include <linux/dqblk_xfs.h>
b3b94faa5   David Teigland   [GFS2] The core o...
53
54
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
55
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
56
57
58
  #include "bmap.h"
  #include "glock.h"
  #include "glops.h"
b3b94faa5   David Teigland   [GFS2] The core o...
59
60
61
62
63
64
  #include "log.h"
  #include "meta_io.h"
  #include "quota.h"
  #include "rgrp.h"
  #include "super.h"
  #include "trans.h"
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
65
  #include "inode.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
66
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
67
68
69
  
  #define QUOTA_USER 1
  #define QUOTA_GROUP 0
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
70
71
72
73
74
  struct gfs2_quota_change_host {
  	u64 qc_change;
  	u32 qc_flags; /* GFS2_QCF_... */
  	u32 qc_id;
  };
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
75
76
  static LIST_HEAD(qd_lru_list);
  static atomic_t qd_lru_count = ATOMIC_INIT(0);
1328df725   Xu Gang   GFS2: Use DEFINE_...
77
  static DEFINE_SPINLOCK(qd_lru_lock);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
78

1495f230f   Ying Han   vmscan: change sh...
79
  int gfs2_shrink_qd_memory(struct shrinker *shrink, struct shrink_control *sc)
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
80
81
82
  {
  	struct gfs2_quota_data *qd;
  	struct gfs2_sbd *sdp;
1495f230f   Ying Han   vmscan: change sh...
83
  	int nr_to_scan = sc->nr_to_scan;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
84

1495f230f   Ying Han   vmscan: change sh...
85
  	if (nr_to_scan == 0)
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
86
  		goto out;
1495f230f   Ying Han   vmscan: change sh...
87
  	if (!(sc->gfp_mask & __GFP_FS))
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
88
89
90
  		return -1;
  
  	spin_lock(&qd_lru_lock);
1495f230f   Ying Han   vmscan: change sh...
91
  	while (nr_to_scan && !list_empty(&qd_lru_list)) {
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
92
93
94
95
96
97
  		qd = list_entry(qd_lru_list.next,
  				struct gfs2_quota_data, qd_reclaim);
  		sdp = qd->qd_gl->gl_sbd;
  
  		/* Free from the filesystem-specific list */
  		list_del(&qd->qd_list);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
98
99
100
  		gfs2_assert_warn(sdp, !qd->qd_change);
  		gfs2_assert_warn(sdp, !qd->qd_slot_count);
  		gfs2_assert_warn(sdp, !qd->qd_bh_count);
f057f6cdf   Steven Whitehouse   GFS2: Merge lock_...
101
  		gfs2_glock_put(qd->qd_gl);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
102
103
104
105
106
107
108
109
  		atomic_dec(&sdp->sd_quota_count);
  
  		/* Delete it from the common reclaim list */
  		list_del_init(&qd->qd_reclaim);
  		atomic_dec(&qd_lru_count);
  		spin_unlock(&qd_lru_lock);
  		kmem_cache_free(gfs2_quotad_cachep, qd);
  		spin_lock(&qd_lru_lock);
1495f230f   Ying Han   vmscan: change sh...
110
  		nr_to_scan--;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
111
112
113
114
115
116
  	}
  	spin_unlock(&qd_lru_lock);
  
  out:
  	return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
117
  static u64 qd2offset(struct gfs2_quota_data *qd)
b3b94faa5   David Teigland   [GFS2] The core o...
118
  {
cd915493f   Steven Whitehouse   [GFS2] Change all...
119
  	u64 offset;
b3b94faa5   David Teigland   [GFS2] The core o...
120

cd915493f   Steven Whitehouse   [GFS2] Change all...
121
  	offset = 2 * (u64)qd->qd_id + !test_bit(QDF_USER, &qd->qd_flags);
b3b94faa5   David Teigland   [GFS2] The core o...
122
123
124
125
  	offset *= sizeof(struct gfs2_quota);
  
  	return offset;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
126
  static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
b3b94faa5   David Teigland   [GFS2] The core o...
127
128
129
130
  		    struct gfs2_quota_data **qdp)
  {
  	struct gfs2_quota_data *qd;
  	int error;
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
131
  	qd = kmem_cache_zalloc(gfs2_quotad_cachep, GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
132
133
  	if (!qd)
  		return -ENOMEM;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
134
  	atomic_set(&qd->qd_count, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
135
136
137
138
  	qd->qd_id = id;
  	if (user)
  		set_bit(QDF_USER, &qd->qd_flags);
  	qd->qd_slot = -1;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
139
  	INIT_LIST_HEAD(&qd->qd_reclaim);
b3b94faa5   David Teigland   [GFS2] The core o...
140

cd915493f   Steven Whitehouse   [GFS2] Change all...
141
  	error = gfs2_glock_get(sdp, 2 * (u64)id + !user,
b3b94faa5   David Teigland   [GFS2] The core o...
142
143
144
  			      &gfs2_quota_glops, CREATE, &qd->qd_gl);
  	if (error)
  		goto fail;
b3b94faa5   David Teigland   [GFS2] The core o...
145
146
147
  	*qdp = qd;
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
148
  fail:
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
149
  	kmem_cache_free(gfs2_quotad_cachep, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
150
151
  	return error;
  }
6a6ada81e   Steven Whitehouse   GFS2: Remove cons...
152
  static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
b3b94faa5   David Teigland   [GFS2] The core o...
153
154
155
156
157
158
159
160
161
  		  struct gfs2_quota_data **qdp)
  {
  	struct gfs2_quota_data *qd = NULL, *new_qd = NULL;
  	int error, found;
  
  	*qdp = NULL;
  
  	for (;;) {
  		found = 0;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
162
  		spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
163
164
165
  		list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
  			if (qd->qd_id == id &&
  			    !test_bit(QDF_USER, &qd->qd_flags) == !user) {
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
166
167
168
169
170
171
172
  				if (!atomic_read(&qd->qd_count) &&
  				    !list_empty(&qd->qd_reclaim)) {
  					/* Remove it from reclaim list */
  					list_del_init(&qd->qd_reclaim);
  					atomic_dec(&qd_lru_count);
  				}
  				atomic_inc(&qd->qd_count);
b3b94faa5   David Teigland   [GFS2] The core o...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  				found = 1;
  				break;
  			}
  		}
  
  		if (!found)
  			qd = NULL;
  
  		if (!qd && new_qd) {
  			qd = new_qd;
  			list_add(&qd->qd_list, &sdp->sd_quota_list);
  			atomic_inc(&sdp->sd_quota_count);
  			new_qd = NULL;
  		}
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
187
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
188

6a6ada81e   Steven Whitehouse   GFS2: Remove cons...
189
  		if (qd) {
b3b94faa5   David Teigland   [GFS2] The core o...
190
  			if (new_qd) {
f057f6cdf   Steven Whitehouse   GFS2: Merge lock_...
191
  				gfs2_glock_put(new_qd->qd_gl);
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
192
  				kmem_cache_free(gfs2_quotad_cachep, new_qd);
b3b94faa5   David Teigland   [GFS2] The core o...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  			}
  			*qdp = qd;
  			return 0;
  		}
  
  		error = qd_alloc(sdp, user, id, &new_qd);
  		if (error)
  			return error;
  	}
  }
  
  static void qd_hold(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
207
208
  	gfs2_assert(sdp, atomic_read(&qd->qd_count));
  	atomic_inc(&qd->qd_count);
b3b94faa5   David Teigland   [GFS2] The core o...
209
210
211
212
  }
  
  static void qd_put(struct gfs2_quota_data *qd)
  {
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
213
214
215
216
217
218
  	if (atomic_dec_and_lock(&qd->qd_count, &qd_lru_lock)) {
  		/* Add to the reclaim list */
  		list_add_tail(&qd->qd_reclaim, &qd_lru_list);
  		atomic_inc(&qd_lru_count);
  		spin_unlock(&qd_lru_lock);
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
219
220
221
222
223
224
225
  }
  
  static int slot_get(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
  	unsigned int c, o = 0, b;
  	unsigned char byte = 0;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
226
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
227
228
  
  	if (qd->qd_slot_count++) {
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
229
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
230
231
232
233
234
235
236
237
238
239
240
  		return 0;
  	}
  
  	for (c = 0; c < sdp->sd_quota_chunks; c++)
  		for (o = 0; o < PAGE_SIZE; o++) {
  			byte = sdp->sd_quota_bitmap[c][o];
  			if (byte != 0xFF)
  				goto found;
  		}
  
  	goto fail;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
241
  found:
b3b94faa5   David Teigland   [GFS2] The core o...
242
243
244
245
246
247
248
249
250
  	for (b = 0; b < 8; b++)
  		if (!(byte & (1 << b)))
  			break;
  	qd->qd_slot = c * (8 * PAGE_SIZE) + o * 8 + b;
  
  	if (qd->qd_slot >= sdp->sd_quota_slots)
  		goto fail;
  
  	sdp->sd_quota_bitmap[c][o] |= 1 << b;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
251
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
252
253
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
254
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
255
  	qd->qd_slot_count--;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
256
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
257
258
259
260
261
262
  	return -ENOSPC;
  }
  
  static void slot_hold(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
263
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
264
265
  	gfs2_assert(sdp, qd->qd_slot_count);
  	qd->qd_slot_count++;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
266
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
267
268
269
270
271
  }
  
  static void slot_put(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
272
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
273
274
275
276
277
  	gfs2_assert(sdp, qd->qd_slot_count);
  	if (!--qd->qd_slot_count) {
  		gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, qd->qd_slot, 0);
  		qd->qd_slot = -1;
  	}
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
278
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
279
280
281
282
283
  }
  
  static int bh_get(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
284
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
285
  	unsigned int block, offset;
b3b94faa5   David Teigland   [GFS2] The core o...
286
287
  	struct buffer_head *bh;
  	int error;
23591256d   Steven Whitehouse   [GFS2] Fix bmap t...
288
  	struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
b3b94faa5   David Teigland   [GFS2] The core o...
289

f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
290
  	mutex_lock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
291
292
  
  	if (qd->qd_bh_count++) {
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
293
  		mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
294
295
296
297
  		return 0;
  	}
  
  	block = qd->qd_slot / sdp->sd_qc_per_block;
0d0868bde   Bob Peterson   [GFS2] Get rid of...
298
  	offset = qd->qd_slot % sdp->sd_qc_per_block;
b3b94faa5   David Teigland   [GFS2] The core o...
299

23591256d   Steven Whitehouse   [GFS2] Fix bmap t...
300
  	bh_map.b_size = 1 << ip->i_inode.i_blkbits;
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
301
  	error = gfs2_block_map(&ip->i_inode, block, &bh_map, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
302
303
  	if (error)
  		goto fail;
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
304
  	error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh);
b3b94faa5   David Teigland   [GFS2] The core o...
305
306
307
308
309
310
311
312
313
314
  	if (error)
  		goto fail;
  	error = -EIO;
  	if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_QC))
  		goto fail_brelse;
  
  	qd->qd_bh = bh;
  	qd->qd_bh_qc = (struct gfs2_quota_change *)
  		(bh->b_data + sizeof(struct gfs2_meta_header) +
  		 offset * sizeof(struct gfs2_quota_change));
2e95b6653   Josef Whiter   [GFS2] fix lockin...
315
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
316
317
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
318
  fail_brelse:
b3b94faa5   David Teigland   [GFS2] The core o...
319
  	brelse(bh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
320
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
321
  	qd->qd_bh_count--;
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
322
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
323
324
325
326
327
328
  	return error;
  }
  
  static void bh_put(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
329
  	mutex_lock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
330
331
332
333
334
335
  	gfs2_assert(sdp, qd->qd_bh_count);
  	if (!--qd->qd_bh_count) {
  		brelse(qd->qd_bh);
  		qd->qd_bh = NULL;
  		qd->qd_bh_qc = NULL;
  	}
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
336
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
337
338
339
340
341
342
343
344
345
346
347
348
  }
  
  static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp)
  {
  	struct gfs2_quota_data *qd = NULL;
  	int error;
  	int found = 0;
  
  	*qdp = NULL;
  
  	if (sdp->sd_vfs->s_flags & MS_RDONLY)
  		return 0;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
349
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
350
351
352
353
354
355
356
357
358
359
  
  	list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
  		if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
  		    !test_bit(QDF_CHANGE, &qd->qd_flags) ||
  		    qd->qd_sync_gen >= sdp->sd_quota_sync_gen)
  			continue;
  
  		list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
  
  		set_bit(QDF_LOCKED, &qd->qd_flags);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
360
361
  		gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
  		atomic_inc(&qd->qd_count);
b3b94faa5   David Teigland   [GFS2] The core o...
362
363
364
365
366
367
368
369
370
371
  		qd->qd_change_sync = qd->qd_change;
  		gfs2_assert_warn(sdp, qd->qd_slot_count);
  		qd->qd_slot_count++;
  		found = 1;
  
  		break;
  	}
  
  	if (!found)
  		qd = NULL;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
372
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
  
  	if (qd) {
  		gfs2_assert_warn(sdp, qd->qd_change_sync);
  		error = bh_get(qd);
  		if (error) {
  			clear_bit(QDF_LOCKED, &qd->qd_flags);
  			slot_put(qd);
  			qd_put(qd);
  			return error;
  		}
  	}
  
  	*qdp = qd;
  
  	return 0;
  }
  
  static int qd_trylock(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
  
  	if (sdp->sd_vfs->s_flags & MS_RDONLY)
  		return 0;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
396
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
397
398
399
  
  	if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
  	    !test_bit(QDF_CHANGE, &qd->qd_flags)) {
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
400
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
401
402
403
404
405
406
  		return 0;
  	}
  
  	list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
  
  	set_bit(QDF_LOCKED, &qd->qd_flags);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
407
408
  	gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
  	atomic_inc(&qd->qd_count);
b3b94faa5   David Teigland   [GFS2] The core o...
409
410
411
  	qd->qd_change_sync = qd->qd_change;
  	gfs2_assert_warn(sdp, qd->qd_slot_count);
  	qd->qd_slot_count++;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
412
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  
  	gfs2_assert_warn(sdp, qd->qd_change_sync);
  	if (bh_get(qd)) {
  		clear_bit(QDF_LOCKED, &qd->qd_flags);
  		slot_put(qd);
  		qd_put(qd);
  		return 0;
  	}
  
  	return 1;
  }
  
  static void qd_unlock(struct gfs2_quota_data *qd)
  {
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
427
428
  	gfs2_assert_warn(qd->qd_gl->gl_sbd,
  			 test_bit(QDF_LOCKED, &qd->qd_flags));
b3b94faa5   David Teigland   [GFS2] The core o...
429
430
431
432
433
  	clear_bit(QDF_LOCKED, &qd->qd_flags);
  	bh_put(qd);
  	slot_put(qd);
  	qd_put(qd);
  }
33a82529e   Steven Whitehouse   GFS2: Remove cons...
434
  static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id,
b3b94faa5   David Teigland   [GFS2] The core o...
435
436
437
  		    struct gfs2_quota_data **qdp)
  {
  	int error;
6a6ada81e   Steven Whitehouse   GFS2: Remove cons...
438
  	error = qd_get(sdp, user, id, qdp);
b3b94faa5   David Teigland   [GFS2] The core o...
439
440
441
442
443
444
445
446
447
448
449
450
  	if (error)
  		return error;
  
  	error = slot_get(*qdp);
  	if (error)
  		goto fail;
  
  	error = bh_get(*qdp);
  	if (error)
  		goto fail_slot;
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
451
  fail_slot:
b3b94faa5   David Teigland   [GFS2] The core o...
452
  	slot_put(*qdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
453
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
454
455
456
457
458
459
460
461
462
463
  	qd_put(*qdp);
  	return error;
  }
  
  static void qdsb_put(struct gfs2_quota_data *qd)
  {
  	bh_put(qd);
  	slot_put(qd);
  	qd_put(qd);
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
464
  int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
465
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
466
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
564e12b11   Bob Peterson   GFS2: decouple qu...
467
468
  	struct gfs2_qadata *qa = ip->i_qadata;
  	struct gfs2_quota_data **qd = qa->qa_qd;
b3b94faa5   David Teigland   [GFS2] The core o...
469
  	int error;
564e12b11   Bob Peterson   GFS2: decouple qu...
470
  	if (gfs2_assert_warn(sdp, !qa->qa_qd_num) ||
b3b94faa5   David Teigland   [GFS2] The core o...
471
472
473
474
475
  	    gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)))
  		return -EIO;
  
  	if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
  		return 0;
33a82529e   Steven Whitehouse   GFS2: Remove cons...
476
  	error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
477
478
  	if (error)
  		goto out;
564e12b11   Bob Peterson   GFS2: decouple qu...
479
  	qa->qa_qd_num++;
b3b94faa5   David Teigland   [GFS2] The core o...
480
  	qd++;
33a82529e   Steven Whitehouse   GFS2: Remove cons...
481
  	error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
482
483
  	if (error)
  		goto out;
564e12b11   Bob Peterson   GFS2: decouple qu...
484
  	qa->qa_qd_num++;
b3b94faa5   David Teigland   [GFS2] The core o...
485
  	qd++;
2933f9254   Steven Whitehouse   [GFS2] Shrink gfs...
486
  	if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) {
33a82529e   Steven Whitehouse   GFS2: Remove cons...
487
  		error = qdsb_get(sdp, QUOTA_USER, uid, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
488
489
  		if (error)
  			goto out;
564e12b11   Bob Peterson   GFS2: decouple qu...
490
  		qa->qa_qd_num++;
b3b94faa5   David Teigland   [GFS2] The core o...
491
492
  		qd++;
  	}
2933f9254   Steven Whitehouse   [GFS2] Shrink gfs...
493
  	if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) {
33a82529e   Steven Whitehouse   GFS2: Remove cons...
494
  		error = qdsb_get(sdp, QUOTA_GROUP, gid, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
495
496
  		if (error)
  			goto out;
564e12b11   Bob Peterson   GFS2: decouple qu...
497
  		qa->qa_qd_num++;
b3b94faa5   David Teigland   [GFS2] The core o...
498
499
  		qd++;
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
500
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
501
502
  	if (error)
  		gfs2_quota_unhold(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
503
504
505
506
507
  	return error;
  }
  
  void gfs2_quota_unhold(struct gfs2_inode *ip)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
508
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
564e12b11   Bob Peterson   GFS2: decouple qu...
509
  	struct gfs2_qadata *qa = ip->i_qadata;
b3b94faa5   David Teigland   [GFS2] The core o...
510
511
512
  	unsigned int x;
  
  	gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags));
564e12b11   Bob Peterson   GFS2: decouple qu...
513
514
515
  	for (x = 0; x < qa->qa_qd_num; x++) {
  		qdsb_put(qa->qa_qd[x]);
  		qa->qa_qd[x] = NULL;
b3b94faa5   David Teigland   [GFS2] The core o...
516
  	}
564e12b11   Bob Peterson   GFS2: decouple qu...
517
  	qa->qa_qd_num = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
518
519
520
521
  }
  
  static int sort_qd(const void *a, const void *b)
  {
48fac1790   Steven Whitehouse   [GFS2] Remove unu...
522
523
  	const struct gfs2_quota_data *qd_a = *(const struct gfs2_quota_data **)a;
  	const struct gfs2_quota_data *qd_b = *(const struct gfs2_quota_data **)b;
b3b94faa5   David Teigland   [GFS2] The core o...
524
525
526
527
  
  	if (!test_bit(QDF_USER, &qd_a->qd_flags) !=
  	    !test_bit(QDF_USER, &qd_b->qd_flags)) {
  		if (test_bit(QDF_USER, &qd_a->qd_flags))
48fac1790   Steven Whitehouse   [GFS2] Remove unu...
528
  			return -1;
b3b94faa5   David Teigland   [GFS2] The core o...
529
  		else
48fac1790   Steven Whitehouse   [GFS2] Remove unu...
530
  			return 1;
b3b94faa5   David Teigland   [GFS2] The core o...
531
  	}
48fac1790   Steven Whitehouse   [GFS2] Remove unu...
532
533
534
535
  	if (qd_a->qd_id < qd_b->qd_id)
  		return -1;
  	if (qd_a->qd_id > qd_b->qd_id)
  		return 1;
b3b94faa5   David Teigland   [GFS2] The core o...
536

48fac1790   Steven Whitehouse   [GFS2] Remove unu...
537
  	return 0;
b3b94faa5   David Teigland   [GFS2] The core o...
538
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
539
  static void do_qc(struct gfs2_quota_data *qd, s64 change)
b3b94faa5   David Teigland   [GFS2] The core o...
540
541
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
542
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
543
  	struct gfs2_quota_change *qc = qd->qd_bh_qc;
cd915493f   Steven Whitehouse   [GFS2] Change all...
544
  	s64 x;
b3b94faa5   David Teigland   [GFS2] The core o...
545

f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
546
  	mutex_lock(&sdp->sd_quota_mutex);
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
547
  	gfs2_trans_add_bh(ip->i_gl, qd->qd_bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
548
549
550
551
552
553
554
555
  
  	if (!test_bit(QDF_CHANGE, &qd->qd_flags)) {
  		qc->qc_change = 0;
  		qc->qc_flags = 0;
  		if (test_bit(QDF_USER, &qd->qd_flags))
  			qc->qc_flags = cpu_to_be32(GFS2_QCF_USER);
  		qc->qc_id = cpu_to_be32(qd->qd_id);
  	}
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
556
  	x = be64_to_cpu(qc->qc_change) + change;
b3b94faa5   David Teigland   [GFS2] The core o...
557
  	qc->qc_change = cpu_to_be64(x);
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
558
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
559
  	qd->qd_change = x;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
560
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
561
562
563
564
565
566
567
568
569
570
571
572
  
  	if (!x) {
  		gfs2_assert_warn(sdp, test_bit(QDF_CHANGE, &qd->qd_flags));
  		clear_bit(QDF_CHANGE, &qd->qd_flags);
  		qc->qc_flags = 0;
  		qc->qc_id = 0;
  		slot_put(qd);
  		qd_put(qd);
  	} else if (!test_and_set_bit(QDF_CHANGE, &qd->qd_flags)) {
  		qd_hold(qd);
  		slot_hold(qd);
  	}
907b9bceb   Steven Whitehouse   [GFS2/DLM] Fix tr...
573

f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
574
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
575
  }
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
576
  /**
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
577
578
579
   * gfs2_adjust_quota - adjust record of current block usage
   * @ip: The quota inode
   * @loc: Offset of the entry in the quota file
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
580
   * @change: The amount of usage change to record
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
581
   * @qd: The quota data
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
582
   * @fdq: The updated limits to record
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
583
584
585
   *
   * This function was mostly borrowed from gfs2_block_truncate_page which was
   * in turn mostly borrowed from ext3
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
586
587
   *
   * Returns: 0 or -ve on error
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
588
   */
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
589

18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
590
  static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
591
592
  			     s64 change, struct gfs2_quota_data *qd,
  			     struct fs_disk_quota *fdq)
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
593
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
594
  	struct inode *inode = &ip->i_inode;
14870b457   Abhijith Das   GFS2: Userland ex...
595
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
596
597
  	struct address_space *mapping = inode->i_mapping;
  	unsigned long index = loc >> PAGE_CACHE_SHIFT;
1990e9176   Abhijith Das   [GFS2] Quotas non...
598
  	unsigned offset = loc & (PAGE_CACHE_SIZE - 1);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
599
  	unsigned blocksize, iblock, pos;
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
600
  	struct buffer_head *bh;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
601
  	struct page *page;
7e619bc3e   Abhijith Das   GFS2: Fix writing...
602
603
604
  	void *kaddr, *ptr;
  	struct gfs2_quota q, *qp;
  	int err, nbytes;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
605
  	u64 size;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
606

891a8e933   Steven Whitehouse   GFS2: Misc fixes
607
608
609
610
611
  	if (gfs2_is_stuffed(ip)) {
  		err = gfs2_unstuff_dinode(ip, NULL);
  		if (err)
  			return err;
  	}
7e619bc3e   Abhijith Das   GFS2: Fix writing...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
  
  	memset(&q, 0, sizeof(struct gfs2_quota));
  	err = gfs2_internal_read(ip, NULL, (char *)&q, &loc, sizeof(q));
  	if (err < 0)
  		return err;
  
  	err = -EIO;
  	qp = &q;
  	qp->qu_value = be64_to_cpu(qp->qu_value);
  	qp->qu_value += change;
  	qp->qu_value = cpu_to_be64(qp->qu_value);
  	qd->qd_qb.qb_value = qp->qu_value;
  	if (fdq) {
  		if (fdq->d_fieldmask & FS_DQ_BSOFT) {
14870b457   Abhijith Das   GFS2: Userland ex...
626
  			qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
627
628
629
  			qd->qd_qb.qb_warn = qp->qu_warn;
  		}
  		if (fdq->d_fieldmask & FS_DQ_BHARD) {
14870b457   Abhijith Das   GFS2: Userland ex...
630
  			qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
631
632
  			qd->qd_qb.qb_limit = qp->qu_limit;
  		}
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
633
634
635
636
  		if (fdq->d_fieldmask & FS_DQ_BCOUNT) {
  			qp->qu_value = cpu_to_be64(fdq->d_bcount >> sdp->sd_fsb2bb_shift);
  			qd->qd_qb.qb_value = qp->qu_value;
  		}
7e619bc3e   Abhijith Das   GFS2: Fix writing...
637
638
639
640
641
642
  	}
  
  	/* Write the quota into the quota file on disk */
  	ptr = qp;
  	nbytes = sizeof(struct gfs2_quota);
  get_a_page:
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
  	page = grab_cache_page(mapping, index);
  	if (!page)
  		return -ENOMEM;
  
  	blocksize = inode->i_sb->s_blocksize;
  	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
  
  	if (!page_has_buffers(page))
  		create_empty_buffers(page, blocksize, 0);
  
  	bh = page_buffers(page);
  	pos = blocksize;
  	while (offset >= pos) {
  		bh = bh->b_this_page;
  		iblock++;
  		pos += blocksize;
  	}
  
  	if (!buffer_mapped(bh)) {
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
662
  		gfs2_block_map(inode, iblock, bh, 1);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
663
  		if (!buffer_mapped(bh))
7e619bc3e   Abhijith Das   GFS2: Fix writing...
664
665
  			goto unlock_out;
  		/* If it's a newly allocated disk block for quota, zero it */
8b4216018   Abhijith Das   GFS2: BUG in gfs2...
666
667
  		if (buffer_new(bh))
  			zero_user(page, pos - blocksize, bh->b_size);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
668
669
670
671
672
673
  	}
  
  	if (PageUptodate(page))
  		set_buffer_uptodate(bh);
  
  	if (!buffer_uptodate(bh)) {
20ed0535d   Steven Whitehouse   GFS2: Fix up REQ ...
674
  		ll_rw_block(READ | REQ_META, 1, &bh);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
675
676
  		wait_on_buffer(bh);
  		if (!buffer_uptodate(bh))
7e619bc3e   Abhijith Das   GFS2: Fix writing...
677
  			goto unlock_out;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
678
679
680
681
682
  	}
  
  	gfs2_trans_add_bh(ip->i_gl, bh, 0);
  
  	kaddr = kmap_atomic(page, KM_USER0);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
683
684
685
  	if (offset + sizeof(struct gfs2_quota) > PAGE_CACHE_SIZE)
  		nbytes = PAGE_CACHE_SIZE - offset;
  	memcpy(kaddr + offset, ptr, nbytes);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
686
687
  	flush_dcache_page(page);
  	kunmap_atomic(kaddr, KM_USER0);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
688
689
690
691
692
  	unlock_page(page);
  	page_cache_release(page);
  
  	/* If quota straddles page boundary, we need to update the rest of the
  	 * quota at the beginning of the next page */
8b4216018   Abhijith Das   GFS2: BUG in gfs2...
693
  	if ((offset + sizeof(struct gfs2_quota)) > PAGE_CACHE_SIZE) {
7e619bc3e   Abhijith Das   GFS2: Fix writing...
694
695
696
697
698
699
  		ptr = ptr + nbytes;
  		nbytes = sizeof(struct gfs2_quota) - nbytes;
  		offset = 0;
  		index++;
  		goto get_a_page;
  	}
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
700

e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
701
  	size = loc + sizeof(struct gfs2_quota);
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
702
  	if (size > inode->i_size)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
703
  		i_size_write(inode, size);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
704
  	inode->i_mtime = inode->i_atime = CURRENT_TIME;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
705
  	mark_inode_dirty(inode);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
706
  	return err;
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
707

7e619bc3e   Abhijith Das   GFS2: Fix writing...
708
  unlock_out:
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
709
710
711
712
  	unlock_page(page);
  	page_cache_release(page);
  	return err;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
713
714
715
  static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
  {
  	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_sbd;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
716
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
717
718
719
720
  	unsigned int data_blocks, ind_blocks;
  	struct gfs2_holder *ghs, i_gh;
  	unsigned int qx, x;
  	struct gfs2_quota_data *qd;
f42faf4fa   Steven Whitehouse   [GFS2] Add gfs2_i...
721
  	loff_t offset;
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
722
  	unsigned int nalloc = 0, blocks;
b3b94faa5   David Teigland   [GFS2] The core o...
723
724
725
726
  	int error;
  
  	gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
  			      &data_blocks, &ind_blocks);
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
727
  	ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
728
729
730
731
  	if (!ghs)
  		return -ENOMEM;
  
  	sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
732
  	mutex_lock_nested(&ip->i_inode.i_mutex, I_MUTEX_QUOTA);
b3b94faa5   David Teigland   [GFS2] The core o...
733
  	for (qx = 0; qx < num_qd; qx++) {
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
734
  		error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE,
b3b94faa5   David Teigland   [GFS2] The core o...
735
736
737
738
739
740
741
742
743
744
  					   GL_NOCACHE, &ghs[qx]);
  		if (error)
  			goto out;
  	}
  
  	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
  	if (error)
  		goto out;
  
  	for (x = 0; x < num_qd; x++) {
b3b94faa5   David Teigland   [GFS2] The core o...
745
  		offset = qd2offset(qda[x]);
461cb419f   Bob Peterson   GFS2: Simplify gf...
746
747
  		if (gfs2_write_alloc_required(ip, offset,
  					      sizeof(struct gfs2_quota)))
b3b94faa5   David Teigland   [GFS2] The core o...
748
749
  			nalloc++;
  	}
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
750
751
752
753
754
755
  	/* 
  	 * 1 blk for unstuffing inode if stuffed. We add this extra
  	 * block to the reservation unconditionally. If the inode
  	 * doesn't need unstuffing, the block will be released to the 
  	 * rgrp since it won't be allocated during the transaction
  	 */
7e619bc3e   Abhijith Das   GFS2: Fix writing...
756
757
758
759
  	/* +3 in the end for unstuffing block, inode size update block
  	 * and another block in case quota straddles page boundary and 
  	 * two blocks need to be updated instead of 1 */
  	blocks = num_qd * data_blocks + RES_DINODE + num_qd + 3;
b3b94faa5   David Teigland   [GFS2] The core o...
760

564e12b11   Bob Peterson   GFS2: decouple qu...
761
762
  	error = gfs2_inplace_reserve(ip, 1 +
  				     (nalloc * (data_blocks + ind_blocks)));
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
763
764
  	if (error)
  		goto out_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
765

20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
766
  	if (nalloc)
54335b1fc   Steven Whitehouse   GFS2: Cache the m...
767
  		blocks += gfs2_rg_blocks(ip) + nalloc * ind_blocks + RES_STATFS;
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
768
769
770
771
  
  	error = gfs2_trans_begin(sdp, blocks, 0);
  	if (error)
  		goto out_ipres;
b3b94faa5   David Teigland   [GFS2] The core o...
772
773
  
  	for (x = 0; x < num_qd; x++) {
b3b94faa5   David Teigland   [GFS2] The core o...
774
775
  		qd = qda[x];
  		offset = qd2offset(qd);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
776
  		error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, qd, NULL);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
777
  		if (error)
b3b94faa5   David Teigland   [GFS2] The core o...
778
  			goto out_end_trans;
b3b94faa5   David Teigland   [GFS2] The core o...
779
780
  
  		do_qc(qd, -qd->qd_change_sync);
662e3a551   Abhijith Das   GFS2: quota allow...
781
  		set_bit(QDF_REFRESH, &qd->qd_flags);
b3b94faa5   David Teigland   [GFS2] The core o...
782
783
784
  	}
  
  	error = 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
785
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
786
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
787
  out_ipres:
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
788
  	gfs2_inplace_release(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
789
  out_alloc:
b3b94faa5   David Teigland   [GFS2] The core o...
790
  	gfs2_glock_dq_uninit(&i_gh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
791
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
792
793
  	while (qx--)
  		gfs2_glock_dq_uninit(&ghs[qx]);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
794
  	mutex_unlock(&ip->i_inode.i_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
795
  	kfree(ghs);
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
796
  	gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
b3b94faa5   David Teigland   [GFS2] The core o...
797
798
  	return error;
  }
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
  {
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
  	struct gfs2_quota q;
  	struct gfs2_quota_lvb *qlvb;
  	loff_t pos;
  	int error;
  
  	memset(&q, 0, sizeof(struct gfs2_quota));
  	pos = qd2offset(qd);
  	error = gfs2_internal_read(ip, NULL, (char *)&q, &pos, sizeof(q));
  	if (error < 0)
  		return error;
  
  	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
  	qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC);
  	qlvb->__pad = 0;
  	qlvb->qb_limit = q.qu_limit;
  	qlvb->qb_warn = q.qu_warn;
  	qlvb->qb_value = q.qu_value;
  	qd->qd_qb = *qlvb;
  
  	return 0;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
823
824
825
826
  static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
  		    struct gfs2_holder *q_gh)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
827
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
828
  	struct gfs2_holder i_gh;
b3b94faa5   David Teigland   [GFS2] The core o...
829
  	int error;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
830
  restart:
b3b94faa5   David Teigland   [GFS2] The core o...
831
832
833
  	error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh);
  	if (error)
  		return error;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
834
  	qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
b3b94faa5   David Teigland   [GFS2] The core o...
835

e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
836
  	if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) {
b3b94faa5   David Teigland   [GFS2] The core o...
837
  		gfs2_glock_dq_uninit(q_gh);
91094d0fb   Steven Whitehouse   GFS2: Remove obso...
838
839
  		error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE,
  					   GL_NOCACHE, q_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
840
841
  		if (error)
  			return error;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
842
  		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
843
844
  		if (error)
  			goto fail;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
845
846
  		error = update_qd(sdp, qd);
  		if (error)
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
847
  			goto fail_gunlock;
b3b94faa5   David Teigland   [GFS2] The core o...
848

e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
849
  		gfs2_glock_dq_uninit(&i_gh);
91094d0fb   Steven Whitehouse   GFS2: Remove obso...
850
851
852
  		gfs2_glock_dq_uninit(q_gh);
  		force_refresh = 0;
  		goto restart;
b3b94faa5   David Teigland   [GFS2] The core o...
853
854
855
  	}
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
856
  fail_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
857
  	gfs2_glock_dq_uninit(&i_gh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
858
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
859
  	gfs2_glock_dq_uninit(q_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
860
861
  	return error;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
862
  int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
863
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
864
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
564e12b11   Bob Peterson   GFS2: decouple qu...
865
  	struct gfs2_qadata *qa = ip->i_qadata;
662e3a551   Abhijith Das   GFS2: quota allow...
866
  	struct gfs2_quota_data *qd;
b3b94faa5   David Teigland   [GFS2] The core o...
867
868
  	unsigned int x;
  	int error = 0;
891a8e933   Steven Whitehouse   GFS2: Misc fixes
869
870
871
  	error = gfs2_quota_hold(ip, uid, gid);
  	if (error)
  		return error;
b3b94faa5   David Teigland   [GFS2] The core o...
872
873
874
875
  
  	if (capable(CAP_SYS_RESOURCE) ||
  	    sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
  		return 0;
564e12b11   Bob Peterson   GFS2: decouple qu...
876
  	sort(qa->qa_qd, qa->qa_qd_num, sizeof(struct gfs2_quota_data *),
b3b94faa5   David Teigland   [GFS2] The core o...
877
  	     sort_qd, NULL);
564e12b11   Bob Peterson   GFS2: decouple qu...
878
  	for (x = 0; x < qa->qa_qd_num; x++) {
662e3a551   Abhijith Das   GFS2: quota allow...
879
  		int force = NO_FORCE;
564e12b11   Bob Peterson   GFS2: decouple qu...
880
  		qd = qa->qa_qd[x];
662e3a551   Abhijith Das   GFS2: quota allow...
881
882
  		if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags))
  			force = FORCE;
564e12b11   Bob Peterson   GFS2: decouple qu...
883
  		error = do_glock(qd, force, &qa->qa_qd_ghs[x]);
b3b94faa5   David Teigland   [GFS2] The core o...
884
885
886
887
888
889
890
891
  		if (error)
  			break;
  	}
  
  	if (!error)
  		set_bit(GIF_QD_LOCKED, &ip->i_flags);
  	else {
  		while (x--)
564e12b11   Bob Peterson   GFS2: decouple qu...
892
  			gfs2_glock_dq_uninit(&qa->qa_qd_ghs[x]);
b3b94faa5   David Teigland   [GFS2] The core o...
893
894
895
896
897
898
899
900
901
902
  		gfs2_quota_unhold(ip);
  	}
  
  	return error;
  }
  
  static int need_sync(struct gfs2_quota_data *qd)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
  	struct gfs2_tune *gt = &sdp->sd_tune;
cd915493f   Steven Whitehouse   [GFS2] Change all...
903
  	s64 value;
b3b94faa5   David Teigland   [GFS2] The core o...
904
905
906
907
908
  	unsigned int num, den;
  	int do_sync = 1;
  
  	if (!qd->qd_qb.qb_limit)
  		return 0;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
909
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
910
  	value = qd->qd_change;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
911
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
912
913
914
915
916
917
918
919
  
  	spin_lock(&gt->gt_spin);
  	num = gt->gt_quota_scale_num;
  	den = gt->gt_quota_scale_den;
  	spin_unlock(&gt->gt_spin);
  
  	if (value < 0)
  		do_sync = 0;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
920
921
  	else if ((s64)be64_to_cpu(qd->qd_qb.qb_value) >=
  		 (s64)be64_to_cpu(qd->qd_qb.qb_limit))
b3b94faa5   David Teigland   [GFS2] The core o...
922
923
924
  		do_sync = 0;
  	else {
  		value *= gfs2_jindex_size(sdp) * num;
4abaca17e   David Howells   [GFS2] Fix GFS2's...
925
  		value = div_s64(value, den);
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
926
  		value += (s64)be64_to_cpu(qd->qd_qb.qb_value);
cd915493f   Steven Whitehouse   [GFS2] Change all...
927
  		if (value < (s64)be64_to_cpu(qd->qd_qb.qb_limit))
b3b94faa5   David Teigland   [GFS2] The core o...
928
929
930
931
932
933
934
935
  			do_sync = 0;
  	}
  
  	return do_sync;
  }
  
  void gfs2_quota_unlock(struct gfs2_inode *ip)
  {
564e12b11   Bob Peterson   GFS2: decouple qu...
936
  	struct gfs2_qadata *qa = ip->i_qadata;
b3b94faa5   David Teigland   [GFS2] The core o...
937
938
939
940
941
942
  	struct gfs2_quota_data *qda[4];
  	unsigned int count = 0;
  	unsigned int x;
  
  	if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags))
  		goto out;
564e12b11   Bob Peterson   GFS2: decouple qu...
943
  	for (x = 0; x < qa->qa_qd_num; x++) {
b3b94faa5   David Teigland   [GFS2] The core o...
944
945
  		struct gfs2_quota_data *qd;
  		int sync;
564e12b11   Bob Peterson   GFS2: decouple qu...
946
  		qd = qa->qa_qd[x];
b3b94faa5   David Teigland   [GFS2] The core o...
947
  		sync = need_sync(qd);
564e12b11   Bob Peterson   GFS2: decouple qu...
948
  		gfs2_glock_dq_uninit(&qa->qa_qd_ghs[x]);
b3b94faa5   David Teigland   [GFS2] The core o...
949
950
951
952
953
954
955
956
957
958
  
  		if (sync && qd_trylock(qd))
  			qda[count++] = qd;
  	}
  
  	if (count) {
  		do_sync(count, qda);
  		for (x = 0; x < count; x++)
  			qd_unlock(qda[x]);
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
959
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
960
961
962
963
964
965
966
967
  	gfs2_quota_unhold(ip);
  }
  
  #define MAX_LINE 256
  
  static int print_message(struct gfs2_quota_data *qd, char *type)
  {
  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
b3b94faa5   David Teigland   [GFS2] The core o...
968

2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
969
970
  	printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u
  ",
02630a12c   Steven Whitehouse   [GFS2] Remove dep...
971
972
973
  	       sdp->sd_fsname, type,
  	       (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group",
  	       qd->qd_id);
b3b94faa5   David Teigland   [GFS2] The core o...
974
975
976
  
  	return 0;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
977
  int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
978
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
979
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
564e12b11   Bob Peterson   GFS2: decouple qu...
980
  	struct gfs2_qadata *qa = ip->i_qadata;
b3b94faa5   David Teigland   [GFS2] The core o...
981
  	struct gfs2_quota_data *qd;
cd915493f   Steven Whitehouse   [GFS2] Change all...
982
  	s64 value;
b3b94faa5   David Teigland   [GFS2] The core o...
983
984
985
986
987
988
989
990
  	unsigned int x;
  	int error = 0;
  
  	if (!test_bit(GIF_QD_LOCKED, &ip->i_flags))
  		return 0;
  
          if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
                  return 0;
564e12b11   Bob Peterson   GFS2: decouple qu...
991
992
  	for (x = 0; x < qa->qa_qd_num; x++) {
  		qd = qa->qa_qd[x];
b3b94faa5   David Teigland   [GFS2] The core o...
993
994
995
996
  
  		if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
  		      (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))))
  			continue;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
997
  		value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
998
  		spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
999
  		value += qd->qd_change;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
1000
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1001

cd915493f   Steven Whitehouse   [GFS2] Change all...
1002
  		if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {
b3b94faa5   David Teigland   [GFS2] The core o...
1003
  			print_message(qd, "exceeded");
2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
1004
1005
1006
  			quota_send_warning(test_bit(QDF_USER, &qd->qd_flags) ?
  					   USRQUOTA : GRPQUOTA, qd->qd_id,
  					   sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN);
b3b94faa5   David Teigland   [GFS2] The core o...
1007
1008
  			error = -EDQUOT;
  			break;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
1009
  		} else if (be64_to_cpu(qd->qd_qb.qb_warn) &&
cd915493f   Steven Whitehouse   [GFS2] Change all...
1010
  			   (s64)be64_to_cpu(qd->qd_qb.qb_warn) < value &&
b3b94faa5   David Teigland   [GFS2] The core o...
1011
  			   time_after_eq(jiffies, qd->qd_last_warn +
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
1012
1013
  					 gfs2_tune_get(sdp,
  						gt_quota_warn_period) * HZ)) {
2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
1014
1015
1016
  			quota_send_warning(test_bit(QDF_USER, &qd->qd_flags) ?
  					   USRQUOTA : GRPQUOTA, qd->qd_id,
  					   sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);
b3b94faa5   David Teigland   [GFS2] The core o...
1017
1018
1019
1020
1021
1022
1023
  			error = print_message(qd, "warning");
  			qd->qd_last_warn = jiffies;
  		}
  	}
  
  	return error;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
1024
1025
  void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
  		       u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
1026
  {
564e12b11   Bob Peterson   GFS2: decouple qu...
1027
  	struct gfs2_qadata *qa = ip->i_qadata;
b3b94faa5   David Teigland   [GFS2] The core o...
1028
1029
  	struct gfs2_quota_data *qd;
  	unsigned int x;
b3b94faa5   David Teigland   [GFS2] The core o...
1030

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1031
  	if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
b3b94faa5   David Teigland   [GFS2] The core o...
1032
  		return;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
1033
  	if (ip->i_diskflags & GFS2_DIF_SYSTEM)
b3b94faa5   David Teigland   [GFS2] The core o...
1034
  		return;
564e12b11   Bob Peterson   GFS2: decouple qu...
1035
1036
  	for (x = 0; x < qa->qa_qd_num; x++) {
  		qd = qa->qa_qd[x];
b3b94faa5   David Teigland   [GFS2] The core o...
1037
1038
1039
1040
  
  		if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
  		    (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) {
  			do_qc(qd, change);
b3b94faa5   David Teigland   [GFS2] The core o...
1041
1042
1043
  		}
  	}
  }
5fb324ad2   Christoph Hellwig   quota: move code ...
1044
  int gfs2_quota_sync(struct super_block *sb, int type, int wait)
b3b94faa5   David Teigland   [GFS2] The core o...
1045
  {
8c42d637f   Steven Whitehouse   GFS2: Alter argum...
1046
  	struct gfs2_sbd *sdp = sb->s_fs_info;
b3b94faa5   David Teigland   [GFS2] The core o...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
  	struct gfs2_quota_data **qda;
  	unsigned int max_qd = gfs2_tune_get(sdp, gt_quota_simul_sync);
  	unsigned int num_qd;
  	unsigned int x;
  	int error = 0;
  
  	sdp->sd_quota_sync_gen++;
  
  	qda = kcalloc(max_qd, sizeof(struct gfs2_quota_data *), GFP_KERNEL);
  	if (!qda)
  		return -ENOMEM;
  
  	do {
  		num_qd = 0;
  
  		for (;;) {
  			error = qd_fish(sdp, qda + num_qd);
  			if (error || !qda[num_qd])
  				break;
  			if (++num_qd == max_qd)
  				break;
  		}
  
  		if (num_qd) {
  			if (!error)
  				error = do_sync(num_qd, qda);
  			if (!error)
  				for (x = 0; x < num_qd; x++)
  					qda[x]->qd_sync_gen =
  						sdp->sd_quota_sync_gen;
  
  			for (x = 0; x < num_qd; x++)
  				qd_unlock(qda[x]);
  		}
  	} while (!error && num_qd == max_qd);
  
  	kfree(qda);
  
  	return error;
  }
5fb324ad2   Christoph Hellwig   quota: move code ...
1087
1088
1089
1090
  static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
  {
  	return gfs2_quota_sync(sb, type, 0);
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
1091
  int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
b3b94faa5   David Teigland   [GFS2] The core o...
1092
1093
1094
1095
  {
  	struct gfs2_quota_data *qd;
  	struct gfs2_holder q_gh;
  	int error;
6a6ada81e   Steven Whitehouse   GFS2: Remove cons...
1096
  	error = qd_get(sdp, user, id, &qd);
b3b94faa5   David Teigland   [GFS2] The core o...
1097
1098
1099
1100
1101
1102
1103
1104
  	if (error)
  		return error;
  
  	error = do_glock(qd, FORCE, &q_gh);
  	if (!error)
  		gfs2_glock_dq_uninit(&q_gh);
  
  	qd_put(qd);
b3b94faa5   David Teigland   [GFS2] The core o...
1105
1106
  	return error;
  }
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
1107
1108
1109
1110
1111
1112
1113
1114
  static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
  {
  	const struct gfs2_quota_change *str = buf;
  
  	qc->qc_change = be64_to_cpu(str->qc_change);
  	qc->qc_flags = be32_to_cpu(str->qc_flags);
  	qc->qc_id = be32_to_cpu(str->qc_id);
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1115
1116
  int gfs2_quota_init(struct gfs2_sbd *sdp)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1117
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1118
1119
  	u64 size = i_size_read(sdp->sd_qc_inode);
  	unsigned int blocks = size >> sdp->sd_sb.sb_bsize_shift;
b3b94faa5   David Teigland   [GFS2] The core o...
1120
1121
  	unsigned int x, slot = 0;
  	unsigned int found = 0;
cd915493f   Steven Whitehouse   [GFS2] Change all...
1122
1123
  	u64 dblock;
  	u32 extlen = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1124
  	int error;
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1125
  	if (gfs2_check_internal_file_size(sdp->sd_qc_inode, 1, 64 << 20))
907b9bceb   Steven Whitehouse   [GFS2/DLM] Fix tr...
1126
  		return -EIO;
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1127

b3b94faa5   David Teigland   [GFS2] The core o...
1128
  	sdp->sd_quota_slots = blocks * sdp->sd_qc_per_block;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
1129
  	sdp->sd_quota_chunks = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * PAGE_SIZE);
b3b94faa5   David Teigland   [GFS2] The core o...
1130
1131
1132
1133
  
  	error = -ENOMEM;
  
  	sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks,
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
1134
  				       sizeof(unsigned char *), GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
1135
1136
1137
1138
  	if (!sdp->sd_quota_bitmap)
  		return error;
  
  	for (x = 0; x < sdp->sd_quota_chunks; x++) {
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
1139
  		sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
  		if (!sdp->sd_quota_bitmap[x])
  			goto fail;
  	}
  
  	for (x = 0; x < blocks; x++) {
  		struct buffer_head *bh;
  		unsigned int y;
  
  		if (!extlen) {
  			int new = 0;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1150
  			error = gfs2_extent_map(&ip->i_inode, x, &new, &dblock, &extlen);
b3b94faa5   David Teigland   [GFS2] The core o...
1151
1152
1153
  			if (error)
  				goto fail;
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
1154
  		error = -EIO;
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
1155
1156
1157
  		bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
  		if (!bh)
  			goto fail;
b3b94faa5   David Teigland   [GFS2] The core o...
1158
1159
1160
1161
  		if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_QC)) {
  			brelse(bh);
  			goto fail;
  		}
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
1162
  		for (y = 0; y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
b3b94faa5   David Teigland   [GFS2] The core o...
1163
  		     y++, slot++) {
b62f963e1   Al Viro   [GFS2] split and ...
1164
  			struct gfs2_quota_change_host qc;
b3b94faa5   David Teigland   [GFS2] The core o...
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
  			struct gfs2_quota_data *qd;
  
  			gfs2_quota_change_in(&qc, bh->b_data +
  					  sizeof(struct gfs2_meta_header) +
  					  y * sizeof(struct gfs2_quota_change));
  			if (!qc.qc_change)
  				continue;
  
  			error = qd_alloc(sdp, (qc.qc_flags & GFS2_QCF_USER),
  					 qc.qc_id, &qd);
  			if (error) {
  				brelse(bh);
  				goto fail;
  			}
  
  			set_bit(QDF_CHANGE, &qd->qd_flags);
  			qd->qd_change = qc.qc_change;
  			qd->qd_slot = slot;
  			qd->qd_slot_count = 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1184

0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1185
  			spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1186
1187
1188
  			gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, slot, 1);
  			list_add(&qd->qd_list, &sdp->sd_quota_list);
  			atomic_inc(&sdp->sd_quota_count);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1189
  			spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
  
  			found++;
  		}
  
  		brelse(bh);
  		dblock++;
  		extlen--;
  	}
  
  	if (found)
  		fs_info(sdp, "found %u quota changes
  ", found);
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1204
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
1205
1206
1207
  	gfs2_quota_cleanup(sdp);
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1208
1209
1210
1211
1212
  void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
  {
  	struct list_head *head = &sdp->sd_quota_list;
  	struct gfs2_quota_data *qd;
  	unsigned int x;
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1213
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1214
1215
  	while (!list_empty(head)) {
  		qd = list_entry(head->prev, struct gfs2_quota_data, qd_list);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1216
1217
1218
  		if (atomic_read(&qd->qd_count) > 1 ||
  		    (atomic_read(&qd->qd_count) &&
  		     !test_bit(QDF_CHANGE, &qd->qd_flags))) {
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1219
1220
  			list_move(&qd->qd_list, head);
  			spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1221
  			schedule();
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1222
  			spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1223
1224
1225
1226
  			continue;
  		}
  
  		list_del(&qd->qd_list);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1227
1228
1229
1230
1231
  		/* Also remove if this qd exists in the reclaim list */
  		if (!list_empty(&qd->qd_reclaim)) {
  			list_del_init(&qd->qd_reclaim);
  			atomic_dec(&qd_lru_count);
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
1232
  		atomic_dec(&sdp->sd_quota_count);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1233
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1234

0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1235
  		if (!atomic_read(&qd->qd_count)) {
b3b94faa5   David Teigland   [GFS2] The core o...
1236
1237
1238
1239
1240
  			gfs2_assert_warn(sdp, !qd->qd_change);
  			gfs2_assert_warn(sdp, !qd->qd_slot_count);
  		} else
  			gfs2_assert_warn(sdp, qd->qd_slot_count == 1);
  		gfs2_assert_warn(sdp, !qd->qd_bh_count);
f057f6cdf   Steven Whitehouse   GFS2: Merge lock_...
1241
  		gfs2_glock_put(qd->qd_gl);
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1242
  		kmem_cache_free(gfs2_quotad_cachep, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
1243

0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1244
  		spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1245
  	}
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1246
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1247
1248
1249
1250
1251
1252
1253
1254
1255
  
  	gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_quota_count));
  
  	if (sdp->sd_quota_bitmap) {
  		for (x = 0; x < sdp->sd_quota_chunks; x++)
  			kfree(sdp->sd_quota_bitmap[x]);
  		kfree(sdp->sd_quota_bitmap);
  	}
  }
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
  static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error)
  {
  	if (error == 0 || error == -EROFS)
  		return;
  	if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
  		fs_err(sdp, "gfs2_quotad: %s error %d
  ", msg, error);
  }
  
  static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg,
8c42d637f   Steven Whitehouse   GFS2: Alter argum...
1266
  			       int (*fxn)(struct super_block *sb, int type),
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1267
1268
1269
1270
  			       unsigned long t, unsigned long *timeo,
  			       unsigned int *new_timeo)
  {
  	if (t >= *timeo) {
8c42d637f   Steven Whitehouse   GFS2: Alter argum...
1271
  		int error = fxn(sdp->sd_vfs, 0);
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1272
1273
1274
1275
1276
1277
  		quotad_error(sdp, msg, error);
  		*timeo = gfs2_tune_get_i(&sdp->sd_tune, new_timeo) * HZ;
  	} else {
  		*timeo -= t;
  	}
  }
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  static void quotad_check_trunc_list(struct gfs2_sbd *sdp)
  {
  	struct gfs2_inode *ip;
  
  	while(1) {
  		ip = NULL;
  		spin_lock(&sdp->sd_trunc_lock);
  		if (!list_empty(&sdp->sd_trunc_list)) {
  			ip = list_entry(sdp->sd_trunc_list.next,
  					struct gfs2_inode, i_trunc_list);
  			list_del_init(&ip->i_trunc_list);
  		}
  		spin_unlock(&sdp->sd_trunc_lock);
  		if (ip == NULL)
  			return;
  		gfs2_glock_finish_truncate(ip);
  	}
  }
3d3c10f2c   Benjamin Marzinski   GFS2: Improve sta...
1296
1297
1298
1299
1300
1301
  void gfs2_wake_up_statfs(struct gfs2_sbd *sdp) {
  	if (!sdp->sd_statfs_force_sync) {
  		sdp->sd_statfs_force_sync = 1;
  		wake_up(&sdp->sd_quota_wait);
  	}
  }
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
  /**
   * gfs2_quotad - Write cached quota changes into the quota file
   * @sdp: Pointer to GFS2 superblock
   *
   */
  
  int gfs2_quotad(void *data)
  {
  	struct gfs2_sbd *sdp = data;
  	struct gfs2_tune *tune = &sdp->sd_tune;
  	unsigned long statfs_timeo = 0;
  	unsigned long quotad_timeo = 0;
  	unsigned long t = 0;
  	DEFINE_WAIT(wait);
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1316
  	int empty;
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1317
1318
1319
1320
  
  	while (!kthread_should_stop()) {
  
  		/* Update the master statfs file */
3d3c10f2c   Benjamin Marzinski   GFS2: Improve sta...
1321
1322
1323
1324
1325
1326
1327
1328
1329
  		if (sdp->sd_statfs_force_sync) {
  			int error = gfs2_statfs_sync(sdp->sd_vfs, 0);
  			quotad_error(sdp, "statfs", error);
  			statfs_timeo = gfs2_tune_get(sdp, gt_statfs_quantum) * HZ;
  		}
  		else
  			quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t,
  				   	   &statfs_timeo,
  					   &tune->gt_statfs_quantum);
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1330
1331
  
  		/* Update quota file */
5fb324ad2   Christoph Hellwig   quota: move code ...
1332
  		quotad_check_timeo(sdp, "sync", gfs2_quota_sync_timeo, t,
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1333
  				   &quotad_timeo, &tune->gt_quota_quantum);
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1334
1335
  		/* Check for & recover partially truncated inodes */
  		quotad_check_trunc_list(sdp);
a0acae0e8   Tejun Heo   freezer: unexport...
1336
  		try_to_freeze();
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1337
  		t = min(quotad_timeo, statfs_timeo);
7fa5d20d1   Steven Whitehouse   GFS2: Make quotad...
1338
  		prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_INTERRUPTIBLE);
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1339
1340
1341
  		spin_lock(&sdp->sd_trunc_lock);
  		empty = list_empty(&sdp->sd_trunc_list);
  		spin_unlock(&sdp->sd_trunc_lock);
3d3c10f2c   Benjamin Marzinski   GFS2: Improve sta...
1342
  		if (empty && !sdp->sd_statfs_force_sync)
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1343
1344
1345
  			t -= schedule_timeout(t);
  		else
  			t = 0;
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1346
1347
1348
1349
1350
  		finish_wait(&sdp->sd_quota_wait, &wait);
  	}
  
  	return 0;
  }
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
1351
1352
1353
1354
1355
1356
1357
  static int gfs2_quota_get_xstate(struct super_block *sb,
  				 struct fs_quota_stat *fqs)
  {
  	struct gfs2_sbd *sdp = sb->s_fs_info;
  
  	memset(fqs, 0, sizeof(struct fs_quota_stat));
  	fqs->qs_version = FS_QSTAT_VERSION;
ad6bb90f3   Christoph Hellwig   GFS2: fix quota s...
1358
1359
1360
  
  	switch (sdp->sd_args.ar_quota) {
  	case GFS2_QUOTA_ON:
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1361
  		fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD);
ad6bb90f3   Christoph Hellwig   GFS2: fix quota s...
1362
1363
  		/*FALLTHRU*/
  	case GFS2_QUOTA_ACCOUNT:
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1364
  		fqs->qs_flags |= (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT);
ad6bb90f3   Christoph Hellwig   GFS2: fix quota s...
1365
1366
1367
1368
  		break;
  	case GFS2_QUOTA_OFF:
  		break;
  	}
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
1369
1370
1371
1372
1373
1374
1375
1376
1377
  	if (sdp->sd_quota_inode) {
  		fqs->qs_uquota.qfs_ino = GFS2_I(sdp->sd_quota_inode)->i_no_addr;
  		fqs->qs_uquota.qfs_nblks = sdp->sd_quota_inode->i_blocks;
  	}
  	fqs->qs_uquota.qfs_nextents = 1; /* unsupported */
  	fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */
  	fqs->qs_incoredqs = atomic_read(&qd_lru_count);
  	return 0;
  }
b9b2dd36c   Christoph Hellwig   quota: unify ->ge...
1378
1379
  static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id,
  			  struct fs_disk_quota *fdq)
113d6b3c9   Steven Whitehouse   GFS2: Add get_xqu...
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
  {
  	struct gfs2_sbd *sdp = sb->s_fs_info;
  	struct gfs2_quota_lvb *qlvb;
  	struct gfs2_quota_data *qd;
  	struct gfs2_holder q_gh;
  	int error;
  
  	memset(fdq, 0, sizeof(struct fs_disk_quota));
  
  	if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
  		return -ESRCH; /* Crazy XFS error code */
  
  	if (type == USRQUOTA)
  		type = QUOTA_USER;
  	else if (type == GRPQUOTA)
  		type = QUOTA_GROUP;
  	else
  		return -EINVAL;
  
  	error = qd_get(sdp, type, id, &qd);
  	if (error)
  		return error;
  	error = do_glock(qd, FORCE, &q_gh);
  	if (error)
  		goto out;
  
  	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
  	fdq->d_version = FS_DQUOT_VERSION;
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1408
  	fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
113d6b3c9   Steven Whitehouse   GFS2: Add get_xqu...
1409
  	fdq->d_id = id;
14870b457   Abhijith Das   GFS2: Userland ex...
1410
1411
1412
  	fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
  	fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
  	fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
113d6b3c9   Steven Whitehouse   GFS2: Add get_xqu...
1413
1414
1415
1416
1417
1418
  
  	gfs2_glock_dq_uninit(&q_gh);
  out:
  	qd_put(qd);
  	return error;
  }
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1419
  /* GFS2 only supports a subset of the XFS fields */
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
1420
  #define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1421

c472b4327   Christoph Hellwig   quota: unify ->se...
1422
1423
  static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
  			  struct fs_disk_quota *fdq)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1424
1425
1426
1427
1428
1429
1430
1431
  {
  	struct gfs2_sbd *sdp = sb->s_fs_info;
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
  	struct gfs2_quota_data *qd;
  	struct gfs2_holder q_gh, i_gh;
  	unsigned int data_blocks, ind_blocks;
  	unsigned int blocks = 0;
  	int alloc_required;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1432
1433
1434
1435
1436
1437
1438
1439
1440
  	loff_t offset;
  	int error;
  
  	if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
  		return -ESRCH; /* Crazy XFS error code */
  
  	switch(type) {
  	case USRQUOTA:
  		type = QUOTA_USER;
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1441
  		if (fdq->d_flags != FS_USER_QUOTA)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1442
1443
1444
1445
  			return -EINVAL;
  		break;
  	case GRPQUOTA:
  		type = QUOTA_GROUP;
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1446
  		if (fdq->d_flags != FS_GROUP_QUOTA)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
  			return -EINVAL;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	if (fdq->d_fieldmask & ~GFS2_FIELDMASK)
  		return -EINVAL;
  	if (fdq->d_id != id)
  		return -EINVAL;
  
  	error = qd_get(sdp, type, id, &qd);
  	if (error)
  		return error;
  
  	mutex_lock(&ip->i_inode.i_mutex);
  	error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh);
  	if (error)
  		goto out_put;
  	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
  	if (error)
  		goto out_q;
  
  	/* Check for existing entry, if none then alloc new blocks */
  	error = update_qd(sdp, qd);
  	if (error)
  		goto out_i;
  
  	/* If nothing has changed, this is a no-op */
  	if ((fdq->d_fieldmask & FS_DQ_BSOFT) &&
14870b457   Abhijith Das   GFS2: Userland ex...
1477
  	    ((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1478
  		fdq->d_fieldmask ^= FS_DQ_BSOFT;
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
1479

e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1480
  	if ((fdq->d_fieldmask & FS_DQ_BHARD) &&
14870b457   Abhijith Das   GFS2: Userland ex...
1481
  	    ((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1482
  		fdq->d_fieldmask ^= FS_DQ_BHARD;
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
1483
1484
1485
1486
  
  	if ((fdq->d_fieldmask & FS_DQ_BCOUNT) &&
  	    ((fdq->d_bcount >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_value)))
  		fdq->d_fieldmask ^= FS_DQ_BCOUNT;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1487
1488
1489
1490
  	if (fdq->d_fieldmask == 0)
  		goto out_i;
  
  	offset = qd2offset(qd);
461cb419f   Bob Peterson   GFS2: Simplify gf...
1491
  	alloc_required = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota));
e79a46a03   Abhijith Das   GFS2: panics on q...
1492
1493
  	if (gfs2_is_stuffed(ip))
  		alloc_required = 1;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1494
  	if (alloc_required) {
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1495
1496
  		gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
  				       &data_blocks, &ind_blocks);
564e12b11   Bob Peterson   GFS2: decouple qu...
1497
1498
  		blocks = 1 + data_blocks + ind_blocks;
  		error = gfs2_inplace_reserve(ip, blocks);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1499
  		if (error)
564e12b11   Bob Peterson   GFS2: decouple qu...
1500
  			goto out_i;
54335b1fc   Steven Whitehouse   GFS2: Cache the m...
1501
  		blocks += gfs2_rg_blocks(ip);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1502
  	}
e79a46a03   Abhijith Das   GFS2: panics on q...
1503
1504
1505
  	/* Some quotas span block boundaries and can update two blocks,
  	   adding an extra block to the transaction to handle such quotas */
  	error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 2, 0);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1506
1507
1508
1509
1510
1511
1512
1513
  	if (error)
  		goto out_release;
  
  	/* Apply changes */
  	error = gfs2_adjust_quota(ip, offset, 0, qd, fdq);
  
  	gfs2_trans_end(sdp);
  out_release:
564e12b11   Bob Peterson   GFS2: decouple qu...
1514
  	if (alloc_required)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1515
  		gfs2_inplace_release(ip);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1516
1517
1518
1519
1520
1521
1522
1523
1524
  out_i:
  	gfs2_glock_dq_uninit(&i_gh);
  out_q:
  	gfs2_glock_dq_uninit(&q_gh);
  out_put:
  	mutex_unlock(&ip->i_inode.i_mutex);
  	qd_put(qd);
  	return error;
  }
cc632e7f9   Steven Whitehouse   GFS2: Hook gfs2_q...
1525
1526
  const struct quotactl_ops gfs2_quotactl_ops = {
  	.quota_sync     = gfs2_quota_sync,
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
1527
  	.get_xstate     = gfs2_quota_get_xstate,
b9b2dd36c   Christoph Hellwig   quota: unify ->ge...
1528
  	.get_dqblk	= gfs2_get_dqblk,
c472b4327   Christoph Hellwig   quota: unify ->se...
1529
  	.set_dqblk	= gfs2_set_dqblk,
cc632e7f9   Steven Whitehouse   GFS2: Hook gfs2_q...
1530
  };