quota: Make VFS quotas use new interface for getting quota info
Create new internal interface for getting information about quota which contains everything needed for both VFS quotas and XFS quotas. Make VFS use this and hook it up to Q_GETINFO. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
@@ -2614,26 +2614,39 @@ out:
|
||||
EXPORT_SYMBOL(dquot_set_dqblk);
|
||||
|
||||
/* Generic routine for getting common part of quota file information */
|
||||
int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
|
||||
int dquot_get_state(struct super_block *sb, struct qc_state *state)
|
||||
{
|
||||
struct mem_dqinfo *mi;
|
||||
struct qc_type_state *tstate;
|
||||
struct quota_info *dqopt = sb_dqopt(sb);
|
||||
int type;
|
||||
|
||||
mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
if (!sb_has_quota_active(sb, type)) {
|
||||
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
return -ESRCH;
|
||||
memset(state, 0, sizeof(*state));
|
||||
for (type = 0; type < MAXQUOTAS; type++) {
|
||||
if (!sb_has_quota_active(sb, type))
|
||||
continue;
|
||||
tstate = state->s_state + type;
|
||||
mi = sb_dqopt(sb)->info + type;
|
||||
tstate->flags = QCI_ACCT_ENABLED;
|
||||
spin_lock(&dq_data_lock);
|
||||
if (mi->dqi_flags & DQF_SYS_FILE)
|
||||
tstate->flags |= QCI_SYSFILE;
|
||||
if (mi->dqi_flags & DQF_ROOT_SQUASH)
|
||||
tstate->flags |= QCI_ROOT_SQUASH;
|
||||
if (sb_has_quota_limits_enabled(sb, type))
|
||||
tstate->flags |= QCI_LIMITS_ENFORCED;
|
||||
tstate->spc_timelimit = mi->dqi_bgrace;
|
||||
tstate->ino_timelimit = mi->dqi_igrace;
|
||||
tstate->ino = dqopt->files[type]->i_ino;
|
||||
tstate->blocks = dqopt->files[type]->i_blocks;
|
||||
tstate->nextents = 1; /* We don't know... */
|
||||
spin_unlock(&dq_data_lock);
|
||||
}
|
||||
mi = sb_dqopt(sb)->info + type;
|
||||
spin_lock(&dq_data_lock);
|
||||
ii->dqi_bgrace = mi->dqi_bgrace;
|
||||
ii->dqi_igrace = mi->dqi_igrace;
|
||||
ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK;
|
||||
ii->dqi_valid = IIF_ALL;
|
||||
spin_unlock(&dq_data_lock);
|
||||
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dquot_get_dqinfo);
|
||||
EXPORT_SYMBOL(dquot_get_state);
|
||||
|
||||
/* Generic routine for setting common part of quota file information */
|
||||
int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
|
||||
@@ -2677,7 +2690,7 @@ const struct quotactl_ops dquot_quotactl_ops = {
|
||||
.quota_on = dquot_quota_on,
|
||||
.quota_off = dquot_quota_off,
|
||||
.quota_sync = dquot_quota_sync,
|
||||
.get_info = dquot_get_dqinfo,
|
||||
.get_state = dquot_get_state,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk
|
||||
@@ -2688,7 +2701,7 @@ 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,
|
||||
.get_state = dquot_get_state,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk
|
||||
|
@@ -118,13 +118,30 @@ static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
|
||||
|
||||
static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
|
||||
{
|
||||
struct if_dqinfo info;
|
||||
struct qc_state state;
|
||||
struct qc_type_state *tstate;
|
||||
struct if_dqinfo uinfo;
|
||||
int ret;
|
||||
|
||||
if (!sb->s_qcop->get_info)
|
||||
/* This checks whether qc_state has enough entries... */
|
||||
BUILD_BUG_ON(MAXQUOTAS > XQM_MAXQUOTAS);
|
||||
if (!sb->s_qcop->get_state)
|
||||
return -ENOSYS;
|
||||
ret = sb->s_qcop->get_info(sb, type, &info);
|
||||
if (!ret && copy_to_user(addr, &info, sizeof(info)))
|
||||
ret = sb->s_qcop->get_state(sb, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
tstate = state.s_state + type;
|
||||
if (!(tstate->flags & QCI_ACCT_ENABLED))
|
||||
return -ESRCH;
|
||||
memset(&uinfo, 0, sizeof(uinfo));
|
||||
uinfo.dqi_bgrace = tstate->spc_timelimit;
|
||||
uinfo.dqi_igrace = tstate->ino_timelimit;
|
||||
if (tstate->flags & QCI_SYSFILE)
|
||||
uinfo.dqi_flags |= DQF_SYS_FILE;
|
||||
if (tstate->flags & QCI_ROOT_SQUASH)
|
||||
uinfo.dqi_flags |= DQF_ROOT_SQUASH;
|
||||
uinfo.dqi_valid = IIF_ALL;
|
||||
if (!ret && copy_to_user(addr, &uinfo, sizeof(uinfo)))
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user