[PATCH] ext4: e2fsprogs: fix inode bitmap num not integer,incompatible for ancient android devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



for example, 1708 inodes every group,3 block groups, bitmap bytes are 1708/8=213.5 when the inode bitmap has some errors, e2fsprogs cannot fix it

Signed-off-by: GaoMing <gaoming20@xxxxxxxxxx>
---
 e2fsck/pass5.c          |  9 ++++-----
 lib/ext2fs/imager.c     | 35 +++++++++++++++++++++++++++--------
 lib/ext2fs/rw_bitmaps.c | 39 ++++++++++++++++++++++++++++-----------
 misc/dumpe2fs.c         |  4 ++--
 4 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 7803e8b..4970dae 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -95,7 +95,7 @@ static void check_inode_bitmap_checksum(e2fsck_t ctx)
 	if (ext2fs_test_ib_dirty(ctx->fs))
 		return;
 
-	nbytes = (size_t)(EXT2_INODES_PER_GROUP(ctx->fs->super) / 8);
+	nbytes = (size_t)((EXT2_INODES_PER_GROUP(ctx->fs->super)+7) / 8);
 	retval = ext2fs_get_mem(ctx->fs->blocksize, &buf);
 	if (retval) {
 		com_err(ctx->program_name, 0, "%s",
@@ -108,14 +108,13 @@ static void check_inode_bitmap_checksum(e2fsck_t ctx)
 		if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_INODE_UNINIT))
 			continue;
 
-		ino_itr = 1 + (i * (nbytes << 3));
+		ino_itr = 1 + (i * EXT2_INODES_PER_GROUP(ctx->fs->super));
 		retval = ext2fs_get_inode_bitmap_range2(ctx->fs->inode_map,
-							ino_itr, nbytes << 3,
+							ino_itr, EXT2_INODES_PER_GROUP(ctx->fs->super),
 							buf);
 		if (retval)
 			break;
-
-		if (ext2fs_inode_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
+		if (ext2fs_inode_bitmap_csum_verify(ctx->fs, i, buf, EXT2_INODES_PER_GROUP(ctx->fs->super) / 8))
 			continue;
 		pctx.group = i;
 		if (!fix_problem(ctx, PR_5_INODE_BITMAP_CSUM_INVALID, &pctx))
diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c
index 7fd06f7..346ec70 100644
--- a/lib/ext2fs/imager.c
+++ b/lib/ext2fs/imager.c
@@ -341,7 +341,8 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
 		bmap = fs->inode_map;
 		itr = 1;
 		cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
-		size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
+		size = ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
+		total_size = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count+7)/8;
 	} else {
 		if (!fs->block_map) {
 			retval = ext2fs_read_block_bitmap(fs);
@@ -352,13 +353,14 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
 		itr = fs->super->s_first_data_block;
 		cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count);
 		size = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
+		total_size = size * fs->group_desc_count;
 	}
-	total_size = size * fs->group_desc_count;
+
 
 	while (cnt > 0) {
 		size = sizeof(buf);
-		if (size > (cnt >> 3))
-			size = (cnt >> 3);
+		if (size > ((cnt+7) >> 3))
+			size = ((cnt+7) >> 3);
 
 		retval = ext2fs_get_generic_bmap_range(bmap, itr,
 						       size << 3, buf);
@@ -372,7 +374,10 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
 			return EXT2_ET_SHORT_READ;
 
 		itr += size << 3;
-		cnt -= size << 3;
+		if (cnt < (size << 3))
+			cnt = 0;
+		else
+			cnt -= size << 3;
 	}
 
 	size = total_size % fs->blocksize;
@@ -406,6 +411,7 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
 	char			buf[1024];
 	unsigned int		size;
 	ssize_t			actual;
+	__u64			count, pos;
 
 	if (flags & IMAGER_FLAG_INODEMAP) {
 		if (!fs->inode_map) {
@@ -431,8 +437,8 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
 
 	while (cnt > 0) {
 		size = sizeof(buf);
-		if (size > (cnt >> 3))
-			size = (cnt >> 3);
+		if (size > ((cnt+7) >> 3))
+			size = ((cnt+7) >> 3);
 
 		actual = read(fd, buf, size);
 		if (actual == -1)
@@ -440,13 +446,26 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
 		if (actual != (int) size)
 			return EXT2_ET_SHORT_READ;
 
+		if (cnt%8 != 0 && cnt < sizeof(buf)) {
+			pos = cnt;
+			count = (((cnt + 7)>>3)<<3)-cnt;
+			while (count > 0) {
+				ext2fs_fast_clear_bit(pos, buf);
+				pos++;
+				count--;
+			}
+		}
+
 		retval = ext2fs_set_generic_bmap_range(bmap, itr,
 						       size << 3, buf);
 		if (retval)
 			return retval;
 
 		itr += size << 3;
-		cnt -= size << 3;
+		if (cnt < (size << 3))
+			cnt = 0;
+		else
+			cnt -= size << 3;
 	}
 	return 0;
 }
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index e86bacd..e2499ff 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -40,6 +40,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
 	blk64_t		blk;
 	blk64_t		blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
 	ext2_ino_t	ino_itr = 1;
+	__u64 count, pos;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -115,19 +116,25 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
 		if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)
 		    )
 			goto skip_this_inode_bitmap;
-
 		retval = ext2fs_get_inode_bitmap_range2(fs->inode_map,
-				ino_itr, inode_nbytes << 3, inode_buf);
+				ino_itr, EXT2_INODES_PER_GROUP(fs->super), inode_buf);
 		if (retval)
 			goto errout;
-
 		retval = ext2fs_inode_bitmap_csum_set(fs, i, inode_buf,
-						      inode_nbytes);
+						      EXT2_INODES_PER_GROUP(fs->super) / 8);
 		if (retval)
 			goto errout;
+		if (EXT2_INODES_PER_GROUP(fs->super)%8 != 0) {
+			pos = EXT2_INODES_PER_GROUP(fs->super);
+			count = (((pos + 7) >> 3)<<3)-pos;
+			while (count > 0) {
+				ext2fs_fast_set_bit(pos, inode_buf);
+				pos++;
+				count--;
+			}
+		}
 		ext2fs_group_desc_csum_set(fs, i);
 		fs->flags |= EXT2_FLAG_DIRTY;
-
 		blk = ext2fs_inode_bitmap_loc(fs, i);
 		if (blk) {
 			retval = io_channel_write_blk64(fs->io, blk, 1,
@@ -138,7 +145,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
 			}
 		}
 	skip_this_inode_bitmap:
-		ino_itr += inode_nbytes << 3;
+		ino_itr += EXT2_INODES_PER_GROUP(fs->super);
 
 	}
 	if (do_block) {
@@ -202,7 +209,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
 	char *buf;
 	errcode_t retval;
 	int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
-	int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
+	int inode_nbytes = (EXT2_INODES_PER_GROUP(fs->super) + 7) / 8;
 	int csum_flag;
 	unsigned int	cnt;
 	blk64_t	blk;
@@ -210,6 +217,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
 	blk64_t   blk_cnt;
 	ext2_ino_t ino_itr = 1;
 	ext2_ino_t ino_cnt;
+	__u64 count, pos;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -337,24 +345,33 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
 					retval = EXT2_ET_INODE_BITMAP_READ;
 					goto cleanup;
 				}
-
+				if (EXT2_INODES_PER_GROUP(fs->super)%8 != 0) {
+					pos = EXT2_INODES_PER_GROUP(fs->super);
+					count = (((pos + 7) >> 3)<<3)-pos;
+					while (count > 0) {
+						ext2fs_fast_clear_bit(pos, inode_bitmap);
+						pos++;
+						count--;
+					}
+				}
 				/* verify inode bitmap checksum */
 				if (!(fs->flags &
 				      EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
 				    !ext2fs_inode_bitmap_csum_verify(fs, i,
-						inode_bitmap, inode_nbytes)) {
+						inode_bitmap,
+						EXT2_INODES_PER_GROUP(fs->super) / 8)) {
 					retval =
 					EXT2_ET_INODE_BITMAP_CSUM_INVALID;
 					goto cleanup;
 				}
 			} else
 				memset(inode_bitmap, 0, inode_nbytes);
-			cnt = inode_nbytes << 3;
+			cnt = EXT2_INODES_PER_GROUP(fs->super);
 			retval = ext2fs_set_inode_bitmap_range2(fs->inode_map,
 					       ino_itr, cnt, inode_bitmap);
 			if (retval)
 				goto cleanup;
-			ino_itr += inode_nbytes << 3;
+			ino_itr += EXT2_INODES_PER_GROUP(fs->super);
 		}
 	}
 
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 395ea9e..5cf431a 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -168,7 +168,7 @@ static void list_desc(ext2_filsys fs, int grp_only)
 		units = _("clusters");
 
 	block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
-	inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
+	inode_nbytes = (EXT2_INODES_PER_GROUP(fs->super)+7) / 8;
 
 	if (fs->block_map)
 		block_bitmap = malloc(block_nbytes);
@@ -303,7 +303,7 @@ static void list_desc(ext2_filsys fs, int grp_only)
 		if (inode_bitmap) {
 			fputs(_("  Free inodes: "), stdout);
 			retval = ext2fs_get_inode_bitmap_range2(fs->inode_map,
-				 ino_itr, inode_nbytes << 3, inode_bitmap);
+				 ino_itr, EXT2_INODES_PER_GROUP(fs->super), inode_bitmap);
 			if (retval)
 				com_err("list_desc", retval,
 					"while reading inode bitmap");
-- 
2.8.1




[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux