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>

authored by Mikulas Patocka and committed by Linus Torvalds 2cbe5c76 602456bf

Changed files
+87 -10
fs
+64 -2
fs/hpfs/alloc.c
··· 8 8 9 9 #include "hpfs_fn.h" 10 10 11 + static 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 + 24 + static 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 + 37 + static 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 + 50 + static 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 64 * Check if a sector is allocated in bitmap 13 65 * This is really slow. Turned on only if chk==2 ··· 255 203 } 256 204 sec = 0; 257 205 ret: 206 + if (sec) { 207 + i = 0; 208 + do 209 + hpfs_claim_alloc(s, sec + i); 210 + while (unlikely(++i < n)); 211 + } 258 212 if (sec && f_p) { 259 213 for (i = 0; i < forward; i++) { 260 - if (!hpfs_alloc_if_possible(s, sec + i + 1)) { 214 + if (!hpfs_alloc_if_possible(s, sec + n + i)) { 261 215 hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i); 262 216 sec = 0; 263 217 break; ··· 286 228 nr >>= 2; 287 229 sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0); 288 230 if (!sec) return 0; 231 + hpfs_claim_dirband_alloc(s, sec); 289 232 return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start; 290 233 } 291 234 ··· 301 242 bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f))); 302 243 hpfs_mark_4buffers_dirty(&qbh); 303 244 hpfs_brelse4(&qbh); 245 + hpfs_claim_alloc(s, sec); 304 246 return 1; 305 247 } 306 248 hpfs_brelse4(&qbh); ··· 335 275 return; 336 276 } 337 277 bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f)); 278 + hpfs_claim_free(s, sec); 338 279 if (!--n) { 339 280 hpfs_mark_4buffers_dirty(&qbh); 340 281 hpfs_brelse4(&qbh); ··· 420 359 bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f)); 421 360 hpfs_mark_4buffers_dirty(&qbh); 422 361 hpfs_brelse4(&qbh); 362 + hpfs_claim_dirband_free(s, dno); 423 363 } 424 364 } 425 365 ··· 428 366 dnode_secno *dno, struct quad_buffer_head *qbh) 429 367 { 430 368 struct dnode *d; 431 - if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) { 369 + if (hpfs_get_free_dnodes(s) > FREE_DNODES_ADD) { 432 370 if (!(*dno = alloc_in_dirband(s, near))) 433 371 if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL; 434 372 } else {
+1 -1
fs/hpfs/hpfs_fn.h
··· 312 312 __printf(2, 3) 313 313 void hpfs_error(struct super_block *, const char *, ...); 314 314 int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *); 315 - unsigned hpfs_count_one_bitmap(struct super_block *, secno); 315 + unsigned hpfs_get_free_dnodes(struct super_block *); 316 316 317 317 /* 318 318 * local time (HPFS) to GMT (Unix)
+22 -7
fs/hpfs/super.c
··· 121 121 call_rcu(&hpfs_sb(s)->rcu, lazy_free_sbi); 122 122 } 123 123 124 - unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno) 124 + static unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno) 125 125 { 126 126 struct quad_buffer_head qbh; 127 127 unsigned long *bits; ··· 129 129 130 130 bits = hpfs_map_4sectors(s, secno, &qbh, 0); 131 131 if (!bits) 132 - return 0; 132 + return (unsigned)-1; 133 133 count = bitmap_weight(bits, 2048 * BITS_PER_BYTE); 134 134 hpfs_brelse4(&qbh); 135 135 return count; ··· 144 144 hpfs_prefetch_bitmap(s, n); 145 145 } 146 146 for (n = 0; n < n_bands; n++) { 147 + unsigned c; 147 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 153 return count; 154 + } 155 + 156 + unsigned 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; 151 166 } 152 167 153 168 static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) ··· 170 155 struct super_block *s = dentry->d_sb; 171 156 struct hpfs_sb_info *sbi = hpfs_sb(s); 172 157 u64 id = huge_encode_dev(s->s_bdev->bd_dev); 158 + 173 159 hpfs_lock(s); 174 160 175 - /*if (sbi->sb_n_free == -1) {*/ 161 + if (sbi->sb_n_free == (unsigned)-1) 176 162 sbi->sb_n_free = count_bitmaps(s); 177 - sbi->sb_n_free_dnodes = hpfs_count_one_bitmap(s, sbi->sb_dmap); 178 - /*}*/ 163 + 179 164 buf->f_type = s->s_magic; 180 165 buf->f_bsize = 512; 181 166 buf->f_blocks = sbi->sb_fs_size; 182 167 buf->f_bfree = sbi->sb_n_free; 183 168 buf->f_bavail = sbi->sb_n_free; 184 169 buf->f_files = sbi->sb_dirband_size / 4; 185 - buf->f_ffree = sbi->sb_n_free_dnodes; 170 + buf->f_ffree = hpfs_get_free_dnodes(s); 186 171 buf->f_fsid.val[0] = (u32)id; 187 172 buf->f_fsid.val[1] = (u32)(id >> 32); 188 173 buf->f_namelen = 254;