diff options
Diffstat (limited to 'fs/hpfs/alloc.c')
| -rw-r--r-- | fs/hpfs/alloc.c | 68 | 
1 files changed, 65 insertions, 3 deletions
diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index cdb84a83806..f005046e159 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c @@ -8,6 +8,58 @@  #include "hpfs_fn.h" +static void hpfs_claim_alloc(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free != (unsigned)-1) { +		if (unlikely(!sbi->sb_n_free)) { +			hpfs_error(s, "free count underflow, allocating sector %08x", sec); +			sbi->sb_n_free = -1; +			return; +		} +		sbi->sb_n_free--; +	} +} + +static void hpfs_claim_free(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free != (unsigned)-1) { +		if (unlikely(sbi->sb_n_free >= sbi->sb_fs_size)) { +			hpfs_error(s, "free count overflow, freeing sector %08x", sec); +			sbi->sb_n_free = -1; +			return; +		} +		sbi->sb_n_free++; +	} +} + +static void hpfs_claim_dirband_alloc(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free_dnodes != (unsigned)-1) { +		if (unlikely(!sbi->sb_n_free_dnodes)) { +			hpfs_error(s, "dirband free count underflow, allocating sector %08x", sec); +			sbi->sb_n_free_dnodes = -1; +			return; +		} +		sbi->sb_n_free_dnodes--; +	} +} + +static void hpfs_claim_dirband_free(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free_dnodes != (unsigned)-1) { +		if (unlikely(sbi->sb_n_free_dnodes >= sbi->sb_dirband_size / 4)) { +			hpfs_error(s, "dirband free count overflow, freeing sector %08x", sec); +			sbi->sb_n_free_dnodes = -1; +			return; +		} +		sbi->sb_n_free_dnodes++; +	} +} +  /*   * Check if a sector is allocated in bitmap   * 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  	}  	sec = 0;  	ret: +	if (sec) { +		i = 0; +		do +			hpfs_claim_alloc(s, sec + i); +		while (unlikely(++i < n)); +	}  	if (sec && f_p) {  		for (i = 0; i < forward; i++) { -			if (!hpfs_alloc_if_possible(s, sec + i + 1)) { +			if (!hpfs_alloc_if_possible(s, sec + n + i)) {  				hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i);  				sec = 0;  				break; @@ -228,6 +286,7 @@ static secno alloc_in_dirband(struct super_block *s, secno near)  	nr >>= 2;  	sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0);  	if (!sec) return 0; +	hpfs_claim_dirband_alloc(s, sec);  	return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start;  } @@ -242,6 +301,7 @@ int hpfs_alloc_if_possible(struct super_block *s, secno sec)  		bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f)));  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh); +		hpfs_claim_alloc(s, sec);  		return 1;  	}  	hpfs_brelse4(&qbh); @@ -256,7 +316,7 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)  	struct quad_buffer_head qbh;  	__le32 *bmp;  	struct hpfs_sb_info *sbi = hpfs_sb(s); -	/*printk("2 - ");*/ +	/*pr_info("2 - ");*/  	if (!n) return;  	if (sec < 0x12) {  		hpfs_error(s, "Trying to free reserved sector %08x", sec); @@ -275,6 +335,7 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)  		return;  	}  	bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f)); +	hpfs_claim_free(s, sec);  	if (!--n) {  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh); @@ -359,6 +420,7 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno)  		bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f));  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh); +		hpfs_claim_dirband_free(s, dno);  	}  } @@ -366,7 +428,7 @@ struct dnode *hpfs_alloc_dnode(struct super_block *s, secno near,  			 dnode_secno *dno, struct quad_buffer_head *qbh)  {  	struct dnode *d; -	if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) { +	if (hpfs_get_free_dnodes(s) > FREE_DNODES_ADD) {  		if (!(*dno = alloc_in_dirband(s, near)))  			if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL;  	} else {  | 
