quota: Allow each filesystem to specify which quota types it supports
authorJan Kara <jack@suse.cz>
Tue, 30 Sep 2014 08:43:09 +0000 (10:43 +0200)
committerJan Kara <jack@suse.cz>
Mon, 10 Nov 2014 09:06:08 +0000 (10:06 +0100)
Currently all filesystems supporting VFS quota support user and group
quotas. With introduction of project quotas this is going to change so
make sure filesystem isn't called for quota type it doesn't support by
introduction of a bitmask determining which quota types each filesystem
supports.

Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/quota/quota.c
fs/super.c
include/linux/fs.h
include/linux/quota.h

index 75621649dbd76dd997aa96462d5d2b6c2124e5a9..2aa4151f99d2e5e9183adfb34e2c31da24e2faa2 100644 (file)
@@ -47,8 +47,11 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
 
 static void quota_sync_one(struct super_block *sb, void *arg)
 {
-       if (sb->s_qcop && sb->s_qcop->quota_sync)
-               sb->s_qcop->quota_sync(sb, *(int *)arg);
+       int type = *(int *)arg;
+
+       if (sb->s_qcop && sb->s_qcop->quota_sync &&
+           (sb->s_quota_types & (1 << type)))
+               sb->s_qcop->quota_sync(sb, type);
 }
 
 static int quota_sync_all(int type)
@@ -297,8 +300,14 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
 
        if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
                return -EINVAL;
+       /*
+        * Quota not supported on this fs? Check this before s_quota_types
+        * since they needn't be set if quota is not supported at all.
+        */
        if (!sb->s_qcop)
                return -ENOSYS;
+       if (!(sb->s_quota_types & (1 << type)))
+               return -EINVAL;
 
        ret = check_quotactl_permission(sb, type, cmd, id);
        if (ret < 0)
index eae088f6aaaeb6e8a3380adad19fb66feebe9905..4512281df8ffbaf9556a7831ed8289bf94d41eef 100644 (file)
@@ -218,6 +218,12 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
        atomic_set(&s->s_active, 1);
        mutex_init(&s->s_vfs_rename_mutex);
        lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
+       /*
+        * For now MAXQUOTAS check in do_quotactl() will limit quota type
+        * appropriately. When each fs sets allowed_types, we can remove the
+        * line below
+        */
+       s->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
        mutex_init(&s->s_dquot.dqio_mutex);
        mutex_init(&s->s_dquot.dqonoff_mutex);
        s->s_maxbytes = MAX_NON_LFS;
index 9ab779e8a63ccd7785637dd9017fc3bc69ff260f..cf55a5483d40d7681cabf8b00fd678dc6edcb574 100644 (file)
@@ -1224,6 +1224,7 @@ struct super_block {
        struct backing_dev_info *s_bdi;
        struct mtd_info         *s_mtd;
        struct hlist_node       s_instances;
+       unsigned int            s_quota_types;  /* Bitmask of supported quota types */
        struct quota_info       s_dquot;        /* Diskquota specific options */
 
        struct sb_writers       s_writers;
index 80d345a3524cc52b8915b79d2e8ec916131a143c..50978b781a19c4d82c60c44918f5049c4cd25272 100644 (file)
@@ -56,6 +56,11 @@ enum quota_type {
        PRJQUOTA = 2,           /* element used for project quotas */
 };
 
+/* Masks for quota types when used as a bitmask */
+#define QTYPE_MASK_USR (1 << USRQUOTA)
+#define QTYPE_MASK_GRP (1 << GRPQUOTA)
+#define QTYPE_MASK_PRJ (1 << PRJQUOTA)
+
 typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
 typedef long long qsize_t;     /* Type in which we store sizes */