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

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