aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds2014-12-10 15:43:30 -0800
committerLinus Torvalds2014-12-10 15:43:30 -0800
commit1366f5d3129f2abde606214de7afc3dd61781fa3 (patch)
treeb275b18e90bd24d64e09894a812bbd7dd1c424f5
parent4b0a268eeccae14d42ff5fb9f19b612913c0007c (diff)
parentfdf2657bc81b10dee856ec9f8fe5b201c0561e9d (diff)
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull quota updates from Jan Kara: "Quota improvements and some minor cleanups. The main portion in the pull request are changes which move i_dquot array from struct inode into fs-private part of an inode which saves memory for filesystems which don't use VFS quotas" * 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: udf: One function call less in udf_fill_super() after error detection udf: Deletion of unnecessary checks before the function call "iput" jbd: Deletion of an unnecessary check before the function call "iput" vfs: Remove i_dquot field from inode jfs: Convert to private i_dquot field reiserfs: Convert to private i_dquot field ocfs2: Convert to private i_dquot field ext4: Convert to private i_dquot field ext3: Convert to private i_dquot field ext2: Convert to private i_dquot field quota: Use function to provide i_dquot pointers xfs: Set allowed quota types gfs2: Set allowed quota types quota: Allow each filesystem to specify which quota types it supports quota: Remove const from function declarations quota: Add log level to printk
-rw-r--r--fs/ext2/ext2.h3
-rw-r--r--fs/ext2/super.c10
-rw-r--r--fs/ext3/ext3.h4
-rw-r--r--fs/ext3/super.c10
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/super.c8
-rw-r--r--fs/gfs2/ops_fstype.c1
-rw-r--r--fs/inode.c3
-rw-r--r--fs/jbd/journal.c3
-rw-r--r--fs/jfs/jfs_incore.h3
-rw-r--r--fs/jfs/super.c9
-rw-r--r--fs/ocfs2/inode.h2
-rw-r--r--fs/ocfs2/super.c8
-rw-r--r--fs/quota/dquot.c59
-rw-r--r--fs/quota/quota.c13
-rw-r--r--fs/reiserfs/reiserfs.h4
-rw-r--r--fs/reiserfs/super.c11
-rw-r--r--fs/udf/super.c11
-rw-r--r--fs/xfs/xfs_super.c1
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/quota.h5
-rw-r--r--include/linux/quotaops.h8
22 files changed, 138 insertions, 47 deletions
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index d9a17d0b124d..e4279ead4a05 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -689,6 +689,9 @@ struct ext2_inode_info {
struct mutex truncate_mutex;
struct inode vfs_inode;
struct list_head i_orphan; /* unlinked but open inodes */
+#ifdef CONFIG_QUOTA
+ struct dquot *i_dquot[MAXQUOTAS];
+#endif
};
/*
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 170dc41e8bf4..ae55fddc26a9 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -166,6 +166,10 @@ static struct inode *ext2_alloc_inode(struct super_block *sb)
return NULL;
ei->i_block_alloc_info = NULL;
ei->vfs_inode.i_version = 1;
+#ifdef CONFIG_QUOTA
+ memset(&ei->i_dquot, 0, sizeof(ei->i_dquot));
+#endif
+
return &ei->vfs_inode;
}
@@ -303,6 +307,10 @@ static int ext2_show_options(struct seq_file *seq, struct dentry *root)
#ifdef CONFIG_QUOTA
static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off);
static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
+static struct dquot **ext2_get_dquots(struct inode *inode)
+{
+ return EXT2_I(inode)->i_dquot;
+}
#endif
static const struct super_operations ext2_sops = {
@@ -320,6 +328,7 @@ static const struct super_operations ext2_sops = {
#ifdef CONFIG_QUOTA
.quota_read = ext2_quota_read,
.quota_write = ext2_quota_write,
+ .get_dquots = ext2_get_dquots,
#endif
};
@@ -1090,6 +1099,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA
sb->dq_op = &dquot_operations;
sb->s_qcop = &dquot_quotactl_ops;
+ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
#endif
root = ext2_iget(sb, EXT2_ROOT_INO);
diff --git a/fs/ext3/ext3.h b/fs/ext3/ext3.h
index fc3cdcf24aed..f483a80b3fe7 100644
--- a/fs/ext3/ext3.h
+++ b/fs/ext3/ext3.h
@@ -615,6 +615,10 @@ struct ext3_inode_info {
atomic_t i_sync_tid;
atomic_t i_datasync_tid;
+#ifdef CONFIG_QUOTA
+ struct dquot *i_dquot[MAXQUOTAS];
+#endif
+
struct inode vfs_inode;
};
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index eb742d0e67ff..9b4e7d750d4f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -485,6 +485,10 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
ei->vfs_inode.i_version = 1;
atomic_set(&ei->i_datasync_tid, 0);
atomic_set(&ei->i_sync_tid, 0);
+#ifdef CONFIG_QUOTA
+ memset(&ei->i_dquot, 0, sizeof(ei->i_dquot));
+#endif
+
return &ei->vfs_inode;
}
@@ -764,6 +768,10 @@ static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
size_t len, loff_t off);
static ssize_t ext3_quota_write(struct super_block *sb, int type,
const char *data, size_t len, loff_t off);
+static struct dquot **ext3_get_dquots(struct inode *inode)
+{
+ return EXT3_I(inode)->i_dquot;
+}
static const struct dquot_operations ext3_quota_operations = {
.write_dquot = ext3_write_dquot,
@@ -803,6 +811,7 @@ static const struct super_operations ext3_sops = {
#ifdef CONFIG_QUOTA
.quota_read = ext3_quota_read,
.quota_write = ext3_quota_write,
+ .get_dquots = ext3_get_dquots,
#endif
.bdev_try_to_free_page = bdev_try_to_free_page,
};
@@ -2001,6 +2010,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA
sb->s_qcop = &ext3_qctl_operations;
sb->dq_op = &ext3_quota_operations;
+ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
#endif
memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index c55a1faaed58..db3f772e57ae 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -941,6 +941,10 @@ struct ext4_inode_info {
tid_t i_sync_tid;
tid_t i_datasync_tid;
+#ifdef CONFIG_QUOTA
+ struct dquot *i_dquot[MAXQUOTAS];
+#endif
+
/* Precomputed uuid+inum+igen checksum for seeding inode checksums */
__u32 i_csum_seed;
};
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2c9e6864abd9..63e802b8ec68 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -892,6 +892,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
spin_lock_init(&(ei->i_block_reservation_lock));
#ifdef CONFIG_QUOTA
ei->i_reserved_quota = 0;
+ memset(&ei->i_dquot, 0, sizeof(ei->i_dquot));
#endif
ei->jinode = NULL;
INIT_LIST_HEAD(&ei->i_rsv_conversion_list);
@@ -1068,6 +1069,11 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
unsigned int flags);
static int ext4_enable_quotas(struct super_block *sb);
+static struct dquot **ext4_get_dquots(struct inode *inode)
+{
+ return EXT4_I(inode)->i_dquot;
+}
+
static const struct dquot_operations ext4_quota_operations = {
.get_reserved_space = ext4_get_reserved_space,
.write_dquot = ext4_write_dquot,
@@ -1117,6 +1123,7 @@ static const struct super_operations ext4_sops = {
#ifdef CONFIG_QUOTA
.quota_read = ext4_quota_read,
.quota_write = ext4_quota_write,
+ .get_dquots = ext4_get_dquots,
#endif
.bdev_try_to_free_page = bdev_try_to_free_page,
};
@@ -3932,6 +3939,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->s_qcop = &ext4_qctl_sysfile_operations;
else
sb->s_qcop = &ext4_qctl_operations;
+ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
#endif
memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index b5803acb8818..8633ad328ee2 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1074,6 +1074,7 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
sb->s_export_op = &gfs2_export_ops;
sb->s_xattr = gfs2_xattr_handlers;
sb->s_qcop = &gfs2_quotactl_ops;
+ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
sb->s_time_gran = 1;
sb->s_maxbytes = MAX_LFS_FILESIZE;
diff --git a/fs/inode.c b/fs/inode.c
index 26753ba7b6d6..2ed95f7caa4f 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -143,9 +143,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_blocks = 0;
inode->i_bytes = 0;
inode->i_generation = 0;
-#ifdef CONFIG_QUOTA
- memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
-#endif
inode->i_pipe = NULL;
inode->i_bdev = NULL;
inode->i_cdev = NULL;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index aab8549591e7..c46a79adb6ad 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -1373,8 +1373,7 @@ int journal_destroy(journal_t *journal)
}
mutex_unlock(&journal->j_checkpoint_mutex);
- if (journal->j_inode)
- iput(journal->j_inode);
+ iput(journal->j_inode);
if (journal->j_revoke)
journal_destroy_revoke(journal);
kfree(journal->j_wbuf);
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index cf47f09e8ac8..fa7e795bd8ae 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -94,6 +94,9 @@ struct jfs_inode_info {
unchar _inline_ea[128]; /* 128: inline extended attr */
} link;
} u;
+#ifdef CONFIG_QUOTA
+ struct dquot *i_dquot[MAXQUOTAS];
+#endif
u32 dev; /* will die when we get wide dev_t */
struct inode vfs_inode;
};
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 93e897e588a8..16c3a9556634 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -117,6 +117,9 @@ static struct inode *jfs_alloc_inode(struct super_block *sb)
jfs_inode = kmem_cache_alloc(jfs_inode_cachep, GFP_NOFS);
if (!jfs_inode)
return NULL;
+#ifdef CONFIG_QUOTA
+ memset(&jfs_inode->i_dquot, 0, sizeof(jfs_inode->i_dquot));
+#endif
return &jfs_inode->vfs_inode;
}
@@ -537,6 +540,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA
sb->dq_op = &dquot_operations;
sb->s_qcop = &dquot_quotactl_ops;
+ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
#endif
/*
@@ -836,6 +840,10 @@ out:
return len - towrite;
}
+static struct dquot **jfs_get_dquots(struct inode *inode)
+{
+ return JFS_IP(inode)->i_dquot;
+}
#endif
static const struct super_operations jfs_super_operations = {
@@ -854,6 +862,7 @@ static const struct super_operations jfs_super_operations = {
#ifdef CONFIG_QUOTA
.quota_read = jfs_quota_read,
.quota_write = jfs_quota_write,
+ .get_dquots = jfs_get_dquots,
#endif
};
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index a9b76de46047..ca3431ee7f24 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -80,6 +80,8 @@ struct ocfs2_inode_info
*/
tid_t i_sync_tid;
tid_t i_datasync_tid;
+
+ struct dquot *i_dquot[MAXQUOTAS];
};
/*
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 93c85bc745e1..0945814ddb7b 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -143,6 +143,11 @@ static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend);
static int ocfs2_enable_quotas(struct ocfs2_super *osb);
static void ocfs2_disable_quotas(struct ocfs2_super *osb);
+static struct dquot **ocfs2_get_dquots(struct inode *inode)
+{
+ return OCFS2_I(inode)->i_dquot;
+}
+
static const struct super_operations ocfs2_sops = {
.statfs = ocfs2_statfs,
.alloc_inode = ocfs2_alloc_inode,
@@ -155,6 +160,7 @@ static const struct super_operations ocfs2_sops = {
.show_options = ocfs2_show_options,
.quota_read = ocfs2_quota_read,
.quota_write = ocfs2_quota_write,
+ .get_dquots = ocfs2_get_dquots,
};
enum {
@@ -563,6 +569,7 @@ static struct inode *ocfs2_alloc_inode(struct super_block *sb)
oi->i_sync_tid = 0;
oi->i_datasync_tid = 0;
+ memset(&oi->i_dquot, 0, sizeof(oi->i_dquot));
jbd2_journal_init_jbd_inode(&oi->ip_jinode, &oi->vfs_inode);
return &oi->vfs_inode;
@@ -2073,6 +2080,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
sb->s_export_op = &ocfs2_export_ops;
sb->s_qcop = &ocfs2_quotactl_ops;
sb->dq_op = &ocfs2_quota_operations;
+ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
sb->s_xattr = ocfs2_xattr_handlers;
sb->s_time_gran = 1;
sb->s_flags |= MS_NOATIME;
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 6b4527216a7f..8f0acef3d184 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -893,6 +893,11 @@ out:
}
EXPORT_SYMBOL(dqget);
+static inline struct dquot **i_dquot(struct inode *inode)
+{
+ return inode->i_sb->s_op->get_dquots(inode);
+}
+
static int dqinit_needed(struct inode *inode, int type)
{
int cnt;
@@ -900,9 +905,9 @@ static int dqinit_needed(struct inode *inode, int type)
if (IS_NOQUOTA(inode))
return 0;
if (type != -1)
- return !inode->i_dquot[type];
+ return !i_dquot(inode)[type];
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- if (!inode->i_dquot[cnt])
+ if (!i_dquot(inode)[cnt])
return 1;
return 0;
}
@@ -965,9 +970,9 @@ static void add_dquot_ref(struct super_block *sb, int type)
static void remove_inode_dquot_ref(struct inode *inode, int type,
struct list_head *tofree_head)
{
- struct dquot *dquot = inode->i_dquot[type];
+ struct dquot *dquot = i_dquot(inode)[type];
- inode->i_dquot[type] = NULL;
+ i_dquot(inode)[type] = NULL;
if (!dquot)
return;
@@ -1402,7 +1407,7 @@ static void __dquot_initialize(struct inode *inode, int type)
* we check it without locking here to avoid unnecessary
* dqget()/dqput() calls.
*/
- if (inode->i_dquot[cnt])
+ if (i_dquot(inode)[cnt])
continue;
init_needed = 1;
@@ -1433,8 +1438,8 @@ static void __dquot_initialize(struct inode *inode, int type)
/* We could race with quotaon or dqget() could have failed */
if (!got[cnt])
continue;
- if (!inode->i_dquot[cnt]) {
- inode->i_dquot[cnt] = got[cnt];
+ if (!i_dquot(inode)[cnt]) {
+ i_dquot(inode)[cnt] = got[cnt];
got[cnt] = NULL;
/*
* Make quota reservation system happy if someone
@@ -1442,7 +1447,7 @@ static void __dquot_initialize(struct inode *inode, int type)
*/
rsv = inode_get_rsv_space(inode);
if (unlikely(rsv))
- dquot_resv_space(inode->i_dquot[cnt], rsv);
+ dquot_resv_space(i_dquot(inode)[cnt], rsv);
}
}
out_err:
@@ -1472,8 +1477,8 @@ static void __dquot_drop(struct inode *inode)
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- put[cnt] = inode->i_dquot[cnt];
- inode->i_dquot[cnt] = NULL;
+ put[cnt] = i_dquot(inode)[cnt];
+ i_dquot(inode)[cnt] = NULL;
}
spin_unlock(&dq_data_lock);
dqput_all(put);
@@ -1494,7 +1499,7 @@ void dquot_drop(struct inode *inode)
* add quota pointers back anyway.
*/
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt])
+ if (i_dquot(inode)[cnt])
break;
}
@@ -1595,7 +1600,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
{
int cnt, ret = 0, index;
struct dquot_warn warn[MAXQUOTAS];
- struct dquot **dquots = inode->i_dquot;
+ struct dquot **dquots = i_dquot(inode);
int reserve = flags & DQUOT_SPACE_RESERVE;
if (!dquot_active(inode)) {
@@ -1643,11 +1648,11 @@ EXPORT_SYMBOL(__dquot_alloc_space);
/*
* This operation can block, but only after everything is updated
*/
-int dquot_alloc_inode(const struct inode *inode)
+int dquot_alloc_inode(struct inode *inode)
{
int cnt, ret = 0, index;
struct dquot_warn warn[MAXQUOTAS];
- struct dquot * const *dquots = inode->i_dquot;
+ struct dquot * const *dquots = i_dquot(inode);
if (!dquot_active(inode))
return 0;
@@ -1696,14 +1701,14 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
spin_lock(&dq_data_lock);
/* Claim reserved quotas to allocated quotas */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt])
- dquot_claim_reserved_space(inode->i_dquot[cnt],
+ if (i_dquot(inode)[cnt])
+ dquot_claim_reserved_space(i_dquot(inode)[cnt],
number);
}
/* Update inode bytes */
inode_claim_rsv_space(inode, number);
spin_unlock(&dq_data_lock);
- mark_all_dquot_dirty(inode->i_dquot);
+ mark_all_dquot_dirty(i_dquot(inode));
srcu_read_unlock(&dquot_srcu, index);
return 0;
}
@@ -1725,14 +1730,14 @@ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
spin_lock(&dq_data_lock);
/* Claim reserved quotas to allocated quotas */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt])
- dquot_reclaim_reserved_space(inode->i_dquot[cnt],
+ if (i_dquot(inode)[cnt])
+ dquot_reclaim_reserved_space(i_dquot(inode)[cnt],
number);
}
/* Update inode bytes */
inode_reclaim_rsv_space(inode, number);
spin_unlock(&dq_data_lock);
- mark_all_dquot_dirty(inode->i_dquot);
+ mark_all_dquot_dirty(i_dquot(inode));
srcu_read_unlock(&dquot_srcu, index);
return;
}
@@ -1745,7 +1750,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
{
unsigned int cnt;
struct dquot_warn warn[MAXQUOTAS];
- struct dquot **dquots = inode->i_dquot;
+ struct dquot **dquots = i_dquot(inode);
int reserve = flags & DQUOT_SPACE_RESERVE, index;
if (!dquot_active(inode)) {
@@ -1784,11 +1789,11 @@ EXPORT_SYMBOL(__dquot_free_space);
/*
* This operation can block, but only after everything is updated
*/
-void dquot_free_inode(const struct inode *inode)
+void dquot_free_inode(struct inode *inode)
{
unsigned int cnt;
struct dquot_warn warn[MAXQUOTAS];
- struct dquot * const *dquots = inode->i_dquot;
+ struct dquot * const *dquots = i_dquot(inode);
int index;
if (!dquot_active(inode))
@@ -1865,7 +1870,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
if (!sb_has_quota_active(inode->i_sb, cnt))
continue;
is_valid[cnt] = 1;
- transfer_from[cnt] = inode->i_dquot[cnt];
+ transfer_from[cnt] = i_dquot(inode)[cnt];
ret = check_idq(transfer_to[cnt], 1, &warn_to[cnt]);
if (ret)
goto over_quota;
@@ -1901,7 +1906,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
dquot_incr_space(transfer_to[cnt], cur_space);
dquot_resv_space(transfer_to[cnt], rsv_space);
- inode->i_dquot[cnt] = transfer_to[cnt];
+ i_dquot(inode)[cnt] = transfer_to[cnt];
}
spin_unlock(&dq_data_lock);
@@ -2743,8 +2748,8 @@ static int __init dquot_init(void)
for (i = 0; i < nr_hash; i++)
INIT_HLIST_HEAD(dquot_hash + i);
- printk("Dquot-cache hash table entries: %ld (order %ld, %ld bytes)\n",
- nr_hash, order, (PAGE_SIZE << order));
+ pr_info("VFS: Dquot-cache hash table entries: %ld (order %ld,"
+ " %ld bytes)\n", nr_hash, order, (PAGE_SIZE << order));
register_shrinker(&dqcache_shrinker);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 75621649dbd7..2aa4151f99d2 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -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)
diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h
index 1894d96ccb7c..bb79cddf0a1f 100644
--- a/fs/reiserfs/reiserfs.h
+++ b/fs/reiserfs/reiserfs.h
@@ -97,6 +97,10 @@ struct reiserfs_inode_info {
#ifdef CONFIG_REISERFS_FS_XATTR
struct rw_semaphore i_xattr_sem;
#endif
+#ifdef CONFIG_QUOTA
+ struct dquot *i_dquot[MAXQUOTAS];
+#endif
+
struct inode vfs_inode;
};
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index f1376c92cf74..ea63ab13ef92 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -594,6 +594,10 @@ static struct inode *reiserfs_alloc_inode(struct super_block *sb)
return NULL;
atomic_set(&ei->openers, 0);
mutex_init(&ei->tailpack);
+#ifdef CONFIG_QUOTA
+ memset(&ei->i_dquot, 0, sizeof(ei->i_dquot));
+#endif
+
return &ei->vfs_inode;
}
@@ -750,6 +754,11 @@ static ssize_t reiserfs_quota_write(struct super_block *, int, const char *,
size_t, loff_t);
static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t,
loff_t);
+
+static struct dquot **reiserfs_get_dquots(struct inode *inode)
+{
+ return REISERFS_I(inode)->i_dquot;
+}
#endif
static const struct super_operations reiserfs_sops = {
@@ -768,6 +777,7 @@ static const struct super_operations reiserfs_sops = {
#ifdef CONFIG_QUOTA
.quota_read = reiserfs_quota_read,
.quota_write = reiserfs_quota_write,
+ .get_dquots = reiserfs_get_dquots,
#endif
};
@@ -1633,6 +1643,7 @@ static int read_super_block(struct super_block *s, int offset)
#ifdef CONFIG_QUOTA
s->s_qcop = &reiserfs_qctl_operations;
s->dq_op = &reiserfs_quota_operations;
+ s->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
#endif
/*
diff --git a/fs/udf/super.c b/fs/udf/super.c
index e229315bbf7a..3ccb2f11fc76 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -2082,12 +2082,12 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
mutex_init(&sbi->s_alloc_mutex);
if (!udf_parse_options((char *)options, &uopt, false))
- goto error_out;
+ goto parse_options_failure;
if (uopt.flags & (1 << UDF_FLAG_UTF8) &&
uopt.flags & (1 << UDF_FLAG_NLS_MAP)) {
udf_err(sb, "utf8 cannot be combined with iocharset\n");
- goto error_out;
+ goto parse_options_failure;
}
#ifdef CONFIG_UDF_NLS
if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map) {
@@ -2237,8 +2237,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
return 0;
error_out:
- if (sbi->s_vat_inode)
- iput(sbi->s_vat_inode);
+ iput(sbi->s_vat_inode);
+parse_options_failure:
#ifdef CONFIG_UDF_NLS
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
unload_nls(sbi->s_nls_map);
@@ -2291,8 +2291,7 @@ static void udf_put_super(struct super_block *sb)
sbi = UDF_SB(sb);
- if (sbi->s_vat_inode)
- iput(sbi->s_vat_inode);
+ iput(sbi->s_vat_inode);
#ifdef CONFIG_UDF_NLS
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
unload_nls(sbi->s_nls_map);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 9f622feda6a4..206b97fd1d8a 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1425,6 +1425,7 @@ xfs_fs_fill_super(
sb->s_export_op = &xfs_export_operations;
#ifdef CONFIG_XFS_QUOTA
sb->s_qcop = &xfs_quotactl_operations;
+ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
#endif
sb->s_op = &xfs_super_operations;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b4a1d73c0d5d..f21b15804917 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -606,9 +606,6 @@ struct inode {
const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct file_lock *i_flock;
struct address_space i_data;
-#ifdef CONFIG_QUOTA
- struct dquot *i_dquot[MAXQUOTAS];
-#endif
struct list_head i_devices;
union {
struct pipe_inode_info *i_pipe;
@@ -1224,6 +1221,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;
@@ -1592,6 +1590,7 @@ struct super_operations {
#ifdef CONFIG_QUOTA
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+ struct dquot **(*get_dquots)(struct inode *);
#endif
int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
long (*nr_cached_objects)(struct super_block *, int);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 80d345a3524c..50978b781a19 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -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 */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 1d3eee594cd6..f23538a6e411 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -64,10 +64,10 @@ void dquot_destroy(struct dquot *dquot);
int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags);
void __dquot_free_space(struct inode *inode, qsize_t number, int flags);
-int dquot_alloc_inode(const struct inode *inode);
+int dquot_alloc_inode(struct inode *inode);
int dquot_claim_space_nodirty(struct inode *inode, qsize_t number);
-void dquot_free_inode(const struct inode *inode);
+void dquot_free_inode(struct inode *inode);
void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number);
int dquot_disable(struct super_block *sb, int type, unsigned int flags);
@@ -213,12 +213,12 @@ static inline void dquot_drop(struct inode *inode)
{
}
-static inline int dquot_alloc_inode(const struct inode *inode)
+static inline int dquot_alloc_inode(struct inode *inode)
{
return 0;
}
-static inline void dquot_free_inode(const struct inode *inode)
+static inline void dquot_free_inode(struct inode *inode)
{
}