[PATCH v3 15/39] fs: quota: introduce a callback of restore_iflags to quotactl_ops

Dongsheng Yang yangds.fnst at cn.fujitsu.com
Tue Sep 15 02:02:10 PDT 2015


In dquot_disable, we need to restore the iflags of quota files
and mark the inodes to dirty. But that's pain to file-systems
working in out-place-updating way, such as btrfs and ubifs. when
they are going to update inode, they have to reserve space for
this inode.

So we can not mark_inode_dirty() in dquot_disable for them. To solve
this kind of problem, the common solution is introduce a callback
to allow file-systems to do the inode_dirty work by themselves,
the similar way with update_time().

Signed-off-by: Dongsheng Yang <yangds.fnst at cn.fujitsu.com>
---
 fs/quota/dquot.c      | 51 ++++++++++++++++++++++++++++++++++-----------------
 include/linux/quota.h |  4 ++++
 2 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index c73f44d..3f08e69 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2020,6 +2020,33 @@ int dquot_file_open(struct inode *inode, struct file *file)
 }
 EXPORT_SYMBOL(dquot_file_open);
 
+static int generic_restore_iflags(struct super_block *sb, struct inode **toputinode,
+					unsigned int *old_flags)
+{
+	int cnt = 0;
+	struct quota_info *dqopt = sb_dqopt(sb);
+
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (toputinode[cnt]) {
+			mutex_lock(&dqopt->dqonoff_mutex);
+			/* If quota was reenabled in the meantime, we have
+			 * nothing to do */
+			if (!sb_has_quota_loaded(sb, cnt)) {
+				mutex_lock(&toputinode[cnt]->i_mutex);
+				toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
+				  S_NOATIME | S_NOQUOTA);
+				toputinode[cnt]->i_flags |= old_flags[cnt];
+				truncate_inode_pages(&toputinode[cnt]->i_data,
+						     0);
+				mutex_unlock(&toputinode[cnt]->i_mutex);
+				mark_inode_dirty_sync(toputinode[cnt]);
+			}
+			mutex_unlock(&dqopt->dqonoff_mutex);
+		}
+
+	return 0;
+}
+
 /*
  * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  */
@@ -2028,6 +2055,7 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
 	int cnt, ret = 0;
 	struct quota_info *dqopt = sb_dqopt(sb);
 	struct inode *toputinode[MAXQUOTAS];
+	unsigned int *old_flags = dqopt->old_flags;
 
 	/* Cannot turn off usage accounting without turning off limits, or
 	 * suspend quotas and simultaneously turn quotas off. */
@@ -2111,28 +2139,17 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
 	 * disk (and so userspace sees correct data afterwards). */
 	sync_filesystem(sb);
 	sync_blockdev(sb->s_bdev);
+
 	/* Now the quota files are just ordinary files and we can set the
 	 * inode flags back. Moreover we discard the pagecache so that
 	 * userspace sees the writes we did bypassing the pagecache. We
 	 * must also discard the blockdev buffers so that we see the
 	 * changes done by userspace on the next quotaon() */
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-		if (toputinode[cnt]) {
-			mutex_lock(&dqopt->dqonoff_mutex);
-			/* If quota was reenabled in the meantime, we have
-			 * nothing to do */
-			if (!sb_has_quota_loaded(sb, cnt)) {
-				mutex_lock(&toputinode[cnt]->i_mutex);
-				toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
-				  S_NOATIME | S_NOQUOTA);
-				toputinode[cnt]->i_flags |= dqopt->old_flags[cnt];
-				truncate_inode_pages(&toputinode[cnt]->i_data,
-						     0);
-				mutex_unlock(&toputinode[cnt]->i_mutex);
-				mark_inode_dirty_sync(toputinode[cnt]);
-			}
-			mutex_unlock(&dqopt->dqonoff_mutex);
-		}
+	if (sb->s_qcop->restore_iflags)
+		ret = sb->s_qcop->restore_iflags(sb, toputinode, old_flags);
+	else
+		ret = generic_restore_iflags(sb, toputinode, old_flags);
+
 	if (sb->s_bdev)
 		invalidate_bdev(sb->s_bdev);
 put_inodes:
diff --git a/include/linux/quota.h b/include/linux/quota.h
index fcfee5a..64e52e4 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -428,6 +428,10 @@ struct quotactl_ops {
 	int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
 	int (*get_state)(struct super_block *, struct qc_state *);
 	int (*rm_xquota)(struct super_block *, unsigned int);
+	/*
+	 * used in quota_disable to restore the i_flags of quota files.
+	 */
+	int (*restore_iflags)(struct super_block *sb, struct inode **, unsigned int *);
 };
 
 struct quota_format_type {
-- 
1.8.4.2




More information about the linux-mtd mailing list