From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1Ys2fY-00083I-61 for mharc-grub-devel@gnu.org; Tue, 12 May 2015 01:23:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37279) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ys2fU-00082g-83 for grub-devel@gnu.org; Tue, 12 May 2015 01:23:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ys2fQ-00012M-RO for grub-devel@gnu.org; Tue, 12 May 2015 01:23:48 -0400 Received: from mail-lb0-x234.google.com ([2a00:1450:4010:c04::234]:34725) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ys2fQ-00012D-CU for grub-devel@gnu.org; Tue, 12 May 2015 01:23:44 -0400 Received: by lbcga7 with SMTP id ga7so109534711lbc.1 for ; Mon, 11 May 2015 22:23:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=XD0goPtF+BLc3HD4RLt/o+iE03/q8w5ne+xYLJxxQxM=; b=ZEvDw4q0G9eVat/CWt0cSoWHbXUgcBKRs4Vt1no2ig+kYBRKe2Z8Xmp9ROmm5fLwTh XI9MJ0sk1isUIFpzXiiPGxwyqZUcMFR4SvVI0+t3MRtAAEaFabVrI+240FxVm6cBCrJ9 gy/8RgKfbMsShNS4CGKKK/s4lLlZxoU1WJPznLZVPM4NGahIFppESdZAcVnhR4XjVmVl HIQK6F9o37Hx4uwxflWWxef+N/6iF0KARswiHe4eEjhBxKkNlOTLEhgZ2M1/MfmwsCea s3jzgt1ssEpoJQ6C0mpfYfw5Ta5myqSFWPRbOrP8tQIjuQyblHZ09WImPXRsOaR1KvsH Uc8g== X-Received: by 10.112.210.103 with SMTP id mt7mr9170455lbc.27.1431408223636; Mon, 11 May 2015 22:23:43 -0700 (PDT) Received: from opensuse.site (ppp91-76-14-38.pppoe.mtu-net.ru. [91.76.14.38]) by mx.google.com with ESMTPSA id q1sm3524560laq.10.2015.05.11.22.23.42 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 May 2015 22:23:42 -0700 (PDT) Date: Tue, 12 May 2015 08:23:40 +0300 From: Andrei Borzenkov To: Jan Kara Subject: Re: [PATCH 4/4] xfs: V5 filesystem format support Message-ID: <20150512082340.78aa6ee5@opensuse.site> In-Reply-To: <1405351291-24767-5-git-send-email-jack@suse.cz> References: <1405351291-24767-1-git-send-email-jack@suse.cz> <1405351291-24767-5-git-send-email-jack@suse.cz> X-Mailer: Claws Mail 3.11.0 (GTK+ 2.24.27; x86_64-suse-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:4010:c04::234 Cc: grub-devel@gnu.org X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 May 2015 05:23:50 -0000 =D0=92 Mon, 14 Jul 2014 17:21:31 +0200 Jan Kara =D0=BF=D0=B8=D1=88=D0=B5=D1=82: > Add support for new XFS on disk format. We have to handle optional > filetype fields in directory entries, additional CRC, LSN, UUID entries > in some structures, etc. >=20 > Signed-off-by: Jan Kara > --- > grub-core/fs/xfs.c | 249 +++++++++++++++++++++++++++++++++++++----------= ------ > 1 file changed, 177 insertions(+), 72 deletions(-) >=20 > diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c > index 7e247a32df5c..7f2582d33e02 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 > =20 > +/* 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 d= irent */ > =20 > 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; > =20 > 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; > =20 > +/* 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; > =20 > +/* 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; > =20 > 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; Can we make it grub_uint8_t xfs_v3_extra[76] or similar to avoid magic numbers later when computing data offset? > } GRUB_PACKED; > =20 > 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; > }; > =20 > @@ -164,6 +176,24 @@ static grub_dl_t my_mod; > =20 > =0C > =20 > +static int grub_xfs_sb_hascrc(struct grub_xfs_data *data) > +{ > + return (grub_be_to_cpu16(data->sblock.version) & XFS_SB_VERSION_NUMBIT= S) =3D=3D 5; Could you define name for magic constant? Also to avoid run-time computation: data->sblock.version & grub_cpu_to_b16_compile_time(XFS_SB_VERSION_NUMBITS) =3D=3D grub_cpu_to_b16_compile_time(5) > +} > + > +static int grub_xfs_sb_hasftype(struct grub_xfs_data *data) > +{ > + grub_uint32_t version =3D grub_be_to_cpu16(data->sblock.version); > + > + if ((version & XFS_SB_VERSION_NUMBITS) =3D=3D 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; > +} > + Same. All are constants, so *_compile_time. > /* 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)); > } > =20 > -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); > -} > - > =0C > static inline grub_uint64_t > grub_xfs_inode_block (struct grub_xfs_data *data, > @@ -261,6 +279,96 @@ grub_xfs_inode_size(struct grub_xfs_data *data) > return 1 << data->sblock.log2_inode; > } > =20 > +static void * > +grub_xfs_inode_data(struct grub_xfs_inode *inode) > +{ > + if (inode->version <=3D 2) > + return ((char *)inode) + 100; That is sizeof(struct grub_xfs_inode) in your patch, right? > + return ((char *)inode) + 176; Please avoid magic numbers. At least give it meaningful name, or as suggested above just define structure to contain it. > +} > + > +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 + The outer parens are somehow confusing. > + (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 =3D (char *)de + sizeof(struct grub_xfs_dir_entry) - 1 + de->l= en; > + > + p +=3D head->largeino ? sizeof(grub_uint64_t) : sizeof(grub_uint32_t); > + if (data->hasftype) > + p++; > + =20 > + 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 =3D 1 << (data->sblock.log2_bsize + data->sblock.log2_d= irblk); > + > + return (struct grub_xfs_dirblock_tail *) > + ((char *)dirblock + dirblksize - sizeof (struct grub_xfs_dirblock_ta= il)); > +} > + > +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; > +} ALIGN_UP? > + > +static struct grub_xfs_dir2_entry * > +grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry = *de) > +{ > + int size =3D 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)); What's wrong with ALIGN_UP (size, 8)? > +} > + > +static grub_uint64_t * > +grub_xfs_btree_keys(struct grub_xfs_data *data, > + struct grub_xfs_btree_node *leaf) > +{ > + char *p =3D (char *)(leaf + 1); > + > + if (data->hascrc) > + p +=3D 48; /* crc, uuid, ... */ > + /* > + * We have to first type to void * to avoid complaints about possible > + * alignment issues on some architectures > + */ > + return (grub_uint64_t *)(void *)p; Leaving it as grub_uint64_t keys and using &keys[6] would avoid this warning as well, not? Also having keys[0] will likely simplify other places as well (we do require GCC in any case). > +} > + > static grub_err_t > grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, > struct grub_xfs_inode *inode) > @@ -268,6 +376,9 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub= _uint64_t ino, > grub_uint64_t block =3D grub_xfs_inode_block (data, ino); > int offset =3D grub_xfs_inode_offset (data, ino); > =20 > + 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(dat= a), > inode)) > @@ -290,6 +401,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_di= sk_addr_t fileblock) > =20 > if (node->inode.format =3D=3D XFS_INODE_FORMAT_BTREE) > { > + struct grub_xfs_btree_root *root; > const grub_uint64_t *keys; > int recoffset; > =20 > @@ -297,15 +409,15 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_= disk_addr_t fileblock) > if (leaf =3D=3D 0) > return 0; > =20 > - nrec =3D grub_be_to_cpu16 (node->inode.data.btree.numrecs); > - keys =3D &node->inode.data.btree.keys[0]; > + root =3D grub_xfs_inode_data(&node->inode); > + nrec =3D grub_be_to_cpu16 (root->numrecs); > + keys =3D &root->keys[0]; > if (node->inode.fork_offset) > recoffset =3D (node->inode.fork_offset - 1) / 2; > else > recoffset =3D (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 +439,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_d= isk_addr_t fileblock) > 0, node->data->bsize, leaf)) > return 0; > =20 > - 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 +450,8 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_di= sk_addr_t fileblock) > } > =20 > nrec =3D grub_be_to_cpu16 (leaf->numrecs); > - keys =3D &leaf->keys[0]; > - recoffset =3D ((node->data->bsize - ((char *) &leaf->keys > + keys =3D grub_xfs_btree_keys(node->data, leaf); > + recoffset =3D ((node->data->bsize - ((char *) keys > - (char *) leaf)) > / (2 * sizeof (grub_uint64_t))); > } > @@ -346,7 +461,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_di= sk_addr_t fileblock) > else if (node->inode.format =3D=3D XFS_INODE_FORMAT_EXT) > { > nrec =3D grub_be_to_cpu32 (node->inode.nextents); > - exts =3D &node->inode.data.extents[0]; > + exts =3D grub_xfs_inode_data(&node->inode); > } > else > { > @@ -404,7 +519,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); > =20 > case XFS_INODE_FORMAT_EXT: > { > @@ -501,23 +616,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, > { > case XFS_INODE_FORMAT_INO: > { > - struct grub_xfs_dir_entry *de =3D &diro->inode.data.dir.direntry[0]; > - int smallino =3D !diro->inode.data.dir.dirhead.smallino; > + struct grub_xfs_dir_header *head =3D grub_xfs_inode_data(&diro->inode); > + struct grub_xfs_dir_entry *de =3D grub_xfs_inline_de(head); > + int smallino =3D !head->largeino; > int i; > grub_uint64_t parent; > =20 > /* If small inode numbers are used to pack the direntry, the > parent inode number is small too. */ > if (smallino) > - { > - parent =3D grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4= ); > - /* The header is a bit smaller than usual. */ > - de =3D (struct grub_xfs_dir_entry *) ((char *) de - 4); > - } > + parent =3D grub_be_to_cpu32 (head->parent.i4); > else > - { > - parent =3D grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8); > - } > + parent =3D grub_be_to_cpu64 (head->parent.i8); > =20 > /* Synthesize the direntries for `.' and `..'. */ > if (iterate_dir_call_hook (diro->ino, ".", &ctx)) > @@ -526,12 +636,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, > if (iterate_dir_call_hook (parent, "..", &ctx)) > return 1; > =20 > - for (i =3D 0; i < diro->inode.data.dir.dirhead.count; i++) > + for (i =3D 0; i < head->count; i++) > { > grub_uint64_t ino; > - grub_uint8_t *inopos =3D (((grub_uint8_t *) de) > - + sizeof (struct grub_xfs_dir_entry) > - + de->len - 1); > + grub_uint8_t *inopos =3D grub_xfs_inline_de_inopos(dir->data, de); > grub_uint8_t c; > =20 > /* inopos might be unaligned. */ > @@ -556,10 +664,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, > return 1; > de->name[de->len] =3D c; > =20 > - de =3D ((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 =3D grub_xfs_inline_next_de(dir->data, head, de); > } > break; > } > @@ -586,15 +691,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 =3D 16; > + struct grub_xfs_dir2_entry *direntry =3D > + grub_xfs_first_de(dir->data, dirblock); > int entries; > - int tail_start =3D (dirblk_size > - - sizeof (struct grub_xfs_dirblock_tail)); > - > - struct grub_xfs_dirblock_tail *tail; > - tail =3D (struct grub_xfs_dirblock_tail *) &dirblock[tail_start]; > + struct grub_xfs_dirblock_tail *tail =3D > + grub_xfs_dir_tail(dir->data, dirblock); > =20 > numread =3D grub_xfs_read_file (dir, 0, 0, > blk << dirblk_log2, > @@ -606,13 +707,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, > - grub_be_to_cpu32 (tail->leaf_stale)); > =20 > /* 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; > =20 > - direntry =3D (struct grub_xfs_dir2_entry *) &dirblock[pos]; > freetag =3D (grub_uint8_t *) direntry; > =20 > if (grub_get_unaligned16 (freetag) =3D=3D 0XFFFF) > @@ -620,14 +719,16 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, > grub_uint8_t *skip =3D (freetag + sizeof (grub_uint16_t)); > =20 > /* This entry is not used, go to the next one. */ > - pos +=3D grub_be_to_cpu16 (grub_get_unaligned16 (skip)); > + direntry =3D (struct grub_xfs_dir2_entry *) > + (((char *)direntry) + > + grub_be_to_cpu16 (grub_get_unaligned16 (skip))); > =20 > continue; > } > =20 > - filename =3D &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 =3D (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] =3D '\0'; > =20 > if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode),=20 > @@ -644,8 +745,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, > break; > =20 > /* Select the next directory entry. */ > - pos =3D GRUB_XFS_NEXT_DIRENT (pos, direntry->len); > - pos =3D GRUB_XFS_ROUND_TO_DIRENT (pos); > + direntry =3D grub_xfs_next_de(dir->data, direntry); > } > } > grub_free (dirblock); > @@ -670,6 +770,7 @@ grub_xfs_mount (grub_disk_t disk) > if (!data) > return 0; > =20 > + 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 +798,13 @@ grub_xfs_mount (grub_disk_t disk) > data->diropen.inode_read =3D 1; > data->bsize =3D grub_be_to_cpu32 (data->sblock.bsize); > data->agsize =3D grub_be_to_cpu32 (data->sblock.agsize); > + data->hasftype =3D grub_xfs_sb_hasftype(data); > + data->hascrc =3D grub_xfs_sb_hascrc(data); > =20 > data->disk =3D disk; > data->pos =3D 0; > + grub_dprintf("xfs", "Reading root ino %llu\n", > + (unsigned long long) grub_cpu_to_be64(data->sblock.rootino)); > =20 > grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode); > =20