Commit 555b2c3d authored by Eric Sandeen's avatar Eric Sandeen Committed by Jan Kara

quota: honor quota type in Q_XGETQSTAT[V] calls

The code in quota_getstate and quota_getstatev is strange; it
says the returned fs_quota_stat[v] structure has room for only
one type of time limits, so fills it in with the first enabled
quota, even though every quotactl command must have a type sent
in by the user.

Instead of just picking the first enabled quota, fill in the
reply with the timers for the quota type that was actually
requested.
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarEric Sandeen <sandeen@redhat.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 936bbf3a
...@@ -331,9 +331,9 @@ static int quota_state_to_flags(struct qc_state *state) ...@@ -331,9 +331,9 @@ static int quota_state_to_flags(struct qc_state *state)
return flags; return flags;
} }
static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs) static int quota_getstate(struct super_block *sb, int type,
struct fs_quota_stat *fqs)
{ {
int type;
struct qc_state state; struct qc_state state;
int ret; int ret;
...@@ -349,14 +349,7 @@ static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs) ...@@ -349,14 +349,7 @@ static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs)
if (!fqs->qs_flags) if (!fqs->qs_flags)
return -ENOSYS; return -ENOSYS;
fqs->qs_incoredqs = state.s_incoredqs; fqs->qs_incoredqs = state.s_incoredqs;
/*
* GETXSTATE quotactl has space for just one set of time limits so
* report them for the first enabled quota type
*/
for (type = 0; type < MAXQUOTAS; type++)
if (state.s_state[type].flags & QCI_ACCT_ENABLED)
break;
BUG_ON(type == MAXQUOTAS);
fqs->qs_btimelimit = state.s_state[type].spc_timelimit; fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
fqs->qs_itimelimit = state.s_state[type].ino_timelimit; fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit; fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
...@@ -391,22 +384,22 @@ static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs) ...@@ -391,22 +384,22 @@ static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs)
return 0; return 0;
} }
static int quota_getxstate(struct super_block *sb, void __user *addr) static int quota_getxstate(struct super_block *sb, int type, void __user *addr)
{ {
struct fs_quota_stat fqs; struct fs_quota_stat fqs;
int ret; int ret;
if (!sb->s_qcop->get_state) if (!sb->s_qcop->get_state)
return -ENOSYS; return -ENOSYS;
ret = quota_getstate(sb, &fqs); ret = quota_getstate(sb, type, &fqs);
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
return -EFAULT; return -EFAULT;
return ret; return ret;
} }
static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs) static int quota_getstatev(struct super_block *sb, int type,
struct fs_quota_statv *fqs)
{ {
int type;
struct qc_state state; struct qc_state state;
int ret; int ret;
...@@ -422,14 +415,7 @@ static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs) ...@@ -422,14 +415,7 @@ static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs)
if (!fqs->qs_flags) if (!fqs->qs_flags)
return -ENOSYS; return -ENOSYS;
fqs->qs_incoredqs = state.s_incoredqs; fqs->qs_incoredqs = state.s_incoredqs;
/*
* GETXSTATV quotactl has space for just one set of time limits so
* report them for the first enabled quota type
*/
for (type = 0; type < MAXQUOTAS; type++)
if (state.s_state[type].flags & QCI_ACCT_ENABLED)
break;
BUG_ON(type == MAXQUOTAS);
fqs->qs_btimelimit = state.s_state[type].spc_timelimit; fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
fqs->qs_itimelimit = state.s_state[type].ino_timelimit; fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit; fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
...@@ -455,7 +441,7 @@ static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs) ...@@ -455,7 +441,7 @@ static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs)
return 0; return 0;
} }
static int quota_getxstatev(struct super_block *sb, void __user *addr) static int quota_getxstatev(struct super_block *sb, int type, void __user *addr)
{ {
struct fs_quota_statv fqs; struct fs_quota_statv fqs;
int ret; int ret;
...@@ -474,7 +460,7 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr) ...@@ -474,7 +460,7 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
default: default:
return -EINVAL; return -EINVAL;
} }
ret = quota_getstatev(sb, &fqs); ret = quota_getstatev(sb, type, &fqs);
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
return -EFAULT; return -EFAULT;
return ret; return ret;
...@@ -744,9 +730,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, ...@@ -744,9 +730,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
case Q_XQUOTARM: case Q_XQUOTARM:
return quota_rmxquota(sb, addr); return quota_rmxquota(sb, addr);
case Q_XGETQSTAT: case Q_XGETQSTAT:
return quota_getxstate(sb, addr); return quota_getxstate(sb, type, addr);
case Q_XGETQSTATV: case Q_XGETQSTATV:
return quota_getxstatev(sb, addr); return quota_getxstatev(sb, type, addr);
case Q_XSETQLIM: case Q_XSETQLIM:
return quota_setxquota(sb, type, id, addr); return quota_setxquota(sb, type, id, addr);
case Q_XGETQUOTA: case Q_XGETQUOTA:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment