]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.suse/quota-Allow-to-separately-enable-quota-accounting-a.patch
Revert "Move xen patchset to new version's subdir."
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / quota-Allow-to-separately-enable-quota-accounting-a.patch
CommitLineData
00e5a55c
BS
1From: Jan Kara <jack@suse.cz>
2References: fate#302681
3Subject: [PATCH 05/28] quota: Allow to separately enable quota accounting and enforcing limits
4Patch-mainline: 2.6.29?
5
6Split DQUOT_USR_ENABLED (and DQUOT_GRP_ENABLED) into DQUOT_USR_USAGE_ENABLED
7and DQUOT_USR_LIMITS_ENABLED. This way we are able to separately enable /
8disable whether we should:
91) ignore quotas completely
102) just keep uptodate information about usage
113) actually enforce quota limits
12
13This is going to be useful when quota is treated as filesystem metadata - we
14then want to keep quota information uptodate all the time and just enable /
15disable limits enforcement.
16
17Signed-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
25diff --git a/fs/dquot.c b/fs/dquot.c
26index 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);
477diff --git a/fs/quota.c b/fs/quota.c
478index 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 }
517diff --git a/include/linux/quota.h b/include/linux/quota.h
518index 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 */
560diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
561index 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--
7451.5.2.4
746