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