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

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