]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/quota-Allow-to-separately-enable-quota-accounting-a.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / quota-Allow-to-separately-enable-quota-accounting-a.patch
1 From: Jan Kara <jack@suse.cz>
2 References: fate#302681
3 Subject: [PATCH 05/28] quota: Allow to separately enable quota accounting and enforcing limits
4 Patch-mainline: 2.6.29?
5
6 Split DQUOT_USR_ENABLED (and DQUOT_GRP_ENABLED) into DQUOT_USR_USAGE_ENABLED
7 and DQUOT_USR_LIMITS_ENABLED. This way we are able to separately enable /
8 disable whether we should:
9 1) ignore quotas completely
10 2) just keep uptodate information about usage
11 3) actually enforce quota limits
12
13 This is going to be useful when quota is treated as filesystem metadata - we
14 then want to keep quota information uptodate all the time and just enable /
15 disable limits enforcement.
16
17 Signed-off-by: Jan Kara <jack@suse.cz>
18 ---
19 fs/dquot.c | 222 ++++++++++++++++++++++++++++-----------------
20 fs/quota.c | 8 +-
21 include/linux/quota.h | 30 ++++++-
22 include/linux/quotaops.h | 86 ++++++++++++++----
23 4 files changed, 234 insertions(+), 112 deletions(-)
24
25 diff --git a/fs/dquot.c b/fs/dquot.c
26 index aea7bf9..bdfae7d 100644
27 --- a/fs/dquot.c
28 +++ b/fs/dquot.c
29 @@ -489,7 +489,7 @@ int vfs_quota_sync(struct super_block *sb, int type)
30 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
31 if (type != -1 && cnt != type)
32 continue;
33 - if (!sb_has_quota_enabled(sb, cnt))
34 + if (!sb_has_quota_active(sb, cnt))
35 continue;
36 spin_lock(&dq_list_lock);
37 dirty = &dqopt->info[cnt].dqi_dirty_list;
38 @@ -514,8 +514,8 @@ int vfs_quota_sync(struct super_block *sb, int type)
39 }
40
41 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
42 - if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt)
43 - && info_dirty(&dqopt->info[cnt]))
44 + if ((cnt == type || type == -1) && sb_has_quota_active(sb, cnt)
45 + && info_dirty(&dqopt->info[cnt]))
46 sb->dq_op->write_info(sb, cnt);
47 spin_lock(&dq_list_lock);
48 dqstats.syncs++;
49 @@ -594,7 +594,7 @@ we_slept:
50 /* We have more than one user... nothing to do */
51 atomic_dec(&dquot->dq_count);
52 /* Releasing dquot during quotaoff phase? */
53 - if (!sb_has_quota_enabled(dquot->dq_sb, dquot->dq_type) &&
54 + if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_type) &&
55 atomic_read(&dquot->dq_count) == 1)
56 wake_up(&dquot->dq_wait_unused);
57 spin_unlock(&dq_list_lock);
58 @@ -668,7 +668,7 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
59 unsigned int hashent = hashfn(sb, id, type);
60 struct dquot *dquot, *empty = NODQUOT;
61
62 - if (!sb_has_quota_enabled(sb, type))
63 + if (!sb_has_quota_active(sb, type))
64 return NODQUOT;
65 we_slept:
66 spin_lock(&dq_list_lock);
67 @@ -1041,7 +1041,8 @@ static inline char ignore_hardlimit(struct dquot *dquot)
68 static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype)
69 {
70 *warntype = QUOTA_NL_NOWARN;
71 - if (test_bit(DQ_FAKE_B, &dquot->dq_flags))
72 + if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
73 + test_bit(DQ_FAKE_B, &dquot->dq_flags))
74 return QUOTA_OK;
75
76 if (dquot->dq_dqb.dqb_ihardlimit &&
77 @@ -1073,7 +1074,8 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype)
78 static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype)
79 {
80 *warntype = QUOTA_NL_NOWARN;
81 - if (test_bit(DQ_FAKE_B, &dquot->dq_flags))
82 + if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
83 + test_bit(DQ_FAKE_B, &dquot->dq_flags))
84 return QUOTA_OK;
85
86 if (dquot->dq_dqb.dqb_bhardlimit &&
87 @@ -1114,7 +1116,8 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
88 static int info_idq_free(struct dquot *dquot, qsize_t inodes)
89 {
90 if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
91 - dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit)
92 + dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit ||
93 + !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type))
94 return QUOTA_NL_NOWARN;
95
96 if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit)
97 @@ -1508,7 +1511,7 @@ warn_put_all:
98 /* Wrapper for transferring ownership of an inode */
99 int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
100 {
101 - if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
102 + if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode)) {
103 vfs_dq_init(inode);
104 if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
105 return 1;
106 @@ -1549,53 +1552,22 @@ struct dquot_operations dquot_operations = {
107 .write_info = dquot_commit_info
108 };
109
110 -static inline void set_enable_flags(struct quota_info *dqopt, int type)
111 -{
112 - switch (type) {
113 - case USRQUOTA:
114 - dqopt->flags |= DQUOT_USR_ENABLED;
115 - dqopt->flags &= ~DQUOT_USR_SUSPENDED;
116 - break;
117 - case GRPQUOTA:
118 - dqopt->flags |= DQUOT_GRP_ENABLED;
119 - dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
120 - break;
121 - }
122 -}
123 -
124 -static inline void reset_enable_flags(struct quota_info *dqopt, int type,
125 - int remount)
126 -{
127 - switch (type) {
128 - case USRQUOTA:
129 - if (remount)
130 - dqopt->flags |= DQUOT_USR_SUSPENDED;
131 - else {
132 - dqopt->flags &= ~DQUOT_USR_ENABLED;
133 - dqopt->flags &= ~DQUOT_USR_SUSPENDED;
134 - }
135 - break;
136 - case GRPQUOTA:
137 - if (remount)
138 - dqopt->flags |= DQUOT_GRP_SUSPENDED;
139 - else {
140 - dqopt->flags &= ~DQUOT_GRP_ENABLED;
141 - dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
142 - }
143 - break;
144 - }
145 -}
146 -
147 -
148 /*
149 * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
150 */
151 -int vfs_quota_off(struct super_block *sb, int type, int remount)
152 +int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
153 {
154 int cnt, ret = 0;
155 struct quota_info *dqopt = sb_dqopt(sb);
156 struct inode *toputinode[MAXQUOTAS];
157
158 + /* Cannot turn off usage accounting without turning off limits, or
159 + * suspend quotas and simultaneously turn quotas off. */
160 + if ((flags & DQUOT_USAGE_ENABLED && !(flags & DQUOT_LIMITS_ENABLED))
161 + || (flags & DQUOT_SUSPENDED && flags & (DQUOT_LIMITS_ENABLED |
162 + DQUOT_USAGE_ENABLED)))
163 + return -EINVAL;
164 +
165 /* We need to serialize quota_off() for device */
166 mutex_lock(&dqopt->dqonoff_mutex);
167
168 @@ -1604,7 +1576,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
169 * sometimes we are called when fill_super() failed and calling
170 * sync_fs() in such cases does no good.
171 */
172 - if (!sb_any_quota_enabled(sb) && !sb_any_quota_suspended(sb)) {
173 + if (!sb_any_quota_loaded(sb)) {
174 mutex_unlock(&dqopt->dqonoff_mutex);
175 return 0;
176 }
177 @@ -1612,17 +1584,28 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
178 toputinode[cnt] = NULL;
179 if (type != -1 && cnt != type)
180 continue;
181 - /* If we keep inodes of quota files after remount and quotaoff
182 - * is called, drop kept inodes. */
183 - if (!remount && sb_has_quota_suspended(sb, cnt)) {
184 - iput(dqopt->files[cnt]);
185 - dqopt->files[cnt] = NULL;
186 - reset_enable_flags(dqopt, cnt, 0);
187 + if (!sb_has_quota_loaded(sb, cnt))
188 continue;
189 +
190 + if (flags & DQUOT_SUSPENDED) {
191 + dqopt->flags |=
192 + dquot_state_flag(DQUOT_SUSPENDED, cnt);
193 + } else {
194 + dqopt->flags &= ~dquot_state_flag(flags, cnt);
195 + /* Turning off suspended quotas? */
196 + if (!sb_has_quota_loaded(sb, cnt) &&
197 + sb_has_quota_suspended(sb, cnt)) {
198 + dqopt->flags &= ~dquot_state_flag(
199 + DQUOT_SUSPENDED, cnt);
200 + iput(dqopt->files[cnt]);
201 + dqopt->files[cnt] = NULL;
202 + continue;
203 + }
204 }
205 - if (!sb_has_quota_enabled(sb, cnt))
206 +
207 + /* We still have to keep quota loaded? */
208 + if (sb_has_quota_loaded(sb, cnt) && !(flags & DQUOT_SUSPENDED))
209 continue;
210 - reset_enable_flags(dqopt, cnt, remount);
211
212 /* Note: these are blocking operations */
213 drop_dquot_ref(sb, cnt);
214 @@ -1638,7 +1621,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
215 put_quota_format(dqopt->info[cnt].dqi_format);
216
217 toputinode[cnt] = dqopt->files[cnt];
218 - if (!remount)
219 + if (!sb_has_quota_loaded(sb, cnt))
220 dqopt->files[cnt] = NULL;
221 dqopt->info[cnt].dqi_flags = 0;
222 dqopt->info[cnt].dqi_igrace = 0;
223 @@ -1661,7 +1644,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
224 mutex_lock(&dqopt->dqonoff_mutex);
225 /* If quota was reenabled in the meantime, we have
226 * nothing to do */
227 - if (!sb_has_quota_enabled(sb, cnt)) {
228 + if (!sb_has_quota_loaded(sb, cnt)) {
229 mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA);
230 toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
231 S_NOATIME | S_NOQUOTA);
232 @@ -1671,10 +1654,13 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
233 }
234 mutex_unlock(&dqopt->dqonoff_mutex);
235 /* On remount RO, we keep the inode pointer so that we
236 - * can reenable quota on the subsequent remount RW.
237 - * But we have better not keep inode pointer when there
238 - * is pending delete on the quota file... */
239 - if (!remount)
240 + * can reenable quota on the subsequent remount RW. We
241 + * have to check 'flags' variable and not use sb_has_
242 + * function because another quotaon / quotaoff could
243 + * change global state before we got here. We refuse
244 + * to suspend quotas when there is pending delete on
245 + * the quota file... */
246 + if (!(flags & DQUOT_SUSPENDED))
247 iput(toputinode[cnt]);
248 else if (!toputinode[cnt]->i_nlink)
249 ret = -EBUSY;
250 @@ -1684,12 +1670,22 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
251 return ret;
252 }
253
254 +int vfs_quota_off(struct super_block *sb, int type, int remount)
255 +{
256 + return vfs_quota_disable(sb, type, remount ? DQUOT_SUSPENDED :
257 + (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED));
258 +}
259 +
260 /*
261 * Turn quotas on on a device
262 */
263
264 -/* Helper function when we already have the inode */
265 -static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
266 +/*
267 + * Helper function to turn quotas on when we already have the inode of
268 + * quota file and no quota information is loaded.
269 + */
270 +static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
271 + unsigned int flags)
272 {
273 struct quota_format_type *fmt = find_quota_format(format_id);
274 struct super_block *sb = inode->i_sb;
275 @@ -1711,6 +1707,11 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
276 error = -EINVAL;
277 goto out_fmt;
278 }
279 + /* Usage always has to be set... */
280 + if (!(flags & DQUOT_USAGE_ENABLED)) {
281 + error = -EINVAL;
282 + goto out_fmt;
283 + }
284
285 /* As we bypass the pagecache we must now flush the inode so that
286 * we see all the changes from userspace... */
287 @@ -1719,8 +1720,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
288 invalidate_bdev(sb->s_bdev);
289 mutex_lock(&inode->i_mutex);
290 mutex_lock(&dqopt->dqonoff_mutex);
291 - if (sb_has_quota_enabled(sb, type) ||
292 - sb_has_quota_suspended(sb, type)) {
293 + if (sb_has_quota_loaded(sb, type)) {
294 error = -EBUSY;
295 goto out_lock;
296 }
297 @@ -1752,7 +1752,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
298 }
299 mutex_unlock(&dqopt->dqio_mutex);
300 mutex_unlock(&inode->i_mutex);
301 - set_enable_flags(dqopt, type);
302 + dqopt->flags |= dquot_state_flag(flags, type);
303
304 add_dquot_ref(sb, type);
305 mutex_unlock(&dqopt->dqonoff_mutex);
306 @@ -1785,20 +1785,23 @@ static int vfs_quota_on_remount(struct super_block *sb, int type)
307 struct quota_info *dqopt = sb_dqopt(sb);
308 struct inode *inode;
309 int ret;
310 + unsigned int flags;
311
312 mutex_lock(&dqopt->dqonoff_mutex);
313 if (!sb_has_quota_suspended(sb, type)) {
314 mutex_unlock(&dqopt->dqonoff_mutex);
315 return 0;
316 }
317 - BUG_ON(sb_has_quota_enabled(sb, type));
318 -
319 inode = dqopt->files[type];
320 dqopt->files[type] = NULL;
321 - reset_enable_flags(dqopt, type, 0);
322 + flags = dqopt->flags & dquot_state_flag(DQUOT_USAGE_ENABLED |
323 + DQUOT_LIMITS_ENABLED, type);
324 + dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, type);
325 mutex_unlock(&dqopt->dqonoff_mutex);
326
327 - ret = vfs_quota_on_inode(inode, type, dqopt->info[type].dqi_fmt_id);
328 + flags = dquot_generic_flag(flags, type);
329 + ret = vfs_load_quota_inode(inode, type, dqopt->info[type].dqi_fmt_id,
330 + flags);
331 iput(inode);
332
333 return ret;
334 @@ -1814,12 +1817,12 @@ int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
335 if (path->mnt->mnt_sb != sb)
336 error = -EXDEV;
337 else
338 - error = vfs_quota_on_inode(path->dentry->d_inode, type,
339 - format_id);
340 + error = vfs_load_quota_inode(path->dentry->d_inode, type,
341 + format_id, DQUOT_USAGE_ENABLED |
342 + DQUOT_LIMITS_ENABLED);
343 return error;
344 }
345
346 -/* Actual function called from quotactl() */
347 int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path,
348 int remount)
349 {
350 @@ -1838,6 +1841,50 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path,
351 }
352
353 /*
354 + * More powerful function for turning on quotas allowing setting
355 + * of individual quota flags
356 + */
357 +int vfs_quota_enable(struct inode *inode, int type, int format_id,
358 + unsigned int flags)
359 +{
360 + int ret = 0;
361 + struct super_block *sb = inode->i_sb;
362 + struct quota_info *dqopt = sb_dqopt(sb);
363 +
364 + /* Just unsuspend quotas? */
365 + if (flags & DQUOT_SUSPENDED)
366 + return vfs_quota_on_remount(sb, type);
367 + if (!flags)
368 + return 0;
369 + /* Just updating flags needed? */
370 + if (sb_has_quota_loaded(sb, type)) {
371 + mutex_lock(&dqopt->dqonoff_mutex);
372 + /* Now do a reliable test... */
373 + if (!sb_has_quota_loaded(sb, type)) {
374 + mutex_unlock(&dqopt->dqonoff_mutex);
375 + goto load_quota;
376 + }
377 + if (flags & DQUOT_USAGE_ENABLED &&
378 + sb_has_quota_usage_enabled(sb, type)) {
379 + ret = -EBUSY;
380 + goto out_lock;
381 + }
382 + if (flags & DQUOT_LIMITS_ENABLED &&
383 + sb_has_quota_limits_enabled(sb, type)) {
384 + ret = -EBUSY;
385 + goto out_lock;
386 + }
387 + sb_dqopt(sb)->flags |= dquot_state_flag(flags, type);
388 +out_lock:
389 + mutex_unlock(&dqopt->dqonoff_mutex);
390 + return ret;
391 + }
392 +
393 +load_quota:
394 + return vfs_load_quota_inode(inode, type, format_id, flags);
395 +}
396 +
397 +/*
398 * This function is used when filesystem needs to initialize quotas
399 * during mount time.
400 */
401 @@ -1858,7 +1905,8 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
402
403 error = security_quota_on(dentry);
404 if (!error)
405 - error = vfs_quota_on_inode(dentry->d_inode, type, format_id);
406 + error = vfs_load_quota_inode(dentry->d_inode, type, format_id,
407 + DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
408
409 out:
410 dput(dentry);
411 @@ -1995,12 +2043,14 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
412 int rc;
413
414 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
415 - if (!(dquot = dqget(sb, id, type))) {
416 - mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
417 - return -ESRCH;
418 + dquot = dqget(sb, id, type);
419 + if (!dquot) {
420 + rc = -ESRCH;
421 + goto out;
422 }
423 rc = do_set_dqblk(dquot, di);
424 dqput(dquot);
425 +out:
426 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
427 return rc;
428 }
429 @@ -2011,7 +2061,7 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
430 struct mem_dqinfo *mi;
431
432 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
433 - if (!sb_has_quota_enabled(sb, type)) {
434 + if (!sb_has_quota_active(sb, type)) {
435 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
436 return -ESRCH;
437 }
438 @@ -2030,11 +2080,12 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
439 int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
440 {
441 struct mem_dqinfo *mi;
442 + int err = 0;
443
444 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
445 - if (!sb_has_quota_enabled(sb, type)) {
446 - mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
447 - return -ESRCH;
448 + if (!sb_has_quota_active(sb, type)) {
449 + err = -ESRCH;
450 + goto out;
451 }
452 mi = sb_dqopt(sb)->info + type;
453 spin_lock(&dq_data_lock);
454 @@ -2048,8 +2099,9 @@ int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
455 mark_info_dirty(sb, type);
456 /* Force write to disk */
457 sb->dq_op->write_info(sb, type);
458 +out:
459 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
460 - return 0;
461 + return err;
462 }
463
464 struct quotactl_ops vfs_quotactl_ops = {
465 @@ -2211,9 +2263,11 @@ EXPORT_SYMBOL(register_quota_format);
466 EXPORT_SYMBOL(unregister_quota_format);
467 EXPORT_SYMBOL(dqstats);
468 EXPORT_SYMBOL(dq_data_lock);
469 +EXPORT_SYMBOL(vfs_quota_enable);
470 EXPORT_SYMBOL(vfs_quota_on);
471 EXPORT_SYMBOL(vfs_quota_on_path);
472 EXPORT_SYMBOL(vfs_quota_on_mount);
473 +EXPORT_SYMBOL(vfs_quota_disable);
474 EXPORT_SYMBOL(vfs_quota_off);
475 EXPORT_SYMBOL(vfs_quota_sync);
476 EXPORT_SYMBOL(vfs_get_dqinfo);
477 diff --git a/fs/quota.c b/fs/quota.c
478 index 7f4386e..a8026f1 100644
479 --- a/fs/quota.c
480 +++ b/fs/quota.c
481 @@ -73,7 +73,7 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid
482 case Q_SETQUOTA:
483 case Q_GETQUOTA:
484 /* This is just informative test so we are satisfied without a lock */
485 - if (!sb_has_quota_enabled(sb, type))
486 + if (!sb_has_quota_active(sb, type))
487 return -ESRCH;
488 }
489
490 @@ -175,7 +175,7 @@ static void quota_sync_sb(struct super_block *sb, int type)
491 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
492 if (type != -1 && cnt != type)
493 continue;
494 - if (!sb_has_quota_enabled(sb, cnt))
495 + if (!sb_has_quota_active(sb, cnt))
496 continue;
497 mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA);
498 truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
499 @@ -201,7 +201,7 @@ restart:
500 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
501 if (type != -1 && type != cnt)
502 continue;
503 - if (!sb_has_quota_enabled(sb, cnt))
504 + if (!sb_has_quota_active(sb, cnt))
505 continue;
506 if (!info_dirty(&sb_dqopt(sb)->info[cnt]) &&
507 list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list))
508 @@ -245,7 +245,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void
509 __u32 fmt;
510
511 down_read(&sb_dqopt(sb)->dqptr_sem);
512 - if (!sb_has_quota_enabled(sb, type)) {
513 + if (!sb_has_quota_active(sb, type)) {
514 up_read(&sb_dqopt(sb)->dqptr_sem);
515 return -ESRCH;
516 }
517 diff --git a/include/linux/quota.h b/include/linux/quota.h
518 index 5167786..0e4b550 100644
519 --- a/include/linux/quota.h
520 +++ b/include/linux/quota.h
521 @@ -320,12 +320,34 @@ struct quota_format_type {
522 struct quota_format_type *qf_next;
523 };
524
525 -#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
526 -#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */
527 -#define DQUOT_USR_SUSPENDED 0x04 /* User diskquotas are off, but
528 +/* Quota state flags - they actually come in two flavors - for users and groups */
529 +enum {
530 + _DQUOT_USAGE_ENABLED = 0, /* Track disk usage for users */
531 + _DQUOT_LIMITS_ENABLED, /* Enforce quota limits for users */
532 + _DQUOT_SUSPENDED, /* User diskquotas are off, but
533 * we have necessary info in
534 * memory to turn them on */
535 -#define DQUOT_GRP_SUSPENDED 0x08 /* The same for group quotas */
536 + _DQUOT_STATE_FLAGS
537 +};
538 +#define DQUOT_USAGE_ENABLED (1 << _DQUOT_USAGE_ENABLED)
539 +#define DQUOT_LIMITS_ENABLED (1 << _DQUOT_LIMITS_ENABLED)
540 +#define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED)
541 +#define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
542 + DQUOT_SUSPENDED)
543 +
544 +static inline unsigned int dquot_state_flag(unsigned int flags, int type)
545 +{
546 + if (type == USRQUOTA)
547 + return flags;
548 + return flags << _DQUOT_STATE_FLAGS;
549 +}
550 +
551 +static inline unsigned int dquot_generic_flag(unsigned int flags, int type)
552 +{
553 + if (type == USRQUOTA)
554 + return flags;
555 + return flags >> _DQUOT_STATE_FLAGS;
556 +}
557
558 struct quota_info {
559 unsigned int flags; /* Flags for diskquotas on this device */
560 diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
561 index 12363cc..f7dcc30 100644
562 --- a/include/linux/quotaops.h
563 +++ b/include/linux/quotaops.h
564 @@ -43,11 +43,14 @@ int dquot_mark_dquot_dirty(struct dquot *dquot);
565
566 int vfs_quota_on(struct super_block *sb, int type, int format_id,
567 char *path, int remount);
568 +int vfs_quota_enable(struct inode *inode, int type, int format_id,
569 + unsigned int flags);
570 int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
571 struct path *path);
572 int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
573 int format_id, int type);
574 int vfs_quota_off(struct super_block *sb, int type, int remount);
575 +int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags);
576 int vfs_quota_sync(struct super_block *sb, int type);
577 int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
578 int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
579 @@ -67,26 +70,22 @@ static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
580 * Functions for checking status of quota
581 */
582
583 -static inline int sb_has_quota_enabled(struct super_block *sb, int type)
584 +static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
585 {
586 - if (type == USRQUOTA)
587 - return (sb_dqopt(sb)->flags & DQUOT_USR_ENABLED)
588 - && !(sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED);
589 - return (sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED)
590 - && !(sb_dqopt(sb)->flags & DQUOT_GROUP_SUSPENDED);
591 + return sb_dqopt(sb)->flags &
592 + dquot_state_flag(DQUOT_USAGE_ENABLED, type);
593 }
594
595 -static inline int sb_any_quota_enabled(struct super_block *sb)
596 +static inline int sb_has_quota_limits_enabled(struct super_block *sb, int type)
597 {
598 - return sb_has_quota_enabled(sb, USRQUOTA) ||
599 - sb_has_quota_enabled(sb, GRPQUOTA);
600 + return sb_dqopt(sb)->flags &
601 + dquot_state_flag(DQUOT_LIMITS_ENABLED, type);
602 }
603
604 static inline int sb_has_quota_suspended(struct super_block *sb, int type)
605 {
606 - if (type == USRQUOTA)
607 - return sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED;
608 - return sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED;
609 + return sb_dqopt(sb)->flags &
610 + dquot_state_flag(DQUOT_SUSPENDED, type);
611 }
612
613 static inline int sb_any_quota_suspended(struct super_block *sb)
614 @@ -95,6 +94,34 @@ static inline int sb_any_quota_suspended(struct super_block *sb)
615 sb_has_quota_suspended(sb, GRPQUOTA);
616 }
617
618 +/* Does kernel know about any quota information for given sb + type? */
619 +static inline int sb_has_quota_loaded(struct super_block *sb, int type)
620 +{
621 + /* Currently if anything is on, then quota usage is on as well */
622 + return sb_has_quota_usage_enabled(sb, type);
623 +}
624 +
625 +static inline int sb_any_quota_loaded(struct super_block *sb)
626 +{
627 + return sb_has_quota_loaded(sb, USRQUOTA) ||
628 + sb_has_quota_loaded(sb, GRPQUOTA);
629 +}
630 +
631 +static inline int sb_has_quota_active(struct super_block *sb, int type)
632 +{
633 + return sb_has_quota_loaded(sb, type) &&
634 + !sb_has_quota_suspended(sb, type);
635 +}
636 +
637 +static inline int sb_any_quota_active(struct super_block *sb)
638 +{
639 + return sb_has_quota_active(sb, USRQUOTA) ||
640 + sb_has_quota_active(sb, GRPQUOTA);
641 +}
642 +
643 +/* For backward compatibility until we remove all users */
644 +#define sb_any_quota_enabled(sb) sb_any_quota_active(sb)
645 +
646 /*
647 * Operations supported for diskquotas.
648 */
649 @@ -109,7 +136,7 @@ extern struct quotactl_ops vfs_quotactl_ops;
650 static inline void vfs_dq_init(struct inode *inode)
651 {
652 BUG_ON(!inode->i_sb);
653 - if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode))
654 + if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode))
655 inode->i_sb->dq_op->initialize(inode, -1);
656 }
657
658 @@ -117,7 +144,7 @@ static inline void vfs_dq_init(struct inode *inode)
659 * a transaction (deadlocks possible otherwise) */
660 static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
661 {
662 - if (sb_any_quota_enabled(inode->i_sb)) {
663 + if (sb_any_quota_active(inode->i_sb)) {
664 /* Used space is updated in alloc_space() */
665 if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA)
666 return 1;
667 @@ -137,7 +164,7 @@ static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
668
669 static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
670 {
671 - if (sb_any_quota_enabled(inode->i_sb)) {
672 + if (sb_any_quota_active(inode->i_sb)) {
673 /* Used space is updated in alloc_space() */
674 if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA)
675 return 1;
676 @@ -157,7 +184,7 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
677
678 static inline int vfs_dq_alloc_inode(struct inode *inode)
679 {
680 - if (sb_any_quota_enabled(inode->i_sb)) {
681 + if (sb_any_quota_active(inode->i_sb)) {
682 vfs_dq_init(inode);
683 if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA)
684 return 1;
685 @@ -167,7 +194,7 @@ static inline int vfs_dq_alloc_inode(struct inode *inode)
686
687 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
688 {
689 - if (sb_any_quota_enabled(inode->i_sb))
690 + if (sb_any_quota_active(inode->i_sb))
691 inode->i_sb->dq_op->free_space(inode, nr);
692 else
693 inode_sub_bytes(inode, nr);
694 @@ -181,7 +208,7 @@ static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
695
696 static inline void vfs_dq_free_inode(struct inode *inode)
697 {
698 - if (sb_any_quota_enabled(inode->i_sb))
699 + if (sb_any_quota_active(inode->i_sb))
700 inode->i_sb->dq_op->free_inode(inode, 1);
701 }
702
703 @@ -202,12 +229,12 @@ static inline int vfs_dq_off(struct super_block *sb, int remount)
704
705 #else
706
707 -static inline int sb_has_quota_enabled(struct super_block *sb, int type)
708 +static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
709 {
710 return 0;
711 }
712
713 -static inline int sb_any_quota_enabled(struct super_block *sb)
714 +static inline int sb_has_quota_limits_enabled(struct super_block *sb, int type)
715 {
716 return 0;
717 }
718 @@ -222,6 +249,25 @@ static inline int sb_any_quota_suspended(struct super_block *sb)
719 return 0;
720 }
721
722 +/* Does kernel know about any quota information for given sb + type? */
723 +static inline int sb_has_quota_loaded(struct super_block *sb, int type)
724 +{
725 + return 0;
726 +}
727 +
728 +static inline int sb_any_quota_loaded(struct super_block *sb)
729 +{
730 + return 0;
731 +}
732 +
733 +static inline int sb_any_quota_active(struct super_block *sb)
734 +{
735 + return 0;
736 +}
737 +
738 +/* For backward compatibility until we remove all users */
739 +#define sb_any_quota_enabled(sb) sb_any_quota_active(sb)
740 +
741 /*
742 * NO-OP when quota not configured.
743 */
744 --
745 1.5.2.4
746