8c6b1ac71e
Also include some minor fixes for gcc 5.1.1 Signed-off-by: Peter Jones <pjones@redhat.com>
135 lines
5.2 KiB
Diff
135 lines
5.2 KiB
Diff
From e20aa39ea4298011ba716087713cff26c6c52006 Mon Sep 17 00:00:00 2001
|
||
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||
Date: Mon, 16 Feb 2015 20:53:26 +0100
|
||
Subject: [PATCH 293/506] ext2: Support META_BG.
|
||
|
||
This fixes bug that system would become unbootable after ext*
|
||
online resize if no resize_inode was created at ext* format time.
|
||
---
|
||
grub-core/fs/ext2.c | 61 +++++++++++++++++++++++++++++++++++++++++---
|
||
tests/ext234_test.in | 1 +
|
||
tests/util/grub-fs-tester.in | 6 ++++-
|
||
3 files changed, 63 insertions(+), 5 deletions(-)
|
||
|
||
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
|
||
index 44c7974..4d45edc 100644
|
||
--- a/grub-core/fs/ext2.c
|
||
+++ b/grub-core/fs/ext2.c
|
||
@@ -107,6 +107,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||
#define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \
|
||
| EXT4_FEATURE_INCOMPAT_EXTENTS \
|
||
| EXT4_FEATURE_INCOMPAT_FLEX_BG \
|
||
+ | EXT2_FEATURE_INCOMPAT_META_BG \
|
||
| EXT4_FEATURE_INCOMPAT_64BIT)
|
||
/* List of rationales for the ignored "incompatible" features:
|
||
* needs_recovery: Not really back-incompatible - was added as such to forbid
|
||
@@ -331,16 +332,68 @@ static grub_dl_t my_mod;
|
||
|
||
|
||
|
||
+/* Check is a = b^x for some x. */
|
||
+static inline int
|
||
+is_power_of (grub_uint64_t a, grub_uint32_t b)
|
||
+{
|
||
+ grub_uint64_t c;
|
||
+ /* Prevent overflow assuming b < 8. */
|
||
+ if (a >= (1LL << 60))
|
||
+ return 0;
|
||
+ for (c = 1; c <= a; c *= b);
|
||
+ return (c == a);
|
||
+}
|
||
+
|
||
+
|
||
+static inline int
|
||
+group_has_super_block (struct grub_ext2_data *data, grub_uint64_t group)
|
||
+{
|
||
+ if (!(data->sblock.feature_ro_compat
|
||
+ & grub_cpu_to_le32_compile_time(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)))
|
||
+ return 1;
|
||
+ /* Algorithm looked up in Linux source. */
|
||
+ if (group <= 1)
|
||
+ return 1;
|
||
+ /* Even number is never a power of odd number. */
|
||
+ if (!(group & 1))
|
||
+ return 0;
|
||
+ return (is_power_of(group, 7) || is_power_of(group, 5) ||
|
||
+ is_power_of(group, 3));
|
||
+}
|
||
+
|
||
/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
|
||
the mounted filesystem DATA. */
|
||
inline static grub_err_t
|
||
-grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
|
||
+grub_ext2_blockgroup (struct grub_ext2_data *data, grub_uint64_t group,
|
||
struct grub_ext2_block_group *blkgrp)
|
||
{
|
||
+ grub_uint64_t full_offset = (group << data->log_group_desc_size);
|
||
+ grub_uint64_t block, offset;
|
||
+ block = (full_offset >> LOG2_BLOCK_SIZE (data));
|
||
+ offset = (full_offset & ((1 << LOG2_BLOCK_SIZE (data)) - 1));
|
||
+ if ((data->sblock.feature_incompat
|
||
+ & grub_cpu_to_le32_compile_time (EXT2_FEATURE_INCOMPAT_META_BG))
|
||
+ && block >= grub_le_to_cpu32(data->sblock.first_meta_bg))
|
||
+ {
|
||
+ grub_uint64_t first_block_group;
|
||
+ /* Find the first block group for which a descriptor
|
||
+ is stored in given block. */
|
||
+ first_block_group = (block << (LOG2_BLOCK_SIZE (data)
|
||
+ - data->log_group_desc_size));
|
||
+
|
||
+ block = (first_block_group
|
||
+ * grub_le_to_cpu32(data->sblock.blocks_per_group));
|
||
+
|
||
+ if (group_has_super_block (data, first_block_group))
|
||
+ block++;
|
||
+ }
|
||
+ else
|
||
+ /* Superblock. */
|
||
+ block++;
|
||
return grub_disk_read (data->disk,
|
||
- ((grub_le_to_cpu32 (data->sblock.first_data_block) + 1)
|
||
- << LOG2_EXT2_BLOCK_SIZE (data)),
|
||
- group << data->log_group_desc_size,
|
||
+ ((grub_le_to_cpu32 (data->sblock.first_data_block)
|
||
+ + block)
|
||
+ << LOG2_EXT2_BLOCK_SIZE (data)), offset,
|
||
sizeof (struct grub_ext2_block_group), blkgrp);
|
||
}
|
||
|
||
diff --git a/tests/ext234_test.in b/tests/ext234_test.in
|
||
index 8910b71..c986960 100644
|
||
--- a/tests/ext234_test.in
|
||
+++ b/tests/ext234_test.in
|
||
@@ -29,3 +29,4 @@ fi
|
||
"@builddir@/grub-fs-tester" ext2
|
||
"@builddir@/grub-fs-tester" ext3
|
||
"@builddir@/grub-fs-tester" ext4
|
||
+"@builddir@/grub-fs-tester" ext4_metabg
|
||
diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in
|
||
index 5656927..9ecbe0f 100644
|
||
--- a/tests/util/grub-fs-tester.in
|
||
+++ b/tests/util/grub-fs-tester.in
|
||
@@ -281,7 +281,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
|
||
#FSLABEL="g;/_é莭莽😁кит u"
|
||
;;
|
||
# FS LIMITATION: reiserfs, extN and jfs label is at most 16 UTF-8 characters
|
||
- x"reiserfs_old" | x"reiserfs" | x"ext2" | xext2_old | x"ext3" | x"ext4" | x"lvm"* | x"mdraid"* | x"jfs" | x"jfs_caseins")
|
||
+ x"reiserfs_old" | x"reiserfs" | x"ext"* | x"lvm"* | x"mdraid"* | x"jfs" | x"jfs_caseins")
|
||
FSLABEL="g;/éт 莭😁";;
|
||
# FS LIMITATION: No underscore, space, semicolon, slash or international characters in UFS* in label. Limited to 32 UTF-8 characters
|
||
x"ufs1" | x"ufs1_sun" | x"ufs2")
|
||
@@ -746,6 +746,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
|
||
MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext2" -r 0 -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}"
|
||
MOUNTFS=ext2
|
||
;;
|
||
+ xext4_metabg)
|
||
+ MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext4" -O meta_bg,^resize_inode -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}"
|
||
+ MOUNTFS=ext4
|
||
+ ;;
|
||
xext*)
|
||
MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
|
||
xxfs)
|
||
--
|
||
2.4.3
|
||
|