diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-02-16 03:44:52 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2010-03-04 18:20:24 -0500 |
commit | 5fb324ad24febe57a8a2e62903dcb7bad546ea71 (patch) | |
tree | f49d1b8b7fe9feffbdd1afba18047001f5d7228f /fs/quota | |
parent | 8c4e4acd660a09e571a71583b5bbe1eee700c9ad (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.c | 29 | ||||
-rw-r--r-- | fs/quota/quota.c | 46 |
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 | } |
571 | EXPORT_SYMBOL(dquot_scan_active); | 571 | EXPORT_SYMBOL(dquot_scan_active); |
572 | 572 | ||
573 | int vfs_quota_sync(struct super_block *sb, int type) | 573 | int 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 | } |
620 | EXPORT_SYMBOL(vfs_quota_sync); | 647 | EXPORT_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 | ||
52 | void 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 | |||
89 | static int quota_sync_all(int type) | 51 | static 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); |
102 | restart: | 64 | restart: |
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: |