diff options
Diffstat (limited to 'fs/ext4/ialloc.c')
| -rw-r--r-- | fs/ext4/ialloc.c | 30 | 
1 files changed, 23 insertions, 7 deletions
| diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index f525f909b559..2addcb8730e1 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -90,6 +90,8 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,  		return -EFSCORRUPTED;  	ext4_lock_group(sb, block_group); +	if (buffer_verified(bh)) +		goto verified;  	blk = ext4_inode_bitmap(sb, desc);  	if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh,  					   EXT4_INODES_PER_GROUP(sb) / 8)) { @@ -101,6 +103,7 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,  		return -EFSBADCRC;  	}  	set_buffer_verified(bh); +verified:  	ext4_unlock_group(sb, block_group);  	return 0;  } @@ -135,9 +138,9 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)  	}  	bh = sb_getblk(sb, bitmap_blk);  	if (unlikely(!bh)) { -		ext4_error(sb, "Cannot read inode bitmap - " -			    "block_group = %u, inode_bitmap = %llu", -			    block_group, bitmap_blk); +		ext4_warning(sb, "Cannot read inode bitmap - " +			     "block_group = %u, inode_bitmap = %llu", +			     block_group, bitmap_blk);  		return ERR_PTR(-ENOMEM);  	}  	if (bitmap_uptodate(bh)) @@ -150,7 +153,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)  	}  	ext4_lock_group(sb, block_group); -	if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { +	if (ext4_has_group_desc_csum(sb) && +	    (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) { +		if (block_group == 0) { +			ext4_unlock_group(sb, block_group); +			unlock_buffer(bh); +			ext4_error(sb, "Inode bitmap for bg 0 marked " +				   "uninitialized"); +			err = -EFSCORRUPTED; +			goto out; +		}  		memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);  		ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb),  				     sb->s_blocksize * 8, bh->b_data); @@ -994,7 +1006,8 @@ got:  		/* recheck and clear flag under lock if we still need to */  		ext4_lock_group(sb, group); -		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { +		if (ext4_has_group_desc_csum(sb) && +		    (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {  			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);  			ext4_free_group_clusters_set(sb, gdp,  				ext4_free_clusters_after_init(sb, group, gdp)); @@ -1073,7 +1086,7 @@ got:  	/* This is the optimal IO size (for stat), not the fs block size */  	inode->i_blocks = 0;  	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); -	ei->i_crtime = timespec64_to_timespec(inode->i_mtime); +	ei->i_crtime = inode->i_mtime;  	memset(ei->i_data, 0, sizeof(ei->i_data));  	ei->i_dir_start_lookup = 0; @@ -1375,7 +1388,10 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,  			    ext4_itable_unused_count(sb, gdp)),  			    sbi->s_inodes_per_block); -	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) { +	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group) || +	    ((group == 0) && ((EXT4_INODES_PER_GROUP(sb) - +			       ext4_itable_unused_count(sb, gdp)) < +			      EXT4_FIRST_INO(sb)))) {  		ext4_error(sb, "Something is wrong with group %u: "  			   "used itable blocks: %d; "  			   "itable unused count: %u", |