diff options
| -rw-r--r-- | fs/quota/dquot.c | 91 | ||||
| -rw-r--r-- | include/linux/quotaops.h | 1 |
2 files changed, 92 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 | } |
| 2386 | EXPORT_SYMBOL(dquot_quota_on_mount); | 2386 | EXPORT_SYMBOL(dquot_quota_on_mount); |
| 2387 | 2387 | ||
| 2388 | static 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; | ||
| 2413 | out_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 | |||
| 2425 | static 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; | ||
| 2457 | out_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 | |||
| 2388 | static inline qsize_t qbtos(qsize_t blocks) | 2468 | static 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 | }; |
| 2615 | EXPORT_SYMBOL(dquot_quotactl_ops); | 2695 | EXPORT_SYMBOL(dquot_quotactl_ops); |
| 2616 | 2696 | ||
| 2697 | const 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 | }; | ||
| 2706 | EXPORT_SYMBOL(dquot_quotactl_sysfile_ops); | ||
| 2707 | |||
| 2617 | static int do_proc_dqstats(struct ctl_table *table, int write, | 2708 | static 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 | { |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index ff0b665591d0..df73258cca47 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
| @@ -166,6 +166,7 @@ static inline bool sb_has_quota_active(struct super_block *sb, int type) | |||
| 166 | */ | 166 | */ |
| 167 | extern const struct dquot_operations dquot_operations; | 167 | extern const struct dquot_operations dquot_operations; |
| 168 | extern const struct quotactl_ops dquot_quotactl_ops; | 168 | extern const struct quotactl_ops dquot_quotactl_ops; |
| 169 | extern const struct quotactl_ops dquot_quotactl_sysfile_ops; | ||
| 169 | 170 | ||
| 170 | #else | 171 | #else |
| 171 | 172 | ||
