Blame view

fs/gfs2/quota.c 38.1 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
41
42
43
   * 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>
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
b3b94faa5   David Teigland   [GFS2] The core o...
44
  #include <linux/sort.h>
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
45
  #include <linux/fs.h>
2e565bb69   Steven Whitehouse   [GFS2] Mark metad...
46
  #include <linux/bio.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
47
  #include <linux/gfs2_ondisk.h>
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
48
49
  #include <linux/kthread.h>
  #include <linux/freezer.h>
2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
50
  #include <linux/quota.h>
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
51
  #include <linux/dqblk_xfs.h>
b3b94faa5   David Teigland   [GFS2] The core o...
52
53
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
54
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
55
56
57
  #include "bmap.h"
  #include "glock.h"
  #include "glops.h"
b3b94faa5   David Teigland   [GFS2] The core o...
58
59
60
61
62
63
  #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...
64
  #include "inode.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
65
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
66
67
68
  
  #define QUOTA_USER 1
  #define QUOTA_GROUP 0
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
69
70
71
72
73
  struct gfs2_quota_change_host {
  	u64 qc_change;
  	u32 qc_flags; /* GFS2_QCF_... */
  	u32 qc_id;
  };
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
74
75
  static LIST_HEAD(qd_lru_list);
  static atomic_t qd_lru_count = ATOMIC_INIT(0);
1328df725   Xu Gang   GFS2: Use DEFINE_...
76
  static DEFINE_SPINLOCK(qd_lru_lock);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
77

7f8275d0d   Dave Chinner   mm: add context a...
78
  int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  {
  	struct gfs2_quota_data *qd;
  	struct gfs2_sbd *sdp;
  
  	if (nr == 0)
  		goto out;
  
  	if (!(gfp_mask & __GFP_FS))
  		return -1;
  
  	spin_lock(&qd_lru_lock);
  	while (nr && !list_empty(&qd_lru_list)) {
  		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...
97
98
99
  		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_...
100
  		gfs2_glock_put(qd->qd_gl);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  		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);
  		nr--;
  	}
  	spin_unlock(&qd_lru_lock);
  
  out:
  	return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
116
  static u64 qd2offset(struct gfs2_quota_data *qd)
b3b94faa5   David Teigland   [GFS2] The core o...
117
  {
cd915493f   Steven Whitehouse   [GFS2] Change all...
118
  	u64 offset;
b3b94faa5   David Teigland   [GFS2] The core o...
119

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

cd915493f   Steven Whitehouse   [GFS2] Change all...
140
  	error = gfs2_glock_get(sdp, 2 * (u64)id + !user,
b3b94faa5   David Teigland   [GFS2] The core o...
141
142
143
  			      &gfs2_quota_glops, CREATE, &qd->qd_gl);
  	if (error)
  		goto fail;
b3b94faa5   David Teigland   [GFS2] The core o...
144
145
146
  	*qdp = qd;
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
147
  fail:
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
148
  	kmem_cache_free(gfs2_quotad_cachep, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
149
150
  	return error;
  }
6a6ada81e   Steven Whitehouse   GFS2: Remove cons...
151
  static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,
b3b94faa5   David Teigland   [GFS2] The core o...
152
153
154
155
156
157
158
159
160
  		  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...
161
  		spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
162
163
164
  		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...
165
166
167
168
169
170
171
  				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...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  				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...
186
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
187

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

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

23591256d   Steven Whitehouse   [GFS2] Fix bmap t...
299
  	bh_map.b_size = 1 << ip->i_inode.i_blkbits;
e9e1ef2b6   Bob Peterson   [GFS2] Remove fun...
300
  	error = gfs2_block_map(&ip->i_inode, block, &bh_map, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
301
302
  	if (error)
  		goto fail;
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
303
  	error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh);
b3b94faa5   David Teigland   [GFS2] The core o...
304
305
306
307
308
309
310
311
312
313
  	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...
314
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
315
316
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
317
  fail_brelse:
b3b94faa5   David Teigland   [GFS2] The core o...
318
  	brelse(bh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
319
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
320
  	qd->qd_bh_count--;
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
321
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
322
323
324
325
326
327
  	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...
328
  	mutex_lock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
329
330
331
332
333
334
  	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...
335
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
336
337
338
339
340
341
342
343
344
345
346
347
  }
  
  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...
348
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
349
350
351
352
353
354
355
356
357
358
  
  	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...
359
360
  		gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
  		atomic_inc(&qd->qd_count);
b3b94faa5   David Teigland   [GFS2] The core o...
361
362
363
364
365
366
367
368
369
370
  		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...
371
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  
  	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...
395
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
396
397
398
  
  	if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
  	    !test_bit(QDF_CHANGE, &qd->qd_flags)) {
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
399
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
400
401
402
403
404
405
  		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...
406
407
  	gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
  	atomic_inc(&qd->qd_count);
b3b94faa5   David Teigland   [GFS2] The core o...
408
409
410
  	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...
411
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  
  	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 ...
426
427
  	gfs2_assert_warn(qd->qd_gl->gl_sbd,
  			 test_bit(QDF_LOCKED, &qd->qd_flags));
b3b94faa5   David Teigland   [GFS2] The core o...
428
429
430
431
432
  	clear_bit(QDF_LOCKED, &qd->qd_flags);
  	bh_put(qd);
  	slot_put(qd);
  	qd_put(qd);
  }
