diff options
Diffstat (limited to 'fs/ext4/ialloc.c')
| -rw-r--r-- | fs/ext4/ialloc.c | 39 | 
1 files changed, 31 insertions, 8 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 137193ff389..5b87fc36aab 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -71,6 +71,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,  				       struct ext4_group_desc *gdp)  {  	struct ext4_group_info *grp; +	struct ext4_sb_info *sbi = EXT4_SB(sb);  	J_ASSERT_BH(bh, buffer_locked(bh));  	/* If checksum is bad mark all blocks and inodes use to prevent @@ -78,7 +79,16 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,  	if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {  		ext4_error(sb, "Checksum bad for group %u", block_group);  		grp = ext4_get_group_info(sb, block_group); +		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) +			percpu_counter_sub(&sbi->s_freeclusters_counter, +					   grp->bb_free);  		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); +		if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { +			int count; +			count = ext4_free_inodes_count(sb, gdp); +			percpu_counter_sub(&sbi->s_freeinodes_counter, +					   count); +		}  		set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);  		return 0;  	} @@ -116,6 +126,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)  	struct buffer_head *bh = NULL;  	ext4_fsblk_t bitmap_blk;  	struct ext4_group_info *grp; +	struct ext4_sb_info *sbi = EXT4_SB(sb);  	desc = ext4_get_group_desc(sb, block_group, NULL);  	if (!desc) @@ -185,6 +196,12 @@ verify:  		ext4_error(sb, "Corrupt inode bitmap - block_group = %u, "  			   "inode_bitmap = %llu", block_group, bitmap_blk);  		grp = ext4_get_group_info(sb, block_group); +		if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { +			int count; +			count = ext4_free_inodes_count(sb, desc); +			percpu_counter_sub(&sbi->s_freeinodes_counter, +					   count); +		}  		set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);  		return NULL;  	} @@ -321,6 +338,12 @@ out:  			fatal = err;  	} else {  		ext4_error(sb, "bit already cleared for inode %lu", ino); +		if (gdp && !EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { +			int count; +			count = ext4_free_inodes_count(sb, gdp); +			percpu_counter_sub(&sbi->s_freeinodes_counter, +					   count); +		}  		set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);  	} @@ -432,7 +455,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,  			ext4fs_dirhash(qstr->name, qstr->len, &hinfo);  			grp = hinfo.hash;  		} else -			get_random_bytes(&grp, sizeof(grp)); +			grp = prandom_u32();  		parent_group = (unsigned)grp % ngroups;  		for (i = 0; i < ngroups; i++) {  			g = (parent_group + i) % ngroups; @@ -851,6 +874,13 @@ got:  		goto out;  	} +	BUFFER_TRACE(group_desc_bh, "get_write_access"); +	err = ext4_journal_get_write_access(handle, group_desc_bh); +	if (err) { +		ext4_std_error(sb, err); +		goto out; +	} +  	/* We may have to initialize the block bitmap if it isn't already */  	if (ext4_has_group_desc_csum(sb) &&  	    gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { @@ -887,13 +917,6 @@ got:  		}  	} -	BUFFER_TRACE(group_desc_bh, "get_write_access"); -	err = ext4_journal_get_write_access(handle, group_desc_bh); -	if (err) { -		ext4_std_error(sb, err); -		goto out; -	} -  	/* Update the relevant bg descriptor fields */  	if (ext4_has_group_desc_csum(sb)) {  		int free;  | 
