forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
d3b8632485
commit
3e2af67e66
|
@ -2385,6 +2385,86 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
|
|||
}
|
||||
EXPORT_SYMBOL(dquot_quota_on_mount);
|
||||
|
||||
static int dquot_quota_enable(struct super_block *sb, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
int type;
|
||||
struct quota_info *dqopt = sb_dqopt(sb);
|
||||
|
||||
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
|
||||
return -ENOSYS;
|
||||
/* Accounting cannot be turned on while fs is mounted */
|
||||
flags &= ~(FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT);
|
||||
if (!flags)
|
||||
return -EINVAL;
|
||||
for (type = 0; type < MAXQUOTAS; type++) {
|
||||
if (!(flags & qtype_enforce_flag(type)))
|
||||
continue;
|
||||
/* Can't enforce without accounting */
|
||||
if (!sb_has_quota_usage_enabled(sb, type))
|
||||
return -EINVAL;
|
||||
ret = dquot_enable(dqopt->files[type], type,
|
||||
dqopt->info[type].dqi_fmt_id,
|
||||
DQUOT_LIMITS_ENABLED);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
}
|
||||
return 0;
|
||||
out_err:
|
||||
/* Backout enforcement enablement we already did */
|
||||
for (type--; type >= 0; type--) {
|
||||
if (flags & qtype_enforce_flag(type))
|
||||
dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
|
||||
}
|
||||
/* Error code translation for better compatibility with XFS */
|
||||
if (ret == -EBUSY)
|
||||
ret = -EEXIST;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dquot_quota_disable(struct super_block *sb, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
int type;
|
||||
struct quota_info *dqopt = sb_dqopt(sb);
|
||||
|
||||
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
|
||||
return -ENOSYS;
|
||||
/*
|
||||
* We don't support turning off accounting via quotactl. In principle
|
||||
* quota infrastructure can do this but filesystems don't expect
|
||||
* userspace to be able to do it.
|
||||
*/
|
||||
if (flags &
|
||||
(FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Filter out limits not enabled */
|
||||
for (type = 0; type < MAXQUOTAS; type++)
|
||||
if (!sb_has_quota_limits_enabled(sb, type))
|
||||
flags &= ~qtype_enforce_flag(type);
|
||||
/* Nothing left? */
|
||||
if (!flags)
|
||||
return -EEXIST;
|
||||
for (type = 0; type < MAXQUOTAS; type++) {
|
||||
if (flags & qtype_enforce_flag(type)) {
|
||||
ret = dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
out_err:
|
||||
/* Backout enforcement disabling we already did */
|
||||
for (type--; type >= 0; type--) {
|
||||
if (flags & qtype_enforce_flag(type))
|
||||
dquot_enable(dqopt->files[type], type,
|
||||
dqopt->info[type].dqi_fmt_id,
|
||||
DQUOT_LIMITS_ENABLED);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline qsize_t qbtos(qsize_t blocks)
|
||||
{
|
||||
return blocks << QIF_DQBLKSIZE_BITS;
|
||||
|
@ -2614,6 +2694,17 @@ const struct quotactl_ops dquot_quotactl_ops = {
|
|||
};
|
||||
EXPORT_SYMBOL(dquot_quotactl_ops);
|
||||
|
||||
const struct quotactl_ops dquot_quotactl_sysfile_ops = {
|
||||
.quota_enable = dquot_quota_enable,
|
||||
.quota_disable = dquot_quota_disable,
|
||||
.quota_sync = dquot_quota_sync,
|
||||
.get_info = dquot_get_dqinfo,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk
|
||||
};
|
||||
EXPORT_SYMBOL(dquot_quotactl_sysfile_ops);
|
||||
|
||||
static int do_proc_dqstats(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
|
|
|
@ -166,6 +166,7 @@ static inline bool sb_has_quota_active(struct super_block *sb, int type)
|
|||
*/
|
||||
extern const struct dquot_operations dquot_operations;
|
||||
extern const struct quotactl_ops dquot_quotactl_ops;
|
||||
extern const struct quotactl_ops dquot_quotactl_sysfile_ops;
|
||||
|
||||
#else
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user