quota: move code from sync_quota_sb into vfs_quota_sync
authorChristoph Hellwig <hch@infradead.org>
Tue, 16 Feb 2010 08:44:52 +0000 (03:44 -0500)
committerJan Kara <jack@suse.cz>
Thu, 4 Mar 2010 23:20:24 +0000 (00:20 +0100)
Currenly sync_quota_sb does a lot of sync and truncate action that only
applies to "VFS" style quotas and is actively harmful for the sync
performance in XFS.  Move it into vfs_quota_sync and add a wait parameter
to ->quota_sync to tell if we need it or not.

My audit of the GFS2 code says it's also not needed given the way GFS2
implements quotas, but I'd be happy if this can get a detailed review.

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

index e3bf6eab8750011a9e582a0f465bbf3dc49b8612..6dbcbad6ab1783449d66a134bb718bbc4037a81f 100644 (file)
@@ -1083,7 +1083,7 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
        }
 }
 
-int gfs2_quota_sync(struct super_block *sb, int type)
+int gfs2_quota_sync(struct super_block *sb, int type, int wait)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_quota_data **qda;
@@ -1127,6 +1127,11 @@ int gfs2_quota_sync(struct super_block *sb, int type)
        return error;
 }
 
+static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
+{
+       return gfs2_quota_sync(sb, type, 0);
+}
+
 int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
 {
        struct gfs2_quota_data *qd;
@@ -1382,7 +1387,7 @@ int gfs2_quotad(void *data)
                                           &tune->gt_statfs_quantum);
 
                /* Update quota file */
-               quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
+               quotad_check_timeo(sdp, "sync", gfs2_quota_sync_timeo, t,
                                   &quotad_timeo, &tune->gt_quota_quantum);
 
                /* Check for & recover partially truncated inodes */
index e271fa07ad0206dfbda9cb33ad01c9cbd0d7c3ef..195f60c8bd144b6ae5040c878e4f14305cafccc4 100644 (file)
@@ -25,7 +25,7 @@ extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);
 extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
                              u32 uid, u32 gid);
 
-extern int gfs2_quota_sync(struct super_block *sb, int type);
+extern int gfs2_quota_sync(struct super_block *sb, int type, int wait);
 extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
 
 extern int gfs2_quota_init(struct gfs2_sbd *sdp);
index b9dd3da22c0a3fc5452a018cb25dfab89fa6ecf0..a8c2bcd0fcc858b34219e2f229d1002bfe6db1c5 100644 (file)
@@ -764,7 +764,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
        int error;
 
        flush_workqueue(gfs2_delete_workqueue);
-       gfs2_quota_sync(sdp->sd_vfs, 0);
+       gfs2_quota_sync(sdp->sd_vfs, 0, 1);
        gfs2_statfs_sync(sdp->sd_vfs, 0);
 
        error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
index 0dc34621f6a6ecf73acddc3c82d0a90c731ff601..4496cc37a0fa2b60dc993dd01eb023f998e8630d 100644 (file)
@@ -167,7 +167,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
        if (simple_strtol(buf, NULL, 0) != 1)
                return -EINVAL;
 
-       gfs2_quota_sync(sdp->sd_vfs, 0);
+       gfs2_quota_sync(sdp->sd_vfs, 0, 1);
        return len;
 }
 
index 6c849de5dc8f9b36d59faabbdcb53ce02466e4ab..4c2213f7ed36e291c4d3ffec6288ad9b8e841f4c 100644 (file)
@@ -570,7 +570,7 @@ out:
 }
 EXPORT_SYMBOL(dquot_scan_active);
 
-int vfs_quota_sync(struct super_block *sb, int type)
+int vfs_quota_sync(struct super_block *sb, int type, int wait)
 {
        struct list_head *dirty;
        struct dquot *dquot;
@@ -615,6 +615,33 @@ int vfs_quota_sync(struct super_block *sb, int type)
        spin_unlock(&dq_list_lock);
        mutex_unlock(&dqopt->dqonoff_mutex);
 
+       if (!wait || (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE))
+               return 0;
+
+       /* This is not very clever (and fast) but currently I don't know about
+        * any other simple way of getting quota data to disk and we must get
+        * them there for userspace to be visible... */
+       if (sb->s_op->sync_fs)
+               sb->s_op->sync_fs(sb, 1);
+       sync_blockdev(sb->s_bdev);
+
+       /*
+        * Now when everything is written we can discard the pagecache so
+        * that userspace sees the changes.
+        */
+       mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (type != -1 && cnt != type)
+                       continue;
+               if (!sb_has_quota_active(sb, cnt))
+                       continue;
+               mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex,
+                                 I_MUTEX_QUOTA);
+               truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
+               mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
+       }
+       mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+
        return 0;
 }
 EXPORT_SYMBOL(vfs_quota_sync);
index 3d31228082ea88ed8086e804430aa14d41c4583a..0593b229656cae1f4b195ee997face59dc7a25c5 100644 (file)
@@ -48,44 +48,6 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
        return security_quotactl(cmd, type, id, sb);
 }
 
