Blame SOURCES/e2fsprogs-1.42.9-libext2fs-don-t-always-read-backup-group-descriptors.patch

0ef434
From 9a7df1b3a2d139ed930ff9ed606b804e71df1cce Mon Sep 17 00:00:00 2001
0ef434
From: "Darrick J. Wong" <darrick.wong@oracle.com>
0ef434
Date: Sat, 11 Jan 2014 13:58:15 -0500
0ef434
Subject: [PATCH 2/2] libext2fs: don't always read backup group descriptors on
0ef434
 a 1k-block meta_bg fs
0ef434
0ef434
On a filesystem with 1K blocks and meta_bg enabled, opening a
0ef434
filesystem with automatic superblock detection tries to compensate for
0ef434
the fact that the superblock lives in block 1.  However, the method by
0ef434
which this is done is later misinterpreted to mean "read the backup
0ef434
group descriptors", which is not what we want in this case.
0ef434
0ef434
Therefore, in ext2fs_open3() separate the 'group zero' adjustment into
0ef434
its own variable so that we don't get fed backup group descriptors
0ef434
when we try to load meta_bg group descriptors.
0ef434
0ef434
Furthermore, enhance ext2fs_descriptor_block_loc2() to perform its own
0ef434
group zero correction.  The other caller of this function neglects to
0ef434
do any group-zero correction of their own, so this fixes them too.
0ef434
0ef434
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
0ef434
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
0ef434
---
0ef434
 lib/ext2fs/ext2fs.h |  5 +++++
0ef434
 lib/ext2fs/openfs.c | 30 +++++++++++++++++++++++++-----
0ef434
 2 files changed, 30 insertions(+), 5 deletions(-)
0ef434
0ef434
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
0ef434
index cb03ecf..380608b 100644
0ef434
--- a/lib/ext2fs/ext2fs.h
0ef434
+++ b/lib/ext2fs/ext2fs.h
0ef434
@@ -1376,6 +1376,11 @@ extern errcode_t ext2fs_open2(const char *name, const char *io_options,
0ef434
 			      int flags, int superblock,
0ef434
 			      unsigned int block_size, io_manager manager,
0ef434
 			      ext2_filsys *ret_fs);
0ef434
+/*
0ef434
+ * The dgrp_t argument to these two functions is not actually a group number
0ef434
+ * but a block number offset within a group table!  Convert with the formula
0ef434
+ * (group_number / groups_per_block).
0ef434
+ */
0ef434
 extern blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs,
0ef434
 					blk64_t group_block, dgrp_t i);
0ef434
 extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
0ef434
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
0ef434
index b27bf19..ba501e6 100644
0ef434
--- a/lib/ext2fs/openfs.c
0ef434
+++ b/lib/ext2fs/openfs.c
0ef434
@@ -37,12 +37,19 @@ blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
0ef434
 				     dgrp_t i)
0ef434
 {
0ef434
 	int	bg;
0ef434
-	int	has_super = 0;
0ef434
+	int	has_super = 0, group_zero_adjust = 0;
0ef434
 	blk64_t	ret_blk;
0ef434
 
0ef434
+	/*
0ef434
+	 * On a bigalloc FS with 1K blocks, block 0 is reserved for non-ext4
0ef434
+	 * stuff, so adjust for that if we're being asked for group 0.
0ef434
+	 */
0ef434
+	if (i == 0 && fs->blocksize == 1024 && EXT2FS_CLUSTER_RATIO(fs) > 1)
0ef434
+		group_zero_adjust = 1;
0ef434
+
0ef434
 	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
0ef434
 	    (i < fs->super->s_first_meta_bg))
0ef434
-		return (group_block + i + 1);
0ef434
+		return group_block + i + 1 + group_zero_adjust;
0ef434
 
0ef434
 	bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
0ef434
 	if (ext2fs_bg_has_super(fs, bg))
0ef434
@@ -71,7 +78,7 @@ blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
0ef434
 		else
0ef434
 			has_super = 0;
0ef434
 	}
0ef434
-	return ret_blk + has_super;
0ef434
+	return ret_blk + has_super + group_zero_adjust;
0ef434
 }
0ef434
 
0ef434
 blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
0ef434
@@ -113,6 +120,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
0ef434
 	unsigned int	blocks_per_group, io_flags;
0ef434
 	blk64_t		group_block, blk;
0ef434
 	char		*dest, *cp;
0ef434
+	int		group_zero_adjust = 0;
0ef434
 #ifdef WORDS_BIGENDIAN
0ef434
 	unsigned int	groups_per_block;
0ef434
 	struct ext2_group_desc *gdp;
0ef434
@@ -353,8 +361,19 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
0ef434
 		goto cleanup;
0ef434
 	if (!group_block)
0ef434
 		group_block = fs->super->s_first_data_block;
0ef434
+	/*
0ef434
+	 * On a FS with a 1K blocksize, block 0 is reserved for bootloaders
0ef434
+	 * so we must increment block numbers to any group 0 items.
0ef434
+	 *
0ef434
+	 * However, we cannot touch group_block directly because in the meta_bg
0ef434
+	 * case, the ext2fs_descriptor_block_loc2() function will interpret
0ef434
+	 * group_block != s_first_data_block to mean that we want to access the
0ef434
+	 * backup group descriptors.  This is not what we want if the caller
0ef434
+	 * set superblock == 0 (i.e. auto-detect the superblock), which is
0ef434
+	 * what's going on here.
0ef434
+	 */
0ef434
 	if (group_block == 0 && fs->blocksize == 1024)
0ef434
-		group_block = 1; /* Deal with 1024 blocksize && bigalloc */
0ef434
+		group_zero_adjust = 1;
0ef434
 	dest = (char *) fs->group_desc;
0ef434
 #ifdef WORDS_BIGENDIAN
0ef434
 	groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
0ef434
@@ -366,7 +385,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
0ef434
 	} else
0ef434
 		first_meta_bg = fs->desc_blocks;
0ef434
 	if (first_meta_bg) {
0ef434
-		retval = io_channel_read_blk(fs->io, group_block+1,
0ef434
+		retval = io_channel_read_blk(fs->io, group_block +
0ef434
+					     group_zero_adjust + 1,
0ef434
 					     first_meta_bg, dest);
0ef434
 		if (retval)
0ef434
 			goto cleanup;
0ef434
-- 
0ef434
2.17.1
0ef434