-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Erwan Velu <erwanaliasr1@gmail.com>
-Date: Wed, 25 Aug 2021 15:31:52 +0200
-Subject: [PATCH] fs/xfs: Fix unreadable filesystem with v4 superblock
-
-The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support)
-introduced the bigtime support by adding some features in v3 inodes.
-This change extended grub_xfs_inode struct by 76 bytes but also changed
-the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this
-commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes
-XFS_V2_INODE_SIZE becomes 16 bytes too small.
-
-As a result, the data structures aren't properly aligned and the GRUB
-generates "attempt to read or write outside of partition" errors when
-trying to read the XFS filesystem:
-
- GNU GRUB version 2.11
- ....
- grub> set debug=efi,gpt,xfs
- grub> insmod part_gpt
- grub> ls (hd0,gpt1)/
- partmap/gpt.c:93: Read a valid GPT header
- partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125
- fs/xfs.c:931: Reading sb
- fs/xfs.c:270: Validating superblock
- fs/xfs.c:295: XFS v4 superblock detected
- fs/xfs.c:962: Reading root ino 128
- fs/xfs.c:515: Reading inode (128) - 64, 0
- fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840
- error: attempt to read or write outside of partition.
-
-This commit change the XFS_V2_INODE_SIZE computation by subtracting 76
-bytes instead of 92 bytes from the actual size of grub_xfs_inode struct.
-This 76 bytes value comes from added members:
- 20 grub_uint8_t unused5
- 1 grub_uint64_t flags2
- 48 grub_uint8_t unused6
-
-This patch explicitly splits the v2 and v3 parts of the structure.
-The unused4 is still ending of the v2 structures and the v3 starts
-at unused5. Thanks to this we will avoid future corruptions of v2
-or v3 inodes.
-
-The XFS_V2_INODE_SIZE is returning to its expected size and the
-filesystem is back to a readable state:
-
- GNU GRUB version 2.11
- ....
- grub> set debug=efi,gpt,xfs
- grub> insmod part_gpt
- grub> ls (hd0,gpt1)/
- partmap/gpt.c:93: Read a valid GPT header
- partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125
- fs/xfs.c:931: Reading sb
- fs/xfs.c:270: Validating superblock
- fs/xfs.c:295: XFS v4 superblock detected
- fs/xfs.c:962: Reading root ino 128
- fs/xfs.c:515: Reading inode (128) - 64, 0
- fs/xfs.c:515: Reading inode (128) - 64, 0
- fs/xfs.c:931: Reading sb
- fs/xfs.c:270: Validating superblock
- fs/xfs.c:295: XFS v4 superblock detected
- fs/xfs.c:962: Reading root ino 128
- fs/xfs.c:515: Reading inode (128) - 64, 0
- fs/xfs.c:515: Reading inode (128) - 64, 0
- fs/xfs.c:515: Reading inode (128) - 64, 0
- fs/xfs.c:515: Reading inode (131) - 64, 768
- efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0
- grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024
- grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816
- grub>
-
-Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support)
-
-Signed-off-by: Erwan Velu <e.velu@criteo.com>
-Tested-by: Carlos Maiolino <cmaiolino@redhat.com>
-Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
-(cherry picked from commit a4b495520e4dc41a896a8b916a64eda9970c50ea)
----
- grub-core/fs/xfs.c | 14 ++++++++++----
- 1 file changed, 10 insertions(+), 4 deletions(-)
-
-diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
-index 0f524c3a8a..e3816d1ec4 100644
---- a/grub-core/fs/xfs.c
-+++ b/grub-core/fs/xfs.c
-@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy
- grub_uint32_t nanosec;
- } GRUB_PACKED;
-
-+/*
-+ * The struct grub_xfs_inode layout was taken from the
-+ * struct xfs_dinode_core which is described here:
-+ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
-+ */
- struct grub_xfs_inode
- {
- grub_uint8_t magic[2];
-@@ -208,14 +213,15 @@ struct grub_xfs_inode
- grub_uint32_t nextents;
- grub_uint16_t unused3;
- grub_uint8_t fork_offset;
-- grub_uint8_t unused4[37];
-+ grub_uint8_t unused4[17]; /* Last member of inode v2. */
-+ grub_uint8_t unused5[20]; /* First member of inode v3. */
- grub_uint64_t flags2;
-- grub_uint8_t unused5[48];
-+ grub_uint8_t unused6[48]; /* Last member of inode v3. */
- } GRUB_PACKED;
-
- #define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode)
--/* Size of struct grub_xfs_inode until fork_offset (included). */
--#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92)
-+/* Size of struct grub_xfs_inode v2, up to unused4 member included. */
-+#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76)
-
- struct grub_xfs_dirblock_tail
- {