-#ifdef CONFIG_QUOTA
-void sync_quota_sb(struct super_block *sb, int type)
-{
-       int cnt;
-
-       if (!sb->s_qcop || !sb->s_qcop->quota_sync)
-               return;
-
-       sb->s_qcop->quota_sync(sb, type);
-
-       if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE)
-               return;
-       /* This is not very clever (and fast) but currently I don't know about
-        * any other simple way of getting quota data to disk and we must get
-        * them there for userspace to be visible... */
-       if (sb->s_op->sync_fs)
-               sb->s_op->sync_fs(sb, 1);
-       sync_blockdev(sb->s_bdev);
-
-       /*
-        * Now when everything is written we can discard the pagecache so
-        * that userspace sees the changes.
-        */
-       mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (type != -1 && cnt != type)
-                       continue;
-               if (!sb_has_quota_active(sb, cnt))
-                       continue;
-               mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex,
-                                 I_MUTEX_QUOTA);
-               truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
-               mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
-       }
-       mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
-}
-#endif
-
 static int quota_sync_all(int type)
 {
        struct super_block *sb;
@@ -101,6 +63,9 @@ static int quota_sync_all(int type)
        spin_lock(&sb_lock);
 restart:
        list_for_each_entry(sb, &super_blocks, s_list) {
+               if (!sb->s_qcop || !sb->s_qcop->quota_sync)
+                       continue;
+
                /* This test just improves performance so it needn't be
                 * reliable... */
                for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -119,7 +84,7 @@ restart:
                spin_unlock(&sb_lock);
                down_read(&sb->s_umount);
                if (sb->s_root)
-                       sync_quota_sb(sb, type);
+                       sb->s_qcop->quota_sync(sb, type, 1);
                up_read(&sb->s_umount);
                spin_lock(&sb_lock);
                if (__put_super_and_need_restart(sb))
@@ -306,8 +271,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
        case Q_SYNC:
                if (!sb->s_qcop->quota_sync)
                        return -ENOSYS;
-               sync_quota_sb(sb, type);
-               return 0;
+               return sb->s_qcop->quota_sync(sb, type, 1);
        case Q_XQUOTAON:
        case Q_XQUOTAOFF:
        case Q_XQUOTARM:
index 418727a2a2390f435d68b1fad91dede88dc4c17f..f557d71cb0971692b5337cefad5db272f10b6a78 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -34,14 +34,14 @@ static int __sync_filesystem(struct super_block *sb, int wait)
        if (!sb->s_bdi)
                return 0;
 
-       /* Avoid doing twice syncing and cache pruning for quota sync */
-       if (!wait) {
-               writeout_quota_sb(sb, -1);
-               writeback_inodes_sb(sb);
-       } else {
-               sync_quota_sb(sb, -1);
+       if (sb->s_qcop && sb->s_qcop->quota_sync)
+               sb->s_qcop->quota_sync(sb, -1, wait);
+
+       if (wait)
                sync_inodes_sb(sb);
-       }
+       else
+               writeback_inodes_sb(sb);
+
        if (sb->s_op->sync_fs)
                sb->s_op->sync_fs(sb, wait);
        return __sync_blockdev(sb->s_bdev, wait);
index a6861f11748044d2c666c6f94edf463c8c47660a..570348cbccb118c7765998722b5316218fb80fc0 100644 (file)
@@ -324,7 +324,7 @@ struct dquot_operations {
 struct quotactl_ops {
        int (*quota_on)(struct super_block *, int, int, char *, int);
        int (*quota_off)(struct super_block *, int, int);
-       int (*quota_sync)(struct super_block *, int);
+       int (*quota_sync)(struct super_block *, int, int);
        int (*get_info)(struct super_block *, int, struct if_dqinfo *);
        int (*set_info)(struct super_block *, int, struct if_dqinfo *);
        int (*get_dqblk)(struct super_block *, int, qid_t, struct if_dqblk *);
index 69d26bc0f884a225794b828fd4bfcaeb8ecf9ed1..8cfd0d44c99484d19c8c8d6129bd7b44f210df0f 100644 (file)
@@ -19,13 +19,6 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb)
 /*
  * declaration of quota_function calls in kernel.
  */
-void sync_quota_sb(struct super_block *sb, int type);
-static inline void writeout_quota_sb(struct super_block *sb, int type)
-{
-       if (sb->s_qcop && sb->s_qcop->quota_sync)
-               sb->s_qcop->quota_sync(sb, type);
-}
-
 void inode_add_rsv_space(struct inode *inode, qsize_t number);
 void inode_claim_rsv_space(struct inode *inode, qsize_t number);
 void inode_sub_rsv_space(struct inode *inode, qsize_t number);
@@ -67,7 +60,7 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
        int format_id, int type);
 int vfs_quota_off(struct super_block *sb, int type, int remount);
 int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags);
-int vfs_quota_sync(struct super_block *sb, int type);
+int vfs_quota_sync(struct super_block *sb, int type, int wait);
 int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
@@ -340,14 +333,6 @@ static inline void vfs_dq_free_inode(struct inode *inode)
 {
 }
 
-static inline void sync_quota_sb(struct super_block *sb, int type)
-{
-}
-
-static inline void writeout_quota_sb(struct super_block *sb, int type)
-{
-}
-
 static inline int vfs_dq_off(struct super_block *sb, int remount)
 {
        return 0;