Skip to content

Commit 3e2af67

Browse files
committed
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>
1 parent d3b8632 commit 3e2af67

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

fs/quota/dquot.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,6 +2385,86 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
23852385
}
23862386
EXPORT_SYMBOL(dquot_quota_on_mount);
23872387

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+
23882468
static inline qsize_t qbtos(qsize_t blocks)
23892469
{
23902470
return blocks << QIF_DQBLKSIZE_BITS;
@@ -2614,6 +2694,17 @@ const struct quotactl_ops dquot_quotactl_ops = {
26142694
};
26152695
EXPORT_SYMBOL(dquot_quotactl_ops);
26162696

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+
26172708
static int do_proc_dqstats(struct ctl_table *table, int write,
26182709
void __user *buffer, size_t *lenp, loff_t *ppos)
26192710
{

include/linux/quotaops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ static inline bool sb_has_quota_active(struct super_block *sb, int type)
166166
*/
167167
extern const struct dquot_operations dquot_operations;
168168
extern const struct quotactl_ops dquot_quotactl_ops;
169+
extern const struct quotactl_ops dquot_quotactl_sysfile_ops;
169170

170171
#else
171172

0 commit comments

Comments
 (0)