[PATCH 01/19] quota: protect getfmt call with dqonoff_mutex lock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



dqptr_sem hasn't any thing in common with quota files,
quota file load  protected with dqonoff_mutex, so we have to use
it for reading fmt info.

Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx>
---
 fs/ext3/super.c          |    1 +
 fs/ext4/super.c          |    1 +
 fs/ocfs2/super.c         |    1 +
 fs/quota/dquot.c         |   14 ++++++++++++++
 fs/quota/quota.c         |   16 ++++++----------
 fs/reiserfs/super.c      |    1 +
 include/linux/quota.h    |    1 +
 include/linux/quotaops.h |    1 +
 8 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index e9fd676..e0f68f0 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -773,6 +773,7 @@ static const struct quotactl_ops ext3_qctl_operations = {
 	.quota_sync	= dquot_quota_sync,
 	.get_info	= dquot_get_dqinfo,
 	.set_info	= dquot_set_dqinfo,
+	.get_fmt	= dquot_get_dqfmt,
 	.get_dqblk	= dquot_get_dqblk,
 	.set_dqblk	= dquot_set_dqblk
 };
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4062fbe..a2e68f9 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1150,6 +1150,7 @@ static const struct quotactl_ops ext4_qctl_operations = {
 	.quota_sync	= dquot_quota_sync,
 	.get_info	= dquot_get_dqinfo,
 	.set_info	= dquot_set_dqinfo,
+	.get_fmt	= dquot_get_dqfmt,
 	.get_dqblk	= dquot_get_dqblk,
 	.set_dqblk	= dquot_set_dqblk
 };
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 26bd015..8e6a20c 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -986,6 +986,7 @@ static const struct quotactl_ops ocfs2_quotactl_ops = {
 	.quota_sync	= dquot_quota_sync,
 	.get_info	= dquot_get_dqinfo,
 	.set_info	= dquot_set_dqinfo,
+	.get_fmt	= dquot_get_dqfmt,
 	.get_dqblk	= dquot_get_dqblk,
 	.set_dqblk	= dquot_set_dqblk,
 };
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 06157aa..d1d1c51 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -1890,6 +1890,19 @@ int dquot_file_open(struct inode *inode, struct file *file)
 }
 EXPORT_SYMBOL(dquot_file_open);
 
+int dquot_get_dqfmt(struct super_block *sb, int type, unsigned int *fmt)
+{
+	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+	if (!sb_has_quota_active(sb, type)) {
+		mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+		return -ESRCH;
+	}
+	*fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
+	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(dquot_get_dqfmt);
+
 /*
  * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  */
@@ -2502,6 +2515,7 @@ const struct quotactl_ops dquot_quotactl_ops = {
 	.quota_sync	= dquot_quota_sync,
 	.get_info	= dquot_get_dqinfo,
 	.set_info	= dquot_set_dqinfo,
+	.get_fmt	= dquot_get_dqfmt,
 	.get_dqblk	= dquot_get_dqblk,
 	.set_dqblk	= dquot_set_dqblk
 };
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index b34bdb2..3b1d315 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -78,17 +78,13 @@ static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
 static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
 {
 	__u32 fmt;
-
-	down_read(&sb_dqopt(sb)->dqptr_sem);
-	if (!sb_has_quota_active(sb, type)) {
-		up_read(&sb_dqopt(sb)->dqptr_sem);
-		return -ESRCH;
-	}
-	fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
-	up_read(&sb_dqopt(sb)->dqptr_sem);
-	if (copy_to_user(addr, &fmt, sizeof(fmt)))
+	int ret;
+	if (!sb->s_qcop->get_fmt)
+		return -ENOSYS;
+	ret = sb->s_qcop->get_fmt(sb, type, &fmt);
+	if (!ret && copy_to_user(addr, &fmt, sizeof(fmt)))
 		return -EFAULT;
-	return 0;
+	return ret;
 }
 
 static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 73c000f..d4d32df 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -644,6 +644,7 @@ static const struct quotactl_ops reiserfs_qctl_operations = {
 	.quota_sync = dquot_quota_sync,
 	.get_info = dquot_get_dqinfo,
 	.set_info = dquot_set_dqinfo,
+	.get_fmt =  dquot_get_dqfmt,
 	.get_dqblk = dquot_get_dqblk,
 	.set_dqblk = dquot_set_dqblk,
 };
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 9a85412..2767e4c 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -331,6 +331,7 @@ struct quotactl_ops {
 	int (*quota_off)(struct super_block *, int);
 	int (*quota_sync)(struct super_block *, int, int);
 	int (*get_info)(struct super_block *, int, struct if_dqinfo *);
+	int (*get_fmt)(struct super_block*, int, unsigned int*);
 	int (*set_info)(struct super_block *, int, struct if_dqinfo *);
 	int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
 	int (*set_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 9e09c9a..45ae255 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -85,6 +85,7 @@ int dquot_quota_off(struct super_block *sb, int type);
 int dquot_quota_sync(struct super_block *sb, int type, int wait);
 int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+int dquot_get_dqfmt(struct super_block *sb, int type, unsigned int *fmt);
 int dquot_get_dqblk(struct super_block *sb, int type, qid_t id,
 		struct fs_disk_quota *di);
 int dquot_set_dqblk(struct super_block *sb, int type, qid_t id,
-- 
1.6.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux