diff options
Diffstat (limited to 'fs/hpfs/alloc.c')
-rw-r--r-- | fs/hpfs/alloc.c | 66 |
1 files changed, 64 insertions, 2 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 | ||
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 | * 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 { |