|
|
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 |
|