aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-02-16 03:44:52 -0500
committerJan Kara <jack@suse.cz>2010-03-04 18:20:24 -0500
commit5fb324ad24febe57a8a2e62903dcb7bad546ea71 (patch)
treef49d1b8b7fe9feffbdd1afba18047001f5d7228f /fs/quota
parent8c4e4acd660a09e571a71583b5bbe1eee700c9ad (diff)
quota: move code from sync_quota_sb into vfs_quota_sync
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>
Diffstat (limited to 'fs/quota')
-rw-r--r--fs/quota/dquot.c29
-rw-r--r--fs/quota/quota.c46
2 files changed, 33 insertions, 42 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 6c849de5dc8f..4c2213f7ed36 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -570,7 +570,7 @@ out:
570} 570}
571EXPORT_SYMBOL(dquot_scan_active); 571EXPORT_SYMBOL(dquot_scan_active);
572 572
573int vfs_quota_sync(struct super_block *sb, int type) 573int vfs_quota_sync(struct super_block *sb, int type, int wait)
574{ 574{
575 struct list_head *dirty; 575 struct list_head *dirty;
576 struct dquot *dquot; 576 struct dquot *dquot;
@@ -615,6 +615,33 @@ int vfs_quota_sync(struct super_block *sb, int type)
615 spin_unlock(&dq_list_lock); 615 spin_unlock(&dq_list_lock);
616 mutex_unlock(&dqopt->dqonoff_mutex); 616 mutex_unlock(&dqopt->dqonoff_mutex);
617 617
618 if (!wait || (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE))
619 return 0;
620
621 /* This is not very clever (and fast) but currently I don't know about
622 * any other simple way of getting quota data to disk and we must get
623 * them there for userspace to be visible... */
624 if (sb->s_op->sync_fs)
625 sb->s_op->sync_fs(sb, 1);
626 sync_blockdev(sb->s_bdev);
627
628 /*
629 * Now when everything is written we can discard the pagecache so
630 * that userspace sees the changes.
631 */
632 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
633 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
634 if (type != -1 && cnt != type)
635 continue;
636 if (!sb_has_quota_active(sb, cnt))
637 continue;
638 mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex,
639 I_MUTEX_QUOTA);
640 truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
641 mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
642 }
643 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
644
618 return 0; 645 return 0;
619} 646}
620EXPORT_SYMBOL(vfs_quota_sync); 647EXPORT_SYMBOL(vfs_quota_sync);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 3d31228082ea..0593b229656c 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -48,44 +48,6 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
48 return security_quotactl(cmd, type, id, sb); 48 return security_quotactl(cmd, type, id, sb);
49} 49}
50 50
51#ifdef CONFIG_QUOTA
52void sync_quota_sb(struct super_block *sb, int type)
53{
54 int cnt;
55
56 if (!sb->s_qcop || !sb->s_qcop->quota_sync)
57 return;
58
59 sb->s_qcop->quota_sync(sb, type);
60
61 if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE)
62 return;
63 /* This is not very clever (and fast) but currently I don't know about
64 * any other simple way of getting quota data to disk and we must get
65 * them there for userspace to be visible... */
66 if (sb->s_op->sync_fs)
67 sb->s_op->sync_fs(sb, 1);
68 sync_blockdev(sb->s_bdev);
69
70 /*
71 * Now when everything is written we can discard the pagecache so
72 * that userspace sees the changes.
73 */
74 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
75 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
76 if (type != -1 && cnt != type)
77 continue;
78 if (!sb_has_quota_active(sb, cnt))
79 continue;
80 mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex,
81 I_MUTEX_QUOTA);
82 truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
83 mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
84 }
85 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
86}
87#endif
88
89static int quota_sync_all(int type) 51static int quota_sync_all(int type)
90{ 52{
91 struct super_block *sb; 53 struct super_block *sb;
@@ -101,6 +63,9 @@ static int quota_sync_all(int type)
101 spin_lock(&sb_lock); 63 spin_lock(&sb_lock);
102restart: 64restart:
103 list_for_each_entry(sb, &super_blocks, s_list) { 65 list_for_each_entry(sb, &super_blocks, s_list) {
66 if (!sb->s_qcop || !sb->s_qcop->quota_sync)
67 continue;
68
104 /* This test just improves performance so it needn't be 69 /* This test just improves performance so it needn't be
105 * reliable... */ 70 * reliable... */
106 for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 71 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -119,7 +84,7 @@ restart:
119 spin_unlock(&sb_lock); 84 spin_unlock(&sb_lock);
120 down_read(&sb->s_umount); 85 down_read(&sb->s_umount);
121 if (sb->s_root) 86 if (sb->s_root)
122 sync_quota_sb(sb, type); 87 sb->s_qcop->quota_sync(sb, type, 1);
123 up_read(&sb->s_umount); 88 up_read(&sb->s_umount);
124 spin_lock(&sb_lock); 89 spin_lock(&sb_lock);
125 if (__put_super_and_need_restart(sb)) 90 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,
306 case Q_SYNC: 271 case Q_SYNC:
307 if (!sb->s_qcop->quota_sync) 272 if (!sb->s_qcop->quota_sync)
308 return -ENOSYS; 273 return -ENOSYS;
309 sync_quota_sb(sb, type); 274 return sb->s_qcop->quota_sync(sb, type, 1);
310 return 0;
311 case Q_XQUOTAON: 275 case Q_XQUOTAON:
312 case Q_XQUOTAOFF: 276 case Q_XQUOTAOFF:
313 case Q_XQUOTARM: 277 case Q_XQUOTARM: