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

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