From 6ae09575b3c951ad77c07d068b8dbbc09031b2d1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 16 Feb 2010 03:44:49 -0500 Subject: quota: special case Q_SYNC without device name The Q_SYNC command can be called without the path to a device, in which case it iterates over all superblocks. Special case this variant directly in sys_quotactl so that the other code always gets a superblock and doesn't need to deal with this case. Signed-off-by: Christoph Hellwig Signed-off-by: Jan Kara --- fs/quota/quota.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'fs/quota') diff --git a/fs/quota/quota.c b/fs/quota/quota.c index dcf7db91fc95..9fde5cd84f8d 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -124,10 +124,17 @@ void sync_quota_sb(struct super_block *sb, int type) } #endif -static void sync_dquots(int type) +static int quota_sync_all(int type) { struct super_block *sb; int cnt; + int ret; + + if (type >= MAXQUOTAS) + return -EINVAL; + ret = security_quotactl(Q_SYNC, type, 0, NULL); + if (ret) + return ret; spin_lock(&sb_lock); restart: @@ -157,6 +164,8 @@ restart: goto restart; } spin_unlock(&sb_lock); + + return 0; } static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, @@ -322,12 +331,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, case Q_SETQUOTA: return quota_setquota(sb, type, id, addr); case Q_SYNC: - if (sb) { - if (!sb->s_qcop->quota_sync) - return -ENOSYS; - sync_quota_sb(sb, type); - } else - sync_dquots(type); + if (!sb->s_qcop->quota_sync) + return -ENOSYS; + sync_quota_sb(sb, type); return 0; case Q_XQUOTAON: case Q_XQUOTAOFF: @@ -392,18 +398,26 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special, cmds = cmd >> SUBCMDSHIFT; type = cmd & SUBCMDMASK; - if (cmds != Q_SYNC || special) { - sb = quotactl_block(special); - if (IS_ERR(sb)) - return PTR_ERR(sb); + /* + * As a special case Q_SYNC can be called without a specific device. + * It will iterate all superblocks that have quota enabled and call + * the sync action on each of them. + */ + if (!special) { + if (cmds == Q_SYNC) + return quota_sync_all(type); + return -ENODEV; } + sb = quotactl_block(special); + if (IS_ERR(sb)) + return PTR_ERR(sb); + ret = check_quotactl_valid(sb, type, cmds, id); if (ret >= 0) ret = do_quotactl(sb, type, cmds, id, addr); - if (sb) - drop_super(sb); + drop_super(sb); return ret; } -- cgit v1.2.3