aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hpfs/super.c
diff options
context:
space:
mode:
authorMikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>2014-01-28 18:10:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-02-02 19:24:07 -0500
commit2cbe5c76fc5e38e9af4b709593146e4b8272b69e (patch)
treede283447508e3d0ef3645f65f5adb5f9becdaf30 /fs/hpfs/super.c
parent602456bf169926d331246de9cc5593b962cea0dc (diff)
hpfs: remember free space
Previously, hpfs scanned all bitmaps each time the user asked for free space using statfs. This patch changes it so that hpfs scans the bitmaps only once, remembes the free space and on next invocation of statfs it returns the value instantly. New versions of wine are hammering on the statfs syscall very heavily, making some games unplayable when they're stored on hpfs, with load times in minutes. This should be backported to the stable kernels because it fixes user-visible problem (excessive level load times in wine). Signed-off-by: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz> Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hpfs/super.c')
-rw-r--r--fs/hpfs/super.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index b8d01ef6f531..4534ff688b76 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -121,7 +121,7 @@ static void hpfs_put_super(struct super_block *s)
121 call_rcu(&hpfs_sb(s)->rcu, lazy_free_sbi); 121 call_rcu(&hpfs_sb(s)->rcu, lazy_free_sbi);
122} 122}
123 123
124unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno) 124static unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
125{ 125{
126 struct quad_buffer_head qbh; 126 struct quad_buffer_head qbh;
127 unsigned long *bits; 127 unsigned long *bits;
@@ -129,7 +129,7 @@ unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
129 129
130 bits = hpfs_map_4sectors(s, secno, &qbh, 0); 130 bits = hpfs_map_4sectors(s, secno, &qbh, 0);
131 if (!bits) 131 if (!bits)
132 return 0; 132 return (unsigned)-1;
133 count = bitmap_weight(bits, 2048 * BITS_PER_BYTE); 133 count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);
134 hpfs_brelse4(&qbh); 134 hpfs_brelse4(&qbh);
135 return count; 135 return count;
@@ -144,30 +144,45 @@ static unsigned count_bitmaps(struct super_block *s)
144 hpfs_prefetch_bitmap(s, n); 144 hpfs_prefetch_bitmap(s, n);
145 } 145 }
146 for (n = 0; n < n_bands; n++) { 146 for (n = 0; n < n_bands; n++) {
147 unsigned c;
147 hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD); 148 hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD);
148 count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n])); 149 c = hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
150 if (c != (unsigned)-1)
151 count += c;
149 } 152 }
150 return count; 153 return count;
151} 154}
152 155
156unsigned hpfs_get_free_dnodes(struct super_block *s)
157{
158 struct hpfs_sb_info *sbi = hpfs_sb(s);
159 if (sbi->sb_n_free_dnodes == (unsigned)-1) {
160 unsigned c = hpfs_count_one_bitmap(s, sbi->sb_dmap);
161 if (c == (unsigned)-1)
162 return 0;
163 sbi->sb_n_free_dnodes = c;
164 }
165 return sbi->sb_n_free_dnodes;
166}
167
153static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) 168static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
154{ 169{
155 struct super_block *s = dentry->d_sb; 170 struct super_block *s = dentry->d_sb;
156 struct hpfs_sb_info *sbi = hpfs_sb(s); 171 struct hpfs_sb_info *sbi = hpfs_sb(s);
157 u64 id = huge_encode_dev(s->s_bdev->bd_dev); 172 u64 id = huge_encode_dev(s->s_bdev->bd_dev);
173
158 hpfs_lock(s); 174 hpfs_lock(s);
159 175
160 /*if (sbi->sb_n_free == -1) {*/ 176 if (sbi->sb_n_free == (unsigned)-1)
161 sbi->sb_n_free = count_bitmaps(s); 177 sbi->sb_n_free = count_bitmaps(s);
162 sbi->sb_n_free_dnodes = hpfs_count_one_bitmap(s, sbi->sb_dmap); 178
163 /*}*/
164 buf->f_type = s->s_magic; 179 buf->f_type = s->s_magic;
165 buf->f_bsize = 512; 180 buf->f_bsize = 512;
166 buf->f_blocks = sbi->sb_fs_size; 181 buf->f_blocks = sbi->sb_fs_size;
167 buf->f_bfree = sbi->sb_n_free; 182 buf->f_bfree = sbi->sb_n_free;
168 buf->f_bavail = sbi->sb_n_free; 183 buf->f_bavail = sbi->sb_n_free;
169 buf->f_files = sbi->sb_dirband_size / 4; 184 buf->f_files = sbi->sb_dirband_size / 4;
170 buf->f_ffree = sbi->sb_n_free_dnodes; 185 buf->f_ffree = hpfs_get_free_dnodes(s);
171 buf->f_fsid.val[0] = (u32)id; 186 buf->f_fsid.val[0] = (u32)id;
172 buf->f_fsid.val[1] = (u32)(id >> 32); 187 buf->f_fsid.val[1] = (u32)(id >> 32);
173 buf->f_namelen = 254; 188 buf->f_namelen = 254;