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

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