aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota/dquot.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-10-06 12:40:51 -0400
committerJan Kara <jack@suse.cz>2015-01-30 06:50:32 -0500
commit3e2af67e66ff025796af1a8a1fcbb4236304f90c (patch)
treee7205670d1994a66a47ad647151dcadcd9b3ae1c /fs/quota/dquot.c
parentd3b863248577504f6eecca2a464d6ddf86b71584 (diff)
quota: Add ->quota_{enable,disable} callbacks for VFS quotas
Add functions which translate ->quota_enable / ->quota_disable calls into appropriate changes in VFS quota. This will enable filesystems supporting VFS quota files in system inodes to be controlled via Q_XQUOTA[ON|OFF] quotactls for better userspace compatibility. Also provide a vector for quotactl using these functions which can be used by filesystems with quota files stored in hidden system files. Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota/dquot.c')
-rw-r--r--fs/quota/dquot.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 29eb9dc5728a..b47d0c17ea6f 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2385,6 +2385,86 @@ out:
2385} 2385}
2386EXPORT_SYMBOL(dquot_quota_on_mount); 2386EXPORT_SYMBOL(dquot_quota_on_mount);
2387 2387
2388static int dquot_quota_enable(struct super_block *sb, unsigned int flags)
2389{
2390 int ret;
2391 int type;
2392 struct quota_info *dqopt = sb_dqopt(sb);
2393
2394 if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
2395 return -ENOSYS;
2396 /* Accounting cannot be turned on while fs is mounted */
2397 flags &= ~(FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT);
2398 if (!flags)
2399 return -EINVAL;
2400 for (type = 0; type < MAXQUOTAS; type++) {
2401 if (!(flags & qtype_enforce_flag(type)))
2402 continue;
2403 /* Can't enforce without accounting */
2404 if (!sb_has_quota_usage_enabled(sb, type))
2405 return -EINVAL;
2406 ret = dquot_enable(dqopt->files[type], type,
2407 dqopt->info[type].dqi_fmt_id,
2408 DQUOT_LIMITS_ENABLED);
2409 if (ret < 0)
2410 goto out_err;
2411 }
2412 return 0;
2413out_err:
2414 /* Backout enforcement enablement we already did */
2415 for (type--; type >= 0; type--) {
2416 if (flags & qtype_enforce_flag(type))
2417 dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
2418 }
2419 /* Error code translation for better compatibility with XFS */
2420 if (ret == -EBUSY)
2421 ret = -EEXIST;
2422 return ret;
2423}
2424
2425static int dquot_quota_disable(struct super_block *sb, unsigned int flags)
2426{
2427 int ret;
2428 int type;
2429 struct quota_info *dqopt = sb_dqopt(sb);
2430
2431 if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
2432 return -ENOSYS;
2433 /*
2434 * We don't support turning off accounting via quotactl. In principle
2435 * quota infrastructure can do this but filesystems don't expect
2436 * userspace to be able to do it.
2437 */
2438 if (flags &
2439 (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT))
2440 return -EOPNOTSUPP;
2441
2442 /* Filter out limits not enabled */
2443 for (type = 0; type < MAXQUOTAS; type++)
2444 if (!sb_has_quota_limits_enabled(sb, type))
2445 flags &= ~qtype_enforce_flag(type);
2446 /* Nothing left? */
2447 if (!flags)
2448 return -EEXIST;
2449 for (type = 0; type < MAXQUOTAS; type++) {
2450 if (flags & qtype_enforce_flag(type)) {
2451 ret = dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
2452 if (ret < 0)
2453 goto out_err;
2454 }
2455 }
2456 return 0;
2457out_err:
2458 /* Backout enforcement disabling we already did */
2459 for (type--; type >= 0; type--) {
2460 if (flags & qtype_enforce_flag(type))
2461 dquot_enable(dqopt->files[type], type,
2462 dqopt->info[type].dqi_fmt_id,
2463 DQUOT_LIMITS_ENABLED);
2464 }
2465 return ret;
2466}
2467
2388static inline qsize_t qbtos(qsize_t blocks) 2468static inline qsize_t qbtos(qsize_t blocks)
2389{ 2469{
2390 return blocks << QIF_DQBLKSIZE_BITS; 2470 return blocks << QIF_DQBLKSIZE_BITS;
@@ -2614,6 +2694,17 @@ const struct quotactl_ops dquot_quotactl_ops = {
2614}; 2694};
2615EXPORT_SYMBOL(dquot_quotactl_ops); 2695EXPORT_SYMBOL(dquot_quotactl_ops);
2616 2696
2697const struct quotactl_ops dquot_quotactl_sysfile_ops = {
2698 .quota_enable = dquot_quota_enable,
2699 .quota_disable = dquot_quota_disable,
2700 .quota_sync = dquot_quota_sync,
2701 .get_info = dquot_get_dqinfo,
2702 .set_info = dquot_set_dqinfo,
2703 .get_dqblk = dquot_get_dqblk,
2704 .set_dqblk = dquot_set_dqblk
2705};
2706EXPORT_SYMBOL(dquot_quotactl_sysfile_ops);
2707
2617static int do_proc_dqstats(struct ctl_table *table, int write, 2708static int do_proc_dqstats(struct ctl_table *table, int write,
2618 void __user *buffer, size_t *lenp, loff_t *ppos) 2709 void __user *buffer, size_t *lenp, loff_t *ppos)
2619{ 2710{