aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hpfs
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
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')
-rw-r--r--fs/hpfs/alloc.c66
-rw-r--r--fs/hpfs/hpfs_fn.h2
-rw-r--r--fs/hpfs/super.c29
3 files changed, 87 insertions, 10 deletions
diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c
index cdb84a838068..58b5106186d0 100644
--- a/fs/hpfs/alloc.c
+++ b/fs/hpfs/alloc.c
@@ -8,6 +8,58 @@
8 8
9#include "hpfs_fn.h" 9#include "hpfs_fn.h"
10 10
11static void hpfs_claim_alloc(struct super_block *s, secno sec)
12{
13 struct hpfs_sb_info *sbi = hpfs_sb(s);
14 if (sbi->sb_n_free != (unsigned)-1) {
15 if (unlikely(!sbi->sb_n_free)) {
16 hpfs_error(s, "free count underflow, allocating sector %08x", sec);
17 sbi->sb_n_free = -1;
18 return;
19 }
20 sbi->sb_n_free--;
21 }
22}
23
24static void hpfs_claim_free(struct super_block *s, secno sec)
25{
26 struct hpfs_sb_info *sbi = hpfs_sb(s);
27 if (sbi->sb_n_free != (unsigned)-1) {
28 if (unlikely(sbi->sb_n_free >= sbi->sb_fs_size)) {
29 hpfs_error(s, "free count overflow, freeing sector %08x", sec);
30 sbi->sb_n_free = -1;
31 return;
32 }
33 sbi->sb_n_free++;
34 }
35}
36
37static void hpfs_claim_dirband_alloc(struct super_block *s, secno sec)
38{
39 struct hpfs_sb_info *sbi = hpfs_sb(s);
40 if (sbi->sb_n_free_dnodes != (unsigned)-1) {
41 if (unlikely(!sbi->sb_n_free_dnodes)) {
42 hpfs_error(s, "dirband free count underflow, allocating sector %08x", sec);
43 sbi->sb_n_free_dnodes = -1;
44 return;
45 }
46 sbi->sb_n_free_dnodes--;
47 }
48}
49
50static void hpfs_claim_dirband_free(struct super_block *s, secno sec)
51{
52 struct hpfs_sb_info *sbi = hpfs_sb(s);
53 if (sbi->sb_n_free_dnodes != (unsigned)-1) {
54 if (unlikely(sbi->sb_n_free_dnodes >= sbi->sb_dirband_size / 4)) {
55 hpfs_error(s, "dirband free count overflow, freeing sector %08x", sec);
56 sbi->sb_n_free_dnodes = -1;
57 return;
58 }
59 sbi->sb_n_free_dnodes++;
60 }
61}
62
11/* 63/*
12 * Check if a sector is allocated in bitmap 64 * Check if a sector is allocated in bitmap
13 * This is really slow. Turned on only if chk==2 65 * This is really slow. Turned on only if chk==2
@@ -203,9 +255,15 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa
203 } 255 }
204 sec = 0; 256 sec = 0;
205 ret: 257 ret:
258 if (sec) {
259 i = 0;
260 do
261 hpfs_claim_alloc(s, sec + i);
262 while (unlikely(++i < n));
263 }
206 if (sec && f_p) { 264 if (sec && f_p) {
207 for (i = 0; i < forward; i++) { 265 for (i = 0; i < forward; i++) {
208 if (!hpfs_alloc_if_possible(s, sec + i + 1)) { 266 if (!hpfs_alloc_if_possible(s, sec + n + i)) {
209 hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i); 267 hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i);
210 sec = 0; 268 sec = 0;
211 break; 269 break;
@@ -228,6 +286,7 @@ static secno alloc_in_dirband(struct super_block *s, secno near)
228 nr >>= 2; 286 nr >>= 2;
229 sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0); 287 sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0);
230 if (!sec) return 0; 288 if (!sec) return 0;
289 hpfs_claim_dirband_alloc(s, sec);
231 return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start; 290 return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start;
232} 291}
233 292
@@ -242,6 +301,7 @@ int hpfs_alloc_if_possible(struct super_block *s, secno sec)
242 bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f))); 301 bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f)));
243 hpfs_mark_4buffers_dirty(&qbh); 302 hpfs_mark_4buffers_dirty(&qbh);
244 hpfs_brelse4(&qbh); 303 hpfs_brelse4(&qbh);
304 hpfs_claim_alloc(s, sec);
245 return 1; 305 return 1;
246 } 306 }
247 hpfs_brelse4(&qbh); 307 hpfs_brelse4(&qbh);
@@ -275,6 +335,7 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)
275 return; 335 return;
276 } 336 }
277 bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f)); 337 bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f));
338 hpfs_claim_free(s, sec);
278 if (!--n) { 339 if (!--n) {
279 hpfs_mark_4buffers_dirty(&qbh); 340 hpfs_mark_4buffers_dirty(&qbh);
280 hpfs_brelse4(&qbh); 341 hpfs_brelse4(&qbh);
@@ -359,6 +420,7 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno)
359 bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f)); 420 bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f));
360 hpfs_mark_4buffers_dirty(&qbh); 421 hpfs_mark_4buffers_dirty(&qbh);
361 hpfs_brelse4(&qbh); 422 hpfs_brelse4(&qbh);
423 hpfs_claim_dirband_free(s, dno);
362 } 424 }
363} 425}
364 426
@@ -366,7 +428,7 @@ struct dnode *hpfs_alloc_dnode(struct super_block *s, secno near,
366 dnode_secno *dno, struct quad_buffer_head *qbh) 428 dnode_secno *dno, struct quad_buffer_head *qbh)
367{ 429{
368 struct dnode *d; 430 struct dnode *d;
369 if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) { 431 if (hpfs_get_free_dnodes(s) > FREE_DNODES_ADD) {
370 if (!(*dno = alloc_in_dirband(s, near))) 432 if (!(*dno = alloc_in_dirband(s, near)))
371 if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL; 433 if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL;
372 } else { 434 } else {
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 6797bf80f6e2..3ba49c080e42 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -312,7 +312,7 @@ static inline struct hpfs_sb_info *hpfs_sb(struct super_block *sb)
312__printf(2, 3) 312__printf(2, 3)
313void hpfs_error(struct super_block *, const char *, ...); 313void hpfs_error(struct super_block *, const char *, ...);
314int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *); 314int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *);
315unsigned hpfs_count_one_bitmap(struct super_block *, secno); 315unsigned hpfs_get_free_dnodes(struct super_block *);
316 316
317/* 317/*
318 * local time (HPFS) to GMT (Unix) 318 * local time (HPFS) to GMT (Unix)
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;