33a82529e   Steven Whitehouse   GFS2: Remove cons...
433
  static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id,
b3b94faa5   David Teigland   [GFS2] The core o...
434
435
436
  		    struct gfs2_quota_data **qdp)
  {
  	int error;
6a6ada81e   Steven Whitehouse   GFS2: Remove cons...
437
  	error = qd_get(sdp, user, id, qdp);
b3b94faa5   David Teigland   [GFS2] The core o...
438
439
440
441
442
443
444
445
446
447
448
449
  	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 ...
450
  fail_slot:
b3b94faa5   David Teigland   [GFS2] The core o...
451
  	slot_put(*qdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
452
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
453
454
455
456
457
458
459
460
461
462
  	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...
463
  int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
464
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
465
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
466
  	struct gfs2_alloc *al = ip->i_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
467
468
469
470
471
472
473
474
475
  	struct gfs2_quota_data **qd = al->al_qd;
  	int error;
  
  	if (gfs2_assert_warn(sdp, !al->al_qd_num) ||
  	    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
479
480
  	if (error)
  		goto out;
  	al->al_qd_num++;
  	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
484
485
  	if (error)
  		goto out;
  	al->al_qd_num++;
  	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
490
491
492
  		if (error)
  			goto out;
  		al->al_qd_num++;
  		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
497
498
499
  		if (error)
  			goto out;
  		al->al_qd_num++;
  		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);
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
509
  	struct gfs2_alloc *al = ip->i_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
510
511
512
513
514
515
516
517
518
519
520
521
522
  	unsigned int x;
  
  	gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags));
  
  	for (x = 0; x < al->al_qd_num; x++) {
  		qdsb_put(al->al_qd[x]);
  		al->al_qd[x] = NULL;
  	}
  	al->al_qd_num = 0;
  }
  
  static int sort_qd(const void *a, const void *b)
  {
48fac1790   Steven Whitehouse   [GFS2] Remove unu...
523
524
  	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...
525
526
527
528
  
  	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...
529
  			return -1;
b3b94faa5   David Teigland   [GFS2] The core o...
530
  		else
48fac1790   Steven Whitehouse   [GFS2] Remove unu...
531
  			return 1;
b3b94faa5   David Teigland   [GFS2] The core o...
532
  	}
48fac1790   Steven Whitehouse   [GFS2] Remove unu...
533
534
535
536
  	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...
537

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

f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
547
  	mutex_lock(&sdp->sd_quota_mutex);
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
548
  	gfs2_trans_add_bh(ip->i_gl, qd->qd_bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
549
550
551
552
553
554
555
556
  
  	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 ...
557
  	x = be64_to_cpu(qc->qc_change) + change;
b3b94faa5   David Teigland   [GFS2] The core o...
558
  	qc->qc_change = cpu_to_be64(x);
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
559
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
560
  	qd->qd_change = x;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
561
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
562
563
564
565
566
567
568
569
570
571
572
573
  
  	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...
574

f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
575
  	mutex_unlock(&sdp->sd_quota_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
576
  }
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
577
  /**
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
578
579
580
   * 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...
581
   * @change: The amount of usage change to record
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
582
   * @qd: The quota data
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
583
   * @fdq: The updated limits to record
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
584
585
586
   *
   * 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...
587
588
   *
   * Returns: 0 or -ve on error
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
589
   */
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
590

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

20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
608
  	if (gfs2_is_stuffed(ip))
0fd535547   Abhijith Das   [GFS2] Force unst...
609
  		gfs2_unstuff_dinode(ip, NULL);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  
  	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...
624
  			qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
625
626
627
  			qd->qd_qb.qb_warn = qp->qu_warn;
  		}
  		if (fdq->d_fieldmask & FS_DQ_BHARD) {
14870b457   Abhijith Das   GFS2: Userland ex...
628
  			qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
629
630
  			qd->qd_qb.qb_limit = qp->qu_limit;
  		}
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
631
632
633
634
  		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...
635
636
637
638
639
640
  	}
  
  	/* 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...
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
  	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...
660
  		gfs2_block_map(inode, iblock, bh, 1);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
661
  		if (!buffer_mapped(bh))
7e619bc3e   Abhijith Das   GFS2: Fix writing...
662
663
  			goto unlock_out;
  		/* If it's a newly allocated disk block for quota, zero it */
8b4216018   Abhijith Das   GFS2: BUG in gfs2...
664
665
  		if (buffer_new(bh))
  			zero_user(page, pos - blocksize, bh->b_size);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
666
667
668
669
670
671
  	}
  
  	if (PageUptodate(page))
  		set_buffer_uptodate(bh);
  
  	if (!buffer_uptodate(bh)) {
2e565bb69   Steven Whitehouse   [GFS2] Mark metad...
672
  		ll_rw_block(READ_META, 1, &bh);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
673
674
  		wait_on_buffer(bh);
  		if (!buffer_uptodate(bh))
7e619bc3e   Abhijith Das   GFS2: Fix writing...
675
  			goto unlock_out;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
676
677
678
679
680
  	}
  
  	gfs2_trans_add_bh(ip->i_gl, bh, 0);
  
  	kaddr = kmap_atomic(page, KM_USER0);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
681
682
683
  	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...
684
685
  	flush_dcache_page(page);
  	kunmap_atomic(kaddr, KM_USER0);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
686
687
688
689
690
  	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...
691
  	if ((offset + sizeof(struct gfs2_quota)) > PAGE_CACHE_SIZE) {
7e619bc3e   Abhijith Das   GFS2: Fix writing...
692
693
694
695
696
697
  		ptr = ptr + nbytes;
  		nbytes = sizeof(struct gfs2_quota) - nbytes;
  		offset = 0;
  		index++;
  		goto get_a_page;
  	}
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
698

7e619bc3e   Abhijith Das   GFS2: Fix writing...
699
  	/* Update the disk inode timestamp and size (if extended) */
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
700
701
  	err = gfs2_meta_inode_buffer(ip, &dibh);
  	if (err)
7e619bc3e   Abhijith Das   GFS2: Fix writing...
702
  		goto out;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
703
704
  
  	size = loc + sizeof(struct gfs2_quota);
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
705
  	if (size > inode->i_size)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
706
  		i_size_write(inode, size);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
707
708
709
710
711
  	inode->i_mtime = inode->i_atime = CURRENT_TIME;
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
  	gfs2_dinode_out(ip, dibh->b_data);
  	brelse(dibh);
  	mark_inode_dirty(inode);
7e619bc3e   Abhijith Das   GFS2: Fix writing...
712
713
714
  out:
  	return err;
  unlock_out:
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
715
716
717
718
  	unlock_page(page);
  	page_cache_release(page);
  	return err;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
719
720
721
  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...
722
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
723
724
725
726
  	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...
727
  	loff_t offset;
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
728
  	unsigned int nalloc = 0, blocks;
b3b94faa5   David Teigland   [GFS2] The core o...
729
730
731
732
733
  	struct gfs2_alloc *al = NULL;
  	int error;
  
  	gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
  			      &data_blocks, &ind_blocks);
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
734
  	ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
735
736
737
738
  	if (!ghs)
  		return -ENOMEM;
  
  	sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
739
  	mutex_lock_nested(&ip->i_inode.i_mutex, I_MUTEX_QUOTA);
b3b94faa5   David Teigland   [GFS2] The core o...
740
  	for (qx = 0; qx < num_qd; qx++) {
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
741
  		error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE,
b3b94faa5   David Teigland   [GFS2] The core o...
742
743
744
745
746
747
748
749
750
751
  					   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...
752
  		offset = qd2offset(qda[x]);
461cb419f   Bob Peterson   GFS2: Simplify gf...
753
754
  		if (gfs2_write_alloc_required(ip, offset,
  					      sizeof(struct gfs2_quota)))
b3b94faa5   David Teigland   [GFS2] The core o...
755
756
  			nalloc++;
  	}
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
757
758
759
760
761
762
763
764
765
766
767
768
  	al = gfs2_alloc_get(ip);
  	if (!al) {
  		error = -ENOMEM;
  		goto out_gunlock;
  	}
  	/* 
  	 * 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
  	 */
  	al->al_requested = 1;
7e619bc3e   Abhijith Das   GFS2: Fix writing...
769
770
771
772
  	/* +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...
773

20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
774
775
776
777
778
  	if (nalloc)
  		al->al_requested += nalloc * (data_blocks + ind_blocks);		
  	error = gfs2_inplace_reserve(ip);
  	if (error)
  		goto out_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
779

20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
780
  	if (nalloc)
bf97b6734   Benjamin Marzinski   GFS2: reserve mor...
781
  		blocks += gfs2_rg_blocks(al) + nalloc * ind_blocks + RES_STATFS;
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
782
783
784
785
  
  	error = gfs2_trans_begin(sdp, blocks, 0);
  	if (error)
  		goto out_ipres;
b3b94faa5   David Teigland   [GFS2] The core o...
786
787
  
  	for (x = 0; x < num_qd; x++) {
b3b94faa5   David Teigland   [GFS2] The core o...
788
789
  		qd = qda[x];
  		offset = qd2offset(qd);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
790
  		error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, qd, NULL);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
791
  		if (error)
b3b94faa5   David Teigland   [GFS2] The core o...
792
  			goto out_end_trans;
b3b94faa5   David Teigland   [GFS2] The core o...
793
794
  
  		do_qc(qd, -qd->qd_change_sync);
b3b94faa5   David Teigland   [GFS2] The core o...
795
796
797
  	}
  
  	error = 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
798
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
799
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
800
  out_ipres:
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
801
  	gfs2_inplace_release(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
802
  out_alloc:
20b95bf2c   Abhijith Das   [GFS2] gfs2_adjus...
803
  	gfs2_alloc_put(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
804
  out_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
805
  	gfs2_glock_dq_uninit(&i_gh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
806
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
807
808
  	while (qx--)
  		gfs2_glock_dq_uninit(&ghs[qx]);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
809
  	mutex_unlock(&ip->i_inode.i_mutex);
b3b94faa5   David Teigland   [GFS2] The core o...
810
  	kfree(ghs);
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
811
  	gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
b3b94faa5   David Teigland   [GFS2] The core o...
812
813
  	return error;
  }
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
  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...
838
839
840
841
  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...
842
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
843
  	struct gfs2_holder i_gh;
b3b94faa5   David Teigland   [GFS2] The core o...
844
  	int error;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
845
  restart:
b3b94faa5   David Teigland   [GFS2] The core o...
846
847
848
  	error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh);
  	if (error)
  		return error;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
849
  	qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
b3b94faa5   David Teigland   [GFS2] The core o...
850

e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
851
  	if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) {
b3b94faa5   David Teigland   [GFS2] The core o...
852
  		gfs2_glock_dq_uninit(q_gh);
91094d0fb   Steven Whitehouse   GFS2: Remove obso...
853
854
  		error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE,
  					   GL_NOCACHE, q_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
855
856
  		if (error)
  			return error;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
857
  		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
858
859
  		if (error)
  			goto fail;
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
860
861
  		error = update_qd(sdp, qd);
  		if (error)
1e72c0f7c   Steven Whitehouse   GFS2: Clean up gf...
862
  			goto fail_gunlock;
b3b94faa5   David Teigland   [GFS2] The core o...
863

e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
864
  		gfs2_glock_dq_uninit(&i_gh);
91094d0fb   Steven Whitehouse   GFS2: Remove obso...
865
866
867
  		gfs2_glock_dq_uninit(q_gh);
  		force_refresh = 0;
  		goto restart;
b3b94faa5   David Teigland   [GFS2] The core o...
868
869
870
  	}
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
871
  fail_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
872
  	gfs2_glock_dq_uninit(&i_gh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
873
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
874
  	gfs2_glock_dq_uninit(q_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
875
876
  	return error;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
877
  int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
878
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
879
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
880
  	struct gfs2_alloc *al = ip->i_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
  	unsigned int x;
  	int error = 0;
  
  	gfs2_quota_hold(ip, uid, gid);
  
  	if (capable(CAP_SYS_RESOURCE) ||
  	    sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
  		return 0;
  
  	sort(al->al_qd, al->al_qd_num, sizeof(struct gfs2_quota_data *),
  	     sort_qd, NULL);
  
  	for (x = 0; x < al->al_qd_num; x++) {
  		error = do_glock(al->al_qd[x], NO_FORCE, &al->al_qd_ghs[x]);
  		if (error)
  			break;
  	}
  
  	if (!error)
  		set_bit(GIF_QD_LOCKED, &ip->i_flags);
  	else {
  		while (x--)
  			gfs2_glock_dq_uninit(&al->al_qd_ghs[x]);
  		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...
914
  	s64 value;
b3b94faa5   David Teigland   [GFS2] The core o...
915
916
917
918
919
  	unsigned int num, den;
  	int do_sync = 1;
  
  	if (!qd->qd_qb.qb_limit)
  		return 0;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
920
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
921
  	value = qd->qd_change;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
922
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
923
924
925
926
927
928
929
930
  
  	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...
931
932
  	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...
933
934
935
  		do_sync = 0;
  	else {
  		value *= gfs2_jindex_size(sdp) * num;
4abaca17e   David Howells   [GFS2] Fix GFS2's...
936
  		value = div_s64(value, den);
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
937
  		value += (s64)be64_to_cpu(qd->qd_qb.qb_value);
cd915493f   Steven Whitehouse   [GFS2] Change all...
938
  		if (value < (s64)be64_to_cpu(qd->qd_qb.qb_limit))
b3b94faa5   David Teigland   [GFS2] The core o...
939
940
941
942
943
944
945
946
  			do_sync = 0;
  	}
  
  	return do_sync;
  }
  
  void gfs2_quota_unlock(struct gfs2_inode *ip)
  {
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
947
  	struct gfs2_alloc *al = ip->i_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
  	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;
  
  	for (x = 0; x < al->al_qd_num; x++) {
  		struct gfs2_quota_data *qd;
  		int sync;
  
  		qd = al->al_qd[x];
  		sync = need_sync(qd);
  
  		gfs2_glock_dq_uninit(&al->al_qd_ghs[x]);
  
  		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 ...
973
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
974
975
976
977
978
979
980
981
  	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...
982

2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
983
984
  	printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u
  ",
02630a12c   Steven Whitehouse   [GFS2] Remove dep...
985
986
987
  	       sdp->sd_fsname, type,
  	       (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group",
  	       qd->qd_id);
b3b94faa5   David Teigland   [GFS2] The core o...
988
989
990
  
  	return 0;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
991
  int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
992
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
993
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
994
  	struct gfs2_alloc *al = ip->i_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
995
  	struct gfs2_quota_data *qd;
cd915493f   Steven Whitehouse   [GFS2] Change all...
996
  	s64 value;
b3b94faa5   David Teigland   [GFS2] The core o...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
  	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;
  
  	for (x = 0; x < al->al_qd_num; x++) {
  		qd = al->al_qd[x];
  
  		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...
1012
  		value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
1013
  		spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1014
  		value += qd->qd_change;
22077f57d   Steven Whitehouse   GFS2: Remove "dou...
1015
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1016

cd915493f   Steven Whitehouse   [GFS2] Change all...
1017
  		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...
1018
  			print_message(qd, "exceeded");
2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
1019
1020
1021
  			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...
1022
1023
  			error = -EDQUOT;
  			break;
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
1024
  		} else if (be64_to_cpu(qd->qd_qb.qb_warn) &&
cd915493f   Steven Whitehouse   [GFS2] Change all...
1025
  			   (s64)be64_to_cpu(qd->qd_qb.qb_warn) < value &&
b3b94faa5   David Teigland   [GFS2] The core o...
1026
  			   time_after_eq(jiffies, qd->qd_last_warn +
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
1027
1028
  					 gfs2_tune_get(sdp,
  						gt_quota_warn_period) * HZ)) {
2ec465052   Steven Whitehouse   GFS2: Use dquot_s...
1029
1030
1031
  			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...
1032
1033
1034
1035
1036
1037
1038
  			error = print_message(qd, "warning");
  			qd->qd_last_warn = jiffies;
  		}
  	}
  
  	return error;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
1039
1040
  void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
  		       u32 uid, u32 gid)
b3b94faa5   David Teigland   [GFS2] The core o...
1041
  {
6dbd82248   Steven Whitehouse   [GFS2] Reduce ino...
1042
  	struct gfs2_alloc *al = ip->i_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
1043
1044
  	struct gfs2_quota_data *qd;
  	unsigned int x;
b3b94faa5   David Teigland   [GFS2] The core o...
1045

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1046
  	if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
b3b94faa5   David Teigland   [GFS2] The core o...
1047
  		return;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
1048
  	if (ip->i_diskflags & GFS2_DIF_SYSTEM)
b3b94faa5   David Teigland   [GFS2] The core o...
1049
1050
1051
1052
1053
1054
1055
1056
  		return;
  
  	for (x = 0; x < al->al_qd_num; x++) {
  		qd = al->al_qd[x];
  
  		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...
1057
1058
1059
  		}
  	}
  }
5fb324ad2   Christoph Hellwig   quota: move code ...
1060
  int gfs2_quota_sync(struct super_block *sb, int type, int wait)
b3b94faa5   David Teigland   [GFS2] The core o...
1061
  {
8c42d637f   Steven Whitehouse   GFS2: Alter argum...
1062
  	struct gfs2_sbd *sdp = sb->s_fs_info;
b3b94faa5   David Teigland   [GFS2] The core o...
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
  	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 ...
1103
1104
1105
1106
  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...
1107
  int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
b3b94faa5   David Teigland   [GFS2] The core o...
1108
1109
1110
1111
  {
  	struct gfs2_quota_data *qd;
  	struct gfs2_holder q_gh;
  	int error;
6a6ada81e   Steven Whitehouse   GFS2: Remove cons...
1112
  	error = qd_get(sdp, user, id, &qd);
b3b94faa5   David Teigland   [GFS2] The core o...
1113
1114
1115
1116
1117
1118
1119
1120
  	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...
1121
1122
  	return error;
  }
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
1123
1124
1125
1126
1127
1128
1129
1130
  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...
1131
1132
  int gfs2_quota_init(struct gfs2_sbd *sdp)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1133
  	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1134
1135
  	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...
1136
1137
  	unsigned int x, slot = 0;
  	unsigned int found = 0;
cd915493f   Steven Whitehouse   [GFS2] Change all...
1138
1139
  	u64 dblock;
  	u32 extlen = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1140
  	int error;
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1141
  	if (gfs2_check_internal_file_size(sdp->sd_qc_inode, 1, 64 << 20))
907b9bceb   Steven Whitehouse   [GFS2/DLM] Fix tr...
1142
  		return -EIO;
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1143

b3b94faa5   David Teigland   [GFS2] The core o...
1144
  	sdp->sd_quota_slots = blocks * sdp->sd_qc_per_block;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
1145
  	sdp->sd_quota_chunks = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * PAGE_SIZE);
b3b94faa5   David Teigland   [GFS2] The core o...
1146
1147
1148
1149
  
  	error = -ENOMEM;
  
  	sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks,
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
1150
  				       sizeof(unsigned char *), GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
1151
1152
1153
1154
  	if (!sdp->sd_quota_bitmap)
  		return error;
  
  	for (x = 0; x < sdp->sd_quota_chunks; x++) {
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
1155
  		sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  		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...
1166
  			error = gfs2_extent_map(&ip->i_inode, x, &new, &dblock, &extlen);
b3b94faa5   David Teigland   [GFS2] The core o...
1167
1168
1169
  			if (error)
  				goto fail;
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
1170
  		error = -EIO;
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
1171
1172
1173
  		bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
  		if (!bh)
  			goto fail;
b3b94faa5   David Teigland   [GFS2] The core o...
1174
1175
1176
1177
  		if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_QC)) {
  			brelse(bh);
  			goto fail;
  		}
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
1178
  		for (y = 0; y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
b3b94faa5   David Teigland   [GFS2] The core o...
1179
  		     y++, slot++) {
b62f963e1   Al Viro   [GFS2] split and ...
1180
  			struct gfs2_quota_change_host qc;
b3b94faa5   David Teigland   [GFS2] The core o...
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
  			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...
1200

0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1201
  			spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1202
1203
1204
  			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...
1205
  			spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
  
  			found++;
  		}
  
  		brelse(bh);
  		dblock++;
  		extlen--;
  	}
  
  	if (found)
  		fs_info(sdp, "found %u quota changes
  ", found);
  
  	return 0;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1220
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
1221
1222
1223
  	gfs2_quota_cleanup(sdp);
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1224
1225
1226
1227
1228
  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...
1229
  	spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1230
1231
  	while (!list_empty(head)) {
  		qd = list_entry(head->prev, struct gfs2_quota_data, qd_list);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1232
1233
1234
  		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...
1235
1236
  			list_move(&qd->qd_list, head);
  			spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1237
  			schedule();
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1238
  			spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1239
1240
1241
1242
  			continue;
  		}
  
  		list_del(&qd->qd_list);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1243
1244
1245
1246
1247
  		/* 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...
1248
  		atomic_dec(&sdp->sd_quota_count);
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1249
  		spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1250

0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1251
  		if (!atomic_read(&qd->qd_count)) {
b3b94faa5   David Teigland   [GFS2] The core o...
1252
1253
1254
1255
1256
  			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_...
1257
  		gfs2_glock_put(qd->qd_gl);
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1258
  		kmem_cache_free(gfs2_quotad_cachep, qd);
b3b94faa5   David Teigland   [GFS2] The core o...
1259

0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1260
  		spin_lock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1261
  	}
0a7ab79c5   Abhijith Das   GFS2: change gfs2...
1262
  	spin_unlock(&qd_lru_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
1263
1264
1265
1266
1267
1268
1269
1270
1271
  
  	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 & ...
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
  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...
1282
  			       int (*fxn)(struct super_block *sb, int type),
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1283
1284
1285
1286
  			       unsigned long t, unsigned long *timeo,
  			       unsigned int *new_timeo)
  {
  	if (t >= *timeo) {
8c42d637f   Steven Whitehouse   GFS2: Alter argum...
1287
  		int error = fxn(sdp->sd_vfs, 0);
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1288
1289
1290
1291
1292
1293
  		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...
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
  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...
1312
1313
1314
1315
1316
1317
  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 & ...
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
  /**
   * 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...
1332
  	int empty;
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1333
1334
1335
1336
  
  	while (!kthread_should_stop()) {
  
  		/* Update the master statfs file */
3d3c10f2c   Benjamin Marzinski   GFS2: Improve sta...
1337
1338
1339
1340
1341
1342
1343
1344
1345
  		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 & ...
1346
1347
  
  		/* Update quota file */
5fb324ad2   Christoph Hellwig   quota: move code ...
1348
  		quotad_check_timeo(sdp, "sync", gfs2_quota_sync_timeo, t,
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1349
  				   &quotad_timeo, &tune->gt_quota_quantum);
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1350
1351
  		/* Check for & recover partially truncated inodes */
  		quotad_check_trunc_list(sdp);
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1352
1353
1354
  		if (freezing(current))
  			refrigerator();
  		t = min(quotad_timeo, statfs_timeo);
7fa5d20d1   Steven Whitehouse   GFS2: Make quotad...
1355
  		prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_INTERRUPTIBLE);
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1356
1357
1358
  		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...
1359
  		if (empty && !sdp->sd_statfs_force_sync)
813e0c46c   Steven Whitehouse   GFS2: Fix "trunca...
1360
1361
1362
  			t -= schedule_timeout(t);
  		else
  			t = 0;
37b2c8377   Steven Whitehouse   GFS2: Clean up & ...
1363
1364
1365
1366
1367
  		finish_wait(&sdp->sd_quota_wait, &wait);
  	}
  
  	return 0;
  }
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
1368
1369
1370
1371
1372
1373
1374
  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...
1375
1376
1377
  
  	switch (sdp->sd_args.ar_quota) {
  	case GFS2_QUOTA_ON:
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1378
  		fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD);
ad6bb90f3   Christoph Hellwig   GFS2: fix quota s...
1379
1380
  		/*FALLTHRU*/
  	case GFS2_QUOTA_ACCOUNT:
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1381
  		fqs->qs_flags |= (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT);
ad6bb90f3   Christoph Hellwig   GFS2: fix quota s...
1382
1383
1384
1385
  		break;
  	case GFS2_QUOTA_OFF:
  		break;
  	}
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
1386
1387
1388
1389
1390
1391
1392
1393
1394
  	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...
1395
1396
  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...
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
  {
  	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...
1425
  	fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
113d6b3c9   Steven Whitehouse   GFS2: Add get_xqu...
1426
  	fdq->d_id = id;
14870b457   Abhijith Das   GFS2: Userland ex...
1427
1428
1429
  	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...
1430
1431
1432
1433
1434
1435
  
  	gfs2_glock_dq_uninit(&q_gh);
  out:
  	qd_put(qd);
  	return error;
  }
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1436
  /* GFS2 only supports a subset of the XFS fields */
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
1437
  #define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1438

c472b4327   Christoph Hellwig   quota: unify ->se...
1439
1440
  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...
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
  {
  	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;
  	struct gfs2_alloc *al;
  	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...
1459
  		if (fdq->d_flags != FS_USER_QUOTA)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1460
1461
1462
1463
  			return -EINVAL;
  		break;
  	case GRPQUOTA:
  		type = QUOTA_GROUP;
ade7ce31c   Christoph Hellwig   quota: Clean up t...
1464
  		if (fdq->d_flags != FS_GROUP_QUOTA)
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
  			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...
1495
  	    ((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1496
  		fdq->d_fieldmask ^= FS_DQ_BSOFT;
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
1497

e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1498
  	if ((fdq->d_fieldmask & FS_DQ_BHARD) &&
14870b457   Abhijith Das   GFS2: Userland ex...
1499
  	    ((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1500
  		fdq->d_fieldmask ^= FS_DQ_BHARD;
802ec9b66   Abhijith Das   GFS2: Allow gfs2 ...
1501
1502
1503
1504
  
  	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...
1505
1506
1507
1508
  	if (fdq->d_fieldmask == 0)
  		goto out_i;
  
  	offset = qd2offset(qd);
461cb419f   Bob Peterson   GFS2: Simplify gf...
1509
  	alloc_required = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota));
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
  	if (alloc_required) {
  		al = gfs2_alloc_get(ip);
  		if (al == NULL)
  			goto out_i;
  		gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
  				       &data_blocks, &ind_blocks);
  		blocks = al->al_requested = 1 + data_blocks + ind_blocks;
  		error = gfs2_inplace_reserve(ip);
  		if (error)
  			goto out_alloc;
bf97b6734   Benjamin Marzinski   GFS2: reserve mor...
1520
  		blocks += gfs2_rg_blocks(al);
e285c1003   Steven Whitehouse   GFS2: Add set_xqu...
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
  	}
  
  	error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0);
  	if (error)
  		goto out_release;
  
  	/* Apply changes */
  	error = gfs2_adjust_quota(ip, offset, 0, qd, fdq);
  
  	gfs2_trans_end(sdp);
  out_release:
  	if (alloc_required) {
  		gfs2_inplace_release(ip);
  out_alloc:
  		gfs2_alloc_put(ip);
  	}
  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...
1546
1547
  const struct quotactl_ops gfs2_quotactl_ops = {
  	.quota_sync     = gfs2_quota_sync,
1d371b5e1   Steven Whitehouse   GFS2: Add get_xst...
1548
  	.get_xstate     = gfs2_quota_get_xstate,
b9b2dd36c   Christoph Hellwig   quota: unify ->ge...
1549
  	.get_dqblk	= gfs2_get_dqblk,
c472b4327   Christoph Hellwig   quota: unify ->se...
1550
  	.set_dqblk	= gfs2_set_dqblk,
cc632e7f9   Steven Whitehouse   GFS2: Hook gfs2_q...
1551
  };