c4a49e5c9a
Resolves: #2247926 Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
116 lines
4.2 KiB
Diff
116 lines
4.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Anthony Iliopoulos <ailiop@suse.com>
|
|
Date: Thu, 26 Oct 2023 11:53:39 +0200
|
|
Subject: [PATCH] fs/xfs: Add large extent counters incompat feature support
|
|
|
|
XFS introduced 64-bit extent counters for inodes via a series of
|
|
upstream commits and the feature was marked as stable in v6.5 via
|
|
commit 61d7e8274cd8 (xfs: drop EXPERIMENTAL tag for large extent
|
|
counts).
|
|
|
|
Further, xfsprogs release v6.5.0 switched this feature on by default
|
|
in mkfs.xfs via commit e5b18d7d1d96 (mkfs: enable large extent counts
|
|
by default).
|
|
|
|
Filesystems formatted with large extent count support, nrext64=1, are
|
|
thus currently not recognizable by GRUB, since this is an incompat
|
|
feature. Add the required support so that those filesystems and inodes
|
|
with large extent counters can be read by GRUB.
|
|
|
|
Signed-off-by: Anthony Iliopoulos <ailiop@suse.com>
|
|
Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
Tested-by: Marta Lewandowska <mlewando@redhat.com>
|
|
Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
|
|
---
|
|
grub-core/fs/xfs.c | 30 +++++++++++++++++++++++++-----
|
|
1 file changed, 25 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
|
index 18edfcff486c..bc2224dbb463 100644
|
|
--- a/grub-core/fs/xfs.c
|
|
+++ b/grub-core/fs/xfs.c
|
|
@@ -79,6 +79,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|
/* Inode flags2 flags */
|
|
#define XFS_DIFLAG2_BIGTIME_BIT 3
|
|
#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT)
|
|
+#define XFS_DIFLAG2_NREXT64_BIT 4
|
|
+#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT)
|
|
|
|
/* incompat feature flags */
|
|
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
|
|
@@ -86,6 +88,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
|
|
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
|
|
#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */
|
|
+#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */
|
|
|
|
/*
|
|
* Directory entries with ftype are explicitly handled by GRUB code.
|
|
@@ -101,7 +104,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|
XFS_SB_FEAT_INCOMPAT_SPINODES | \
|
|
XFS_SB_FEAT_INCOMPAT_META_UUID | \
|
|
XFS_SB_FEAT_INCOMPAT_BIGTIME | \
|
|
- XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR)
|
|
+ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \
|
|
+ XFS_SB_FEAT_INCOMPAT_NREXT64)
|
|
|
|
struct grub_xfs_sblock
|
|
{
|
|
@@ -203,7 +207,8 @@ struct grub_xfs_inode
|
|
grub_uint16_t mode;
|
|
grub_uint8_t version;
|
|
grub_uint8_t format;
|
|
- grub_uint8_t unused2[26];
|
|
+ grub_uint8_t unused2[18];
|
|
+ grub_uint64_t nextents_big;
|
|
grub_uint64_t atime;
|
|
grub_uint64_t mtime;
|
|
grub_uint64_t ctime;
|
|
@@ -545,11 +550,26 @@ get_fsb (const void *keys, int idx)
|
|
return grub_be_to_cpu64 (grub_get_unaligned64 (p));
|
|
}
|
|
|
|
+static int
|
|
+grub_xfs_inode_has_large_extent_counts (const struct grub_xfs_inode *inode)
|
|
+{
|
|
+ return inode->version >= 3 &&
|
|
+ (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_NREXT64));
|
|
+}
|
|
+
|
|
+static grub_uint64_t
|
|
+grub_xfs_get_inode_nextents (struct grub_xfs_inode *inode)
|
|
+{
|
|
+ return (grub_xfs_inode_has_large_extent_counts (inode)) ?
|
|
+ grub_be_to_cpu64 (inode->nextents_big) :
|
|
+ grub_be_to_cpu32 (inode->nextents);
|
|
+}
|
|
+
|
|
static grub_disk_addr_t
|
|
grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
|
{
|
|
struct grub_xfs_btree_node *leaf = 0;
|
|
- int ex, nrec;
|
|
+ grub_uint64_t ex, nrec;
|
|
struct grub_xfs_extent *exts;
|
|
grub_uint64_t ret = 0;
|
|
|
|
@@ -574,7 +594,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
|
/ (2 * sizeof (grub_uint64_t));
|
|
do
|
|
{
|
|
- int i;
|
|
+ grub_uint64_t i;
|
|
|
|
for (i = 0; i < nrec; i++)
|
|
{
|
|
@@ -621,7 +641,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
|
grub_addr_t exts_end = 0;
|
|
grub_addr_t data_end = 0;
|
|
|
|
- nrec = grub_be_to_cpu32 (node->inode.nextents);
|
|
+ nrec = grub_xfs_get_inode_nextents (&node->inode);
|
|
exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode);
|
|
|
|
if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) ||
|