forked from pool/grub2
Accepting request 238591 from home:jankara:branches:Base:System
Support for XFS V5 superblock OBS-URL: https://build.opensuse.org/request/show/238591 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=93
This commit is contained in:
parent
a9f17210c7
commit
6d222d8bc9
76
grub2-xfs-Add-helper-for-inode-size.patch
Normal file
76
grub2-xfs-Add-helper-for-inode-size.patch
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
From 34231b28cbb6b2e10d7668c5b6d2432e8563bd1d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Kara <jack@suse.cz>
|
||||||
|
Date: Thu, 5 Jun 2014 20:56:21 +0200
|
||||||
|
Subject: [PATCH 1/4] xfs: Add helper for inode size
|
||||||
|
|
||||||
|
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||||
|
---
|
||||||
|
grub-core/fs/xfs.c | 17 +++++++++++------
|
||||||
|
1 file changed, 11 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||||
|
index 16ffd3f1ebd9..a2fc942707c1 100644
|
||||||
|
--- a/grub-core/fs/xfs.c
|
||||||
|
+++ b/grub-core/fs/xfs.c
|
||||||
|
@@ -255,6 +255,11 @@ grub_xfs_inode_offset (struct grub_xfs_data *data,
|
||||||
|
data->sblock.log2_inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline int
|
||||||
|
+grub_xfs_inode_size(struct grub_xfs_data *data)
|
||||||
|
+{
|
||||||
|
+ return 1 << data->sblock.log2_inode;
|
||||||
|
+}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
|
||||||
|
@@ -264,8 +269,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
|
||||||
|
int offset = grub_xfs_inode_offset (data, ino);
|
||||||
|
|
||||||
|
/* Read the inode. */
|
||||||
|
- if (grub_disk_read (data->disk, block, offset,
|
||||||
|
- 1 << data->sblock.log2_inode, inode))
|
||||||
|
+ if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data),
|
||||||
|
+ inode))
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
if (grub_strncmp ((char *) inode->magic, "IN", 2))
|
||||||
|
@@ -297,7 +302,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
|
if (node->inode.fork_offset)
|
||||||
|
recoffset = (node->inode.fork_offset - 1) / 2;
|
||||||
|
else
|
||||||
|
- recoffset = ((1 << node->data->sblock.log2_inode)
|
||||||
|
+ recoffset = (grub_xfs_inode_size(node->data)
|
||||||
|
- ((char *) &node->inode.data.btree.keys
|
||||||
|
- (char *) &node->inode))
|
||||||
|
/ (2 * sizeof (grub_uint64_t));
|
||||||
|
@@ -458,7 +463,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
|
||||||
|
|
||||||
|
fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
|
||||||
|
- sizeof (struct grub_xfs_inode)
|
||||||
|
- + (1 << ctx->diro->data->sblock.log2_inode) + 1);
|
||||||
|
+ + grub_xfs_inode_size(ctx->diro->data) + 1);
|
||||||
|
if (!fdiro)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
@@ -684,7 +689,7 @@ grub_xfs_mount (grub_disk_t disk)
|
||||||
|
data = grub_realloc (data,
|
||||||
|
sizeof (struct grub_xfs_data)
|
||||||
|
- sizeof (struct grub_xfs_inode)
|
||||||
|
- + (1 << data->sblock.log2_inode) + 1);
|
||||||
|
+ + grub_xfs_inode_size(data) + 1);
|
||||||
|
|
||||||
|
if (! data)
|
||||||
|
goto fail;
|
||||||
|
@@ -802,7 +807,7 @@ grub_xfs_open (struct grub_file *file, const char *name)
|
||||||
|
grub_memcpy (&data->diropen, fdiro,
|
||||||
|
sizeof (struct grub_fshelp_node)
|
||||||
|
- sizeof (struct grub_xfs_inode)
|
||||||
|
- + (1 << data->sblock.log2_inode));
|
||||||
|
+ + grub_xfs_inode_size(data));
|
||||||
|
grub_free (fdiro);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
1.8.1.4
|
||||||
|
|
@ -0,0 +1,82 @@
|
|||||||
|
From 57ae4073cc28fa74014a62aca397a40ce1f73763 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Kara <jack@suse.cz>
|
||||||
|
Date: Thu, 12 Jun 2014 11:01:11 +0200
|
||||||
|
Subject: [PATCH 3/4] xfs: Convert inode numbers to cpu endianity immediately
|
||||||
|
after reading
|
||||||
|
|
||||||
|
Currently XFS driver converted inode numbers to native endianity only
|
||||||
|
when using them to compute inode position. Although this works, it is
|
||||||
|
somewhat confusing. So convert inode numbers when reading them from disk
|
||||||
|
structures as every other field.
|
||||||
|
|
||||||
|
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||||
|
---
|
||||||
|
grub-core/fs/xfs.c | 13 ++++++-------
|
||||||
|
1 file changed, 6 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||||
|
index ef3bc787e968..7e247a32df5c 100644
|
||||||
|
--- a/grub-core/fs/xfs.c
|
||||||
|
+++ b/grub-core/fs/xfs.c
|
||||||
|
@@ -180,14 +180,14 @@ static inline grub_uint64_t
|
||||||
|
GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data,
|
||||||
|
grub_uint64_t ino)
|
||||||
|
{
|
||||||
|
- return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
|
||||||
|
+ return (ino & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline grub_uint64_t
|
||||||
|
GRUB_XFS_INO_AG (struct grub_xfs_data *data,
|
||||||
|
grub_uint64_t ino)
|
||||||
|
{
|
||||||
|
- return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data));
|
||||||
|
+ return (ino >> GRUB_XFS_INO_AGBITS (data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline grub_disk_addr_t
|
||||||
|
@@ -511,13 +511,12 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
if (smallino)
|
||||||
|
{
|
||||||
|
parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
|
||||||
|
- parent = grub_cpu_to_be64 (parent);
|
||||||
|
/* The header is a bit smaller than usual. */
|
||||||
|
de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- parent = diro->inode.data.dir.dirhead.parent.i8;
|
||||||
|
+ parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Synthesize the direntries for `.' and `..'. */
|
||||||
|
@@ -550,7 +549,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
| (((grub_uint64_t) inopos[5]) << 16)
|
||||||
|
| (((grub_uint64_t) inopos[6]) << 8)
|
||||||
|
| (((grub_uint64_t) inopos[7]) << 0);
|
||||||
|
- ino = grub_cpu_to_be64 (ino);
|
||||||
|
|
||||||
|
c = de->name[de->len];
|
||||||
|
de->name[de->len] = '\0';
|
||||||
|
@@ -632,7 +630,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
is not used by GRUB. So it can be overwritten. */
|
||||||
|
filename[direntry->len] = '\0';
|
||||||
|
|
||||||
|
- if (iterate_dir_call_hook (direntry->inode, filename, &ctx))
|
||||||
|
+ if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode),
|
||||||
|
+ filename, &ctx))
|
||||||
|
{
|
||||||
|
grub_free (dirblock);
|
||||||
|
return 1;
|
||||||
|
@@ -694,7 +693,7 @@ grub_xfs_mount (grub_disk_t disk)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
data->diropen.data = data;
|
||||||
|
- data->diropen.ino = data->sblock.rootino;
|
||||||
|
+ data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino);
|
||||||
|
data->diropen.inode_read = 1;
|
||||||
|
data->bsize = grub_be_to_cpu32 (data->sblock.bsize);
|
||||||
|
data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
|
||||||
|
--
|
||||||
|
1.8.1.4
|
||||||
|
|
32
grub2-xfs-Fix-termination-loop-for-directory-iteration.patch
Normal file
32
grub2-xfs-Fix-termination-loop-for-directory-iteration.patch
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
From a7d584c005bde09bb86475a79d714215b3480821 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Kara <jack@suse.cz>
|
||||||
|
Date: Wed, 11 Jun 2014 18:36:59 +0200
|
||||||
|
Subject: [PATCH 2/4] xfs: Fix termination loop for directory iteration
|
||||||
|
|
||||||
|
Directory iteration used wrong position (sizeof wrong structure) for
|
||||||
|
termination of iteration inside a directory block. Luckily the position
|
||||||
|
ended up being wrong by just 1 byte and directory entries are larger so
|
||||||
|
things worked out fine in practice. But fix the problem anyway.
|
||||||
|
|
||||||
|
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||||
|
---
|
||||||
|
grub-core/fs/xfs.c | 3 +--
|
||||||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||||
|
index a2fc942707c1..ef3bc787e968 100644
|
||||||
|
--- a/grub-core/fs/xfs.c
|
||||||
|
+++ b/grub-core/fs/xfs.c
|
||||||
|
@@ -608,8 +608,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
- grub_be_to_cpu32 (tail->leaf_stale));
|
||||||
|
|
||||||
|
/* Iterate over all entries within this block. */
|
||||||
|
- while (pos < (dirblk_size
|
||||||
|
- - (int) sizeof (struct grub_xfs_dir2_entry)))
|
||||||
|
+ while (pos < tail_start)
|
||||||
|
{
|
||||||
|
struct grub_xfs_dir2_entry *direntry;
|
||||||
|
grub_uint8_t *freetag;
|
||||||
|
--
|
||||||
|
1.8.1.4
|
||||||
|
|
481
grub2-xfs-V5-filesystem-format-support.patch
Normal file
481
grub2-xfs-V5-filesystem-format-support.patch
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
From 2f725e644d8ccf001a4dccddc8abb2c9479352a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Kara <jack@suse.cz>
|
||||||
|
Date: Wed, 11 Jun 2014 18:36:01 +0200
|
||||||
|
Subject: [PATCH] xfs: V5 filesystem format support
|
||||||
|
|
||||||
|
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||||
|
---
|
||||||
|
grub-core/fs/xfs.c | 245 +++++++++++++++++++++++++++++++++++++----------------
|
||||||
|
1 file changed, 173 insertions(+), 72 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
|
||||||
|
index 7e247a32df5c..3b1d8994067f 100644
|
||||||
|
--- a/grub-core/fs/xfs.c
|
||||||
|
+++ b/grub-core/fs/xfs.c
|
||||||
|
@@ -34,6 +34,15 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
#define XFS_INODE_FORMAT_EXT 2
|
||||||
|
#define XFS_INODE_FORMAT_BTREE 3
|
||||||
|
|
||||||
|
+/* Superblock version field flags */
|
||||||
|
+#define XFS_SB_VERSION_NUMBITS 0x000f
|
||||||
|
+#define XFS_SB_VERSION_MOREBITSBIT 0x8000
|
||||||
|
+
|
||||||
|
+/* features2 field flags */
|
||||||
|
+#define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */
|
||||||
|
+
|
||||||
|
+/* incompat feature flags */
|
||||||
|
+#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
|
||||||
|
|
||||||
|
struct grub_xfs_sblock
|
||||||
|
{
|
||||||
|
@@ -45,7 +54,9 @@ struct grub_xfs_sblock
|
||||||
|
grub_uint64_t rootino;
|
||||||
|
grub_uint8_t unused3[20];
|
||||||
|
grub_uint32_t agsize;
|
||||||
|
- grub_uint8_t unused4[20];
|
||||||
|
+ grub_uint8_t unused4[12];
|
||||||
|
+ grub_uint16_t version;
|
||||||
|
+ grub_uint8_t unused5[6];
|
||||||
|
grub_uint8_t label[12];
|
||||||
|
grub_uint8_t log2_bsize;
|
||||||
|
grub_uint8_t log2_sect;
|
||||||
|
@@ -54,12 +65,19 @@ struct grub_xfs_sblock
|
||||||
|
grub_uint8_t log2_agblk;
|
||||||
|
grub_uint8_t unused6[67];
|
||||||
|
grub_uint8_t log2_dirblk;
|
||||||
|
+ grub_uint8_t unused7[7];
|
||||||
|
+ grub_uint32_t features2;
|
||||||
|
+ grub_uint8_t unused8[4];
|
||||||
|
+ grub_uint32_t sb_features_compat;
|
||||||
|
+ grub_uint32_t sb_features_ro_compat;
|
||||||
|
+ grub_uint32_t sb_features_incompat;
|
||||||
|
+ grub_uint32_t sb_features_log_incompat;
|
||||||
|
} GRUB_PACKED;
|
||||||
|
|
||||||
|
struct grub_xfs_dir_header
|
||||||
|
{
|
||||||
|
grub_uint8_t count;
|
||||||
|
- grub_uint8_t smallino;
|
||||||
|
+ grub_uint8_t largeino;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
grub_uint32_t i4;
|
||||||
|
@@ -67,14 +85,16 @@ struct grub_xfs_dir_header
|
||||||
|
} GRUB_PACKED parent;
|
||||||
|
} GRUB_PACKED;
|
||||||
|
|
||||||
|
+/* Structure for directory entry inlined in the inode */
|
||||||
|
struct grub_xfs_dir_entry
|
||||||
|
{
|
||||||
|
grub_uint8_t len;
|
||||||
|
grub_uint16_t offset;
|
||||||
|
char name[1];
|
||||||
|
- /* Inode number follows, 32 bits. */
|
||||||
|
+ /* Inode number follows, 32 / 64 bits. */
|
||||||
|
} GRUB_PACKED;
|
||||||
|
|
||||||
|
+/* Structure for directory entry in a block */
|
||||||
|
struct grub_xfs_dir2_entry
|
||||||
|
{
|
||||||
|
grub_uint64_t inode;
|
||||||
|
@@ -90,7 +110,8 @@ struct grub_xfs_btree_node
|
||||||
|
grub_uint16_t numrecs;
|
||||||
|
grub_uint64_t left;
|
||||||
|
grub_uint64_t right;
|
||||||
|
- grub_uint64_t keys[1];
|
||||||
|
+ /* In V5 here follow crc, uuid, etc. */
|
||||||
|
+ /* Then follow keys and block pointers */
|
||||||
|
} GRUB_PACKED;
|
||||||
|
|
||||||
|
struct grub_xfs_btree_root
|
||||||
|
@@ -123,17 +144,6 @@ struct grub_xfs_inode
|
||||||
|
grub_uint16_t unused3;
|
||||||
|
grub_uint8_t fork_offset;
|
||||||
|
grub_uint8_t unused4[17];
|
||||||
|
- union
|
||||||
|
- {
|
||||||
|
- char raw[156];
|
||||||
|
- struct dir
|
||||||
|
- {
|
||||||
|
- struct grub_xfs_dir_header dirhead;
|
||||||
|
- struct grub_xfs_dir_entry direntry[1];
|
||||||
|
- } dir;
|
||||||
|
- grub_xfs_extent extents[XFS_INODE_EXTENTS];
|
||||||
|
- struct grub_xfs_btree_root btree;
|
||||||
|
- } GRUB_PACKED data;
|
||||||
|
} GRUB_PACKED;
|
||||||
|
|
||||||
|
struct grub_xfs_dirblock_tail
|
||||||
|
@@ -157,6 +167,8 @@ struct grub_xfs_data
|
||||||
|
int pos;
|
||||||
|
int bsize;
|
||||||
|
grub_uint32_t agsize;
|
||||||
|
+ unsigned int hasftype:1;
|
||||||
|
+ unsigned int hascrc:1;
|
||||||
|
struct grub_fshelp_node diropen;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -164,6 +176,24 @@ static grub_dl_t my_mod;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
+static int grub_xfs_sb_hascrc(struct grub_xfs_data *data)
|
||||||
|
+{
|
||||||
|
+ return (grub_be_to_cpu16(data->sblock.version) & XFS_SB_VERSION_NUMBITS) == 5;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int grub_xfs_sb_hasftype(struct grub_xfs_data *data)
|
||||||
|
+{
|
||||||
|
+ grub_uint32_t version = grub_be_to_cpu16(data->sblock.version);
|
||||||
|
+
|
||||||
|
+ if ((version & XFS_SB_VERSION_NUMBITS) == 5 &&
|
||||||
|
+ grub_be_to_cpu32(data->sblock.sb_features_incompat) & XFS_SB_FEAT_INCOMPAT_FTYPE)
|
||||||
|
+ return 1;
|
||||||
|
+ if (version & XFS_SB_VERSION_MOREBITSBIT &&
|
||||||
|
+ grub_be_to_cpu32(data->sblock.features2) & XFS_SB_VERSION2_FTYPE)
|
||||||
|
+ return 1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Filetype information as used in inodes. */
|
||||||
|
#define FILETYPE_INO_MASK 0170000
|
||||||
|
#define FILETYPE_INO_REG 0100000
|
||||||
|
@@ -219,18 +249,6 @@ GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex)
|
||||||
|
return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 21) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
-static inline int
|
||||||
|
-GRUB_XFS_ROUND_TO_DIRENT (int pos)
|
||||||
|
-{
|
||||||
|
- return ((((pos) + 8 - 1) / 8) * 8);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static inline int
|
||||||
|
-GRUB_XFS_NEXT_DIRENT (int pos, int len)
|
||||||
|
-{
|
||||||
|
- return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
|
||||||
|
static inline grub_uint64_t
|
||||||
|
grub_xfs_inode_block (struct grub_xfs_data *data,
|
||||||
|
@@ -261,6 +279,92 @@ grub_xfs_inode_size(struct grub_xfs_data *data)
|
||||||
|
return 1 << data->sblock.log2_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void *
|
||||||
|
+grub_xfs_inode_data(struct grub_xfs_inode *inode)
|
||||||
|
+{
|
||||||
|
+ if (inode->version <= 2)
|
||||||
|
+ return ((char *)inode) + 100;
|
||||||
|
+ return ((char *)inode) + 176;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct grub_xfs_dir_entry *
|
||||||
|
+grub_xfs_inline_de(struct grub_xfs_dir_header *head)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * With small inode numbers the header is 4 bytes smaller because of
|
||||||
|
+ * smaller parent pointer
|
||||||
|
+ */
|
||||||
|
+ return (void *)(((char *)head) + sizeof(struct grub_xfs_dir_header) -
|
||||||
|
+ (head->largeino ? 0 : sizeof(grub_uint32_t)));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_uint8_t *
|
||||||
|
+grub_xfs_inline_de_inopos(struct grub_xfs_data *data,
|
||||||
|
+ struct grub_xfs_dir_entry *de)
|
||||||
|
+{
|
||||||
|
+ return ((grub_uint8_t *)(de + 1)) + de->len - 1 +
|
||||||
|
+ (data->hasftype ? 1 : 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct grub_xfs_dir_entry *
|
||||||
|
+grub_xfs_inline_next_de(struct grub_xfs_data *data,
|
||||||
|
+ struct grub_xfs_dir_header *head,
|
||||||
|
+ struct grub_xfs_dir_entry *de)
|
||||||
|
+{
|
||||||
|
+ char *p = (char *)de + sizeof(struct grub_xfs_dir_entry) - 1 + de->len;
|
||||||
|
+
|
||||||
|
+ p += head->largeino ? sizeof(grub_uint64_t) : sizeof(grub_uint32_t);
|
||||||
|
+ if (data->hasftype)
|
||||||
|
+ p++;
|
||||||
|
+
|
||||||
|
+ return (struct grub_xfs_dir_entry *)p;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct grub_xfs_dirblock_tail *
|
||||||
|
+grub_xfs_dir_tail(struct grub_xfs_data *data, void *dirblock)
|
||||||
|
+{
|
||||||
|
+ int dirblksize = 1 << (data->sblock.log2_bsize + data->sblock.log2_dirblk);
|
||||||
|
+
|
||||||
|
+ return (struct grub_xfs_dirblock_tail *)
|
||||||
|
+ ((char *)dirblock + dirblksize - sizeof (struct grub_xfs_dirblock_tail));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct grub_xfs_dir2_entry *
|
||||||
|
+grub_xfs_first_de(struct grub_xfs_data *data, void *dirblock)
|
||||||
|
+{
|
||||||
|
+ if (data->hascrc)
|
||||||
|
+ return (struct grub_xfs_dir2_entry *)((char *)dirblock + 64);
|
||||||
|
+ return (struct grub_xfs_dir2_entry *)((char *)dirblock + 16);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int
|
||||||
|
+grub_xfs_round_dirent_size (int len)
|
||||||
|
+{
|
||||||
|
+ return (len + 7) & ~7;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct grub_xfs_dir2_entry *
|
||||||
|
+grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry *de)
|
||||||
|
+{
|
||||||
|
+ int size = sizeof (struct grub_xfs_dir2_entry) + de->len + 2 /* Tag */;
|
||||||
|
+
|
||||||
|
+ if (data->hasftype)
|
||||||
|
+ size++; /* File type */
|
||||||
|
+ return (struct grub_xfs_dir2_entry *)
|
||||||
|
+ (((char *)de) + grub_xfs_round_dirent_size (size));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_uint64_t *
|
||||||
|
+grub_xfs_btree_keys(struct grub_xfs_data *data,
|
||||||
|
+ struct grub_xfs_btree_node *leaf)
|
||||||
|
+{
|
||||||
|
+ char *p = (char *)(leaf + 1);
|
||||||
|
+
|
||||||
|
+ if (data->hascrc)
|
||||||
|
+ p += 48; /* crc, uuid, ... */
|
||||||
|
+ return (grub_uint64_t *)p;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static grub_err_t
|
||||||
|
grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
|
||||||
|
struct grub_xfs_inode *inode)
|
||||||
|
@@ -268,6 +372,9 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
|
||||||
|
grub_uint64_t block = grub_xfs_inode_block (data, ino);
|
||||||
|
int offset = grub_xfs_inode_offset (data, ino);
|
||||||
|
|
||||||
|
+ grub_dprintf("xfs", "Reading inode (%llu) - %llu, %d\n",
|
||||||
|
+ (unsigned long long) ino,
|
||||||
|
+ (unsigned long long) block, offset);
|
||||||
|
/* Read the inode. */
|
||||||
|
if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data),
|
||||||
|
inode))
|
||||||
|
@@ -290,6 +397,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
|
|
||||||
|
if (node->inode.format == XFS_INODE_FORMAT_BTREE)
|
||||||
|
{
|
||||||
|
+ struct grub_xfs_btree_root *root;
|
||||||
|
const grub_uint64_t *keys;
|
||||||
|
int recoffset;
|
||||||
|
|
||||||
|
@@ -297,15 +405,15 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
|
if (leaf == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
|
||||||
|
- keys = &node->inode.data.btree.keys[0];
|
||||||
|
+ root = grub_xfs_inode_data(&node->inode);
|
||||||
|
+ nrec = grub_be_to_cpu16 (root->numrecs);
|
||||||
|
+ keys = &root->keys[0];
|
||||||
|
if (node->inode.fork_offset)
|
||||||
|
recoffset = (node->inode.fork_offset - 1) / 2;
|
||||||
|
else
|
||||||
|
recoffset = (grub_xfs_inode_size(node->data)
|
||||||
|
- - ((char *) &node->inode.data.btree.keys
|
||||||
|
- - (char *) &node->inode))
|
||||||
|
- / (2 * sizeof (grub_uint64_t));
|
||||||
|
+ - ((char *) keys - (char *) &node->inode))
|
||||||
|
+ / (2 * sizeof (grub_uint64_t));
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
@@ -327,7 +435,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
|
0, node->data->bsize, leaf))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
|
||||||
|
+ if ((!node->data->hascrc &&
|
||||||
|
+ grub_strncmp ((char *) leaf->magic, "BMAP", 4)) ||
|
||||||
|
+ (node->data->hascrc &&
|
||||||
|
+ grub_strncmp ((char *) leaf->magic, "BMA3", 4)))
|
||||||
|
{
|
||||||
|
grub_free (leaf);
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node");
|
||||||
|
@@ -335,8 +446,8 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
|
}
|
||||||
|
|
||||||
|
nrec = grub_be_to_cpu16 (leaf->numrecs);
|
||||||
|
- keys = &leaf->keys[0];
|
||||||
|
- recoffset = ((node->data->bsize - ((char *) &leaf->keys
|
||||||
|
+ keys = grub_xfs_btree_keys(node->data, leaf);
|
||||||
|
+ recoffset = ((node->data->bsize - ((char *) keys
|
||||||
|
- (char *) leaf))
|
||||||
|
/ (2 * sizeof (grub_uint64_t)));
|
||||||
|
}
|
||||||
|
@@ -346,7 +457,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
|
else if (node->inode.format == XFS_INODE_FORMAT_EXT)
|
||||||
|
{
|
||||||
|
nrec = grub_be_to_cpu32 (node->inode.nextents);
|
||||||
|
- exts = &node->inode.data.extents[0];
|
||||||
|
+ exts = grub_xfs_inode_data(&node->inode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@@ -404,7 +515,7 @@ grub_xfs_read_symlink (grub_fshelp_node_t node)
|
||||||
|
switch (node->inode.format)
|
||||||
|
{
|
||||||
|
case XFS_INODE_FORMAT_INO:
|
||||||
|
- return grub_strndup (node->inode.data.raw, size);
|
||||||
|
+ return grub_strndup (grub_xfs_inode_data(&node->inode), size);
|
||||||
|
|
||||||
|
case XFS_INODE_FORMAT_EXT:
|
||||||
|
{
|
||||||
|
@@ -501,23 +612,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
{
|
||||||
|
case XFS_INODE_FORMAT_INO:
|
||||||
|
{
|
||||||
|
- struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0];
|
||||||
|
- int smallino = !diro->inode.data.dir.dirhead.smallino;
|
||||||
|
+ struct grub_xfs_dir_header *head = grub_xfs_inode_data(&diro->inode);
|
||||||
|
+ struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head);
|
||||||
|
+ int smallino = !head->largeino;
|
||||||
|
int i;
|
||||||
|
grub_uint64_t parent;
|
||||||
|
|
||||||
|
/* If small inode numbers are used to pack the direntry, the
|
||||||
|
parent inode number is small too. */
|
||||||
|
if (smallino)
|
||||||
|
- {
|
||||||
|
- parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
|
||||||
|
- /* The header is a bit smaller than usual. */
|
||||||
|
- de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
|
||||||
|
- }
|
||||||
|
+ parent = grub_be_to_cpu32 (head->parent.i4);
|
||||||
|
else
|
||||||
|
- {
|
||||||
|
- parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8);
|
||||||
|
- }
|
||||||
|
+ parent = grub_be_to_cpu64 (head->parent.i8);
|
||||||
|
|
||||||
|
/* Synthesize the direntries for `.' and `..'. */
|
||||||
|
if (iterate_dir_call_hook (diro->ino, ".", &ctx))
|
||||||
|
@@ -526,12 +632,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
if (iterate_dir_call_hook (parent, "..", &ctx))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- for (i = 0; i < diro->inode.data.dir.dirhead.count; i++)
|
||||||
|
+ for (i = 0; i < head->count; i++)
|
||||||
|
{
|
||||||
|
grub_uint64_t ino;
|
||||||
|
- grub_uint8_t *inopos = (((grub_uint8_t *) de)
|
||||||
|
- + sizeof (struct grub_xfs_dir_entry)
|
||||||
|
- + de->len - 1);
|
||||||
|
+ grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de);
|
||||||
|
grub_uint8_t c;
|
||||||
|
|
||||||
|
/* inopos might be unaligned. */
|
||||||
|
@@ -556,10 +660,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
return 1;
|
||||||
|
de->name[de->len] = c;
|
||||||
|
|
||||||
|
- de = ((struct grub_xfs_dir_entry *)
|
||||||
|
- (((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len
|
||||||
|
- + ((smallino ? sizeof (grub_uint32_t)
|
||||||
|
- : sizeof (grub_uint64_t))) - 1));
|
||||||
|
+ de = grub_xfs_inline_next_de(dir->data, head, de);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -586,15 +687,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
>> dirblk_log2);
|
||||||
|
blk++)
|
||||||
|
{
|
||||||
|
- /* The header is skipped, the first direntry is stored
|
||||||
|
- from byte 16. */
|
||||||
|
- int pos = 16;
|
||||||
|
+ struct grub_xfs_dir2_entry *direntry =
|
||||||
|
+ grub_xfs_first_de(dir->data, dirblock);
|
||||||
|
int entries;
|
||||||
|
- int tail_start = (dirblk_size
|
||||||
|
- - sizeof (struct grub_xfs_dirblock_tail));
|
||||||
|
-
|
||||||
|
- struct grub_xfs_dirblock_tail *tail;
|
||||||
|
- tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
|
||||||
|
+ struct grub_xfs_dirblock_tail *tail =
|
||||||
|
+ grub_xfs_dir_tail(dir->data, dirblock);
|
||||||
|
|
||||||
|
numread = grub_xfs_read_file (dir, 0, 0,
|
||||||
|
blk << dirblk_log2,
|
||||||
|
@@ -606,13 +703,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
- grub_be_to_cpu32 (tail->leaf_stale));
|
||||||
|
|
||||||
|
/* Iterate over all entries within this block. */
|
||||||
|
- while (pos < tail_start)
|
||||||
|
+ while ((char *)direntry < (char *)tail)
|
||||||
|
{
|
||||||
|
- struct grub_xfs_dir2_entry *direntry;
|
||||||
|
grub_uint8_t *freetag;
|
||||||
|
char *filename;
|
||||||
|
|
||||||
|
- direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos];
|
||||||
|
freetag = (grub_uint8_t *) direntry;
|
||||||
|
|
||||||
|
if (grub_get_unaligned16 (freetag) == 0XFFFF)
|
||||||
|
@@ -620,14 +715,16 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t));
|
||||||
|
|
||||||
|
/* This entry is not used, go to the next one. */
|
||||||
|
- pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip));
|
||||||
|
+ direntry = (struct grub_xfs_dir2_entry *)
|
||||||
|
+ (((char *)direntry) +
|
||||||
|
+ grub_be_to_cpu16 (grub_get_unaligned16 (skip)));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- filename = &dirblock[pos + sizeof (*direntry)];
|
||||||
|
- /* The byte after the filename is for the tag, which
|
||||||
|
- is not used by GRUB. So it can be overwritten. */
|
||||||
|
+ filename = (char *)(direntry + 1);
|
||||||
|
+ /* The byte after the filename is for the filetype, padding, or
|
||||||
|
+ tag, which is not used by GRUB. So it can be overwritten. */
|
||||||
|
filename[direntry->len] = '\0';
|
||||||
|
|
||||||
|
if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode),
|
||||||
|
@@ -644,8 +741,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Select the next directory entry. */
|
||||||
|
- pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len);
|
||||||
|
- pos = GRUB_XFS_ROUND_TO_DIRENT (pos);
|
||||||
|
+ direntry = grub_xfs_next_de(dir->data, direntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grub_free (dirblock);
|
||||||
|
@@ -670,6 +766,7 @@ grub_xfs_mount (grub_disk_t disk)
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
+ grub_dprintf("xfs", "Reading sb\n");
|
||||||
|
/* Read the superblock. */
|
||||||
|
if (grub_disk_read (disk, 0, 0,
|
||||||
|
sizeof (struct grub_xfs_sblock), &data->sblock))
|
||||||
|
@@ -697,9 +794,13 @@ grub_xfs_mount (grub_disk_t disk)
|
||||||
|
data->diropen.inode_read = 1;
|
||||||
|
data->bsize = grub_be_to_cpu32 (data->sblock.bsize);
|
||||||
|
data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
|
||||||
|
+ data->hasftype = grub_xfs_sb_hasftype(data);
|
||||||
|
+ data->hascrc = grub_xfs_sb_hascrc(data);
|
||||||
|
|
||||||
|
data->disk = disk;
|
||||||
|
data->pos = 0;
|
||||||
|
+ grub_dprintf("xfs", "Reading root ino %llu\n",
|
||||||
|
+ (unsigned long long) grub_cpu_to_be64(data->sblock.rootino));
|
||||||
|
|
||||||
|
grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode);
|
||||||
|
|
||||||
|
--
|
||||||
|
1.8.1.4
|
||||||
|
|
@ -1,3 +1,14 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Jun 25 09:20:16 UTC 2014 - jack@suse.cz
|
||||||
|
|
||||||
|
- xfs V5 superblock support (bnc#880166 bnc#883392)
|
||||||
|
|
||||||
|
- added patches:
|
||||||
|
* grub2-xfs-Add-helper-for-inode-size.patch
|
||||||
|
* grub2-xfs-Fix-termination-loop-for-directory-iteration.patch
|
||||||
|
* grub2-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch
|
||||||
|
* grub2-xfs-V5-filesystem-format-support.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Jun 20 19:50:28 UTC 2014 - jeffm@suse.com
|
Fri Jun 20 19:50:28 UTC 2014 - jeffm@suse.com
|
||||||
|
|
||||||
|
@ -174,6 +174,10 @@ Patch224: grub2-ppc64-build-ppc64-32bit.patch
|
|||||||
Patch225: grub2-ppc64-qemu.patch
|
Patch225: grub2-ppc64-qemu.patch
|
||||||
Patch226: grub2-ppc64le-timeout.patch
|
Patch226: grub2-ppc64le-timeout.patch
|
||||||
Patch227: grub2-use-stat-instead-of-udevadm-for-partition-lookup.patch
|
Patch227: grub2-use-stat-instead-of-udevadm-for-partition-lookup.patch
|
||||||
|
Patch228: grub2-xfs-Add-helper-for-inode-size.patch
|
||||||
|
Patch229: grub2-xfs-Fix-termination-loop-for-directory-iteration.patch
|
||||||
|
Patch230: grub2-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch
|
||||||
|
Patch231: grub2-xfs-V5-filesystem-format-support.patch
|
||||||
|
|
||||||
Requires: gettext-runtime
|
Requires: gettext-runtime
|
||||||
%if 0%{?suse_version} >= 1140
|
%if 0%{?suse_version} >= 1140
|
||||||
@ -364,6 +368,10 @@ mv po/grub.pot po/%{name}.pot
|
|||||||
%patch225 -p1
|
%patch225 -p1
|
||||||
%patch226 -p1
|
%patch226 -p1
|
||||||
%patch227 -p1
|
%patch227 -p1
|
||||||
|
%patch228 -p1
|
||||||
|
%patch229 -p1
|
||||||
|
%patch230 -p1
|
||||||
|
%patch231 -p1
|
||||||
|
|
||||||
# Generate po/LINGUAS for message catalogs ...
|
# Generate po/LINGUAS for message catalogs ...
|
||||||
./linguas.sh
|
./linguas.sh
|
||||||
|
Loading…
Reference in New Issue
Block a user