* [PATCH] btree support in xfs driver @ 2008-01-31 19:40 Bean 2008-01-31 19:57 ` Marco Gerards 2008-01-31 19:58 ` Robert Millan 0 siblings, 2 replies; 8+ messages in thread From: Bean @ 2008-01-31 19:40 UTC (permalink / raw) To: The development of GRUB 2 Hi, I add btree support for the xfs driver, and fix a few bugs. Now i' m able to list a directory of over 5000 files, please test it. 2008-02-01 Bean <bean123ch@gmail.com> * fs/xfs.h (grub_xfs_sblock): New member log2_dirblk. (grub_xfs_btree_node): New structure. (grub_xfs_btree_root): New structure. (grub_xfs_inode): New member nblocks, extsize, nextents and btree. (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents. (GRUB_XFS_EXTENT_BLOCK): Likewise. (GRUB_XFS_EXTENT_SIZE): Likewise. (grub_xfs_read_block): Support btree format type. (grub_xfs_iterate_dir): Use regparm(1) attribute in call_hook. Use directory block as basic unit. diff --git a/fs/xfs.c b/fs/xfs.c index b3154c7..fc5dc04 100644 --- a/fs/xfs.c +++ b/fs/xfs.c @@ -47,6 +46,8 @@ struct grub_xfs_sblock grub_uint8_t unused4[2]; grub_uint8_t log2_inop; grub_uint8_t log2_agblk; + grub_uint8_t unused5[67]; + grub_uint8_t log2_dirblk; } __attribute__ ((packed)); struct grub_xfs_dir_header @@ -72,6 +73,23 @@ struct grub_xfs_dir2_entry typedef grub_uint32_t grub_xfs_extent[4]; +struct grub_xfs_btree_node +{ + grub_uint8_t magic[4]; + grub_uint16_t level; + grub_uint16_t numrecs; + grub_uint64_t left; + grub_uint64_t right; + grub_uint64_t keys[1]; +} __attribute__ ((packed)); + +struct grub_xfs_btree_root +{ + grub_uint16_t level; + grub_uint16_t numrecs; + grub_uint64_t keys[1]; +} __attribute__ ((packed)); + struct grub_xfs_inode { grub_uint8_t magic[2]; @@ -80,7 +98,10 @@ struct grub_xfs_inode grub_uint8_t format; grub_uint8_t unused2[50]; grub_uint64_t size; - grub_uint8_t unused3[36]; + grub_uint64_t nblocks; + grub_uint32_t extsize; + grub_uint32_t nextents; + grub_uint8_t unused3[20]; union { char raw[156]; @@ -90,6 +111,7 @@ struct grub_xfs_inode struct grub_xfs_dir_entry direntry[1]; } dir; grub_xfs_extent extents[XFS_INODE_EXTENTS]; + struct grub_xfs_btree_root btree; } data __attribute__ ((packed)); } __attribute__ ((packed)); @@ -138,18 +160,18 @@ static grub_dl_t my_mod; #define GRUB_XFS_INO_AG(data,ino) \ (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)) -#define GRUB_XFS_EXTENT_OFFSET(inode,ex) \ - ((grub_be_to_cpu32 ((inode)->data.extents[ex][0]) & ~(1 << 31)) << 23 \ - | grub_be_to_cpu32 ((inode)->data.extents[ex][1]) >> 9) +#define GRUB_XFS_EXTENT_OFFSET(exts,ex) \ + ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 \ + | grub_be_to_cpu32 (exts[ex][1]) >> 9) -#define GRUB_XFS_EXTENT_BLOCK(inode,ex) \ - ((grub_uint64_t) (grub_be_to_cpu32 ((inode)->data.extents[ex][1]) \ +#define GRUB_XFS_EXTENT_BLOCK(exts,ex) \ + ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) \ & (~255)) << 43 \ - | (grub_uint64_t) grub_be_to_cpu32 ((inode)->data.extents[ex][2]) << 11 \ - | grub_be_to_cpu32 ((inode)->data.extents[ex][3]) >> 21) + | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 \ + | grub_be_to_cpu32 (exts[ex][3]) >> 21) -#define GRUB_XFS_EXTENT_SIZE(inode,ex) \ - (grub_be_to_cpu32 ((inode)->data.extents[ex][3]) & ((1 << 20) - 1)) +#define GRUB_XFS_EXTENT_SIZE(exts,ex) \ + (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1)) #define GRUB_XFS_ROUND_TO_DIRENT(pos) ((((pos) + 8 - 1) / 8) * 8) #define GRUB_XFS_NEXT_DIRENT(pos,len) \ @@ -200,9 +221,60 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, static int grub_xfs_read_block (grub_fshelp_node_t node, int fileblock) { - int ex; + struct grub_xfs_btree_node *leaf = 0; + int ex, nrec; + grub_xfs_extent *exts; + + if (node->inode.format == XFS_INODE_FORMAT_BTREE) + { + grub_uint64_t *keys; + + leaf = grub_malloc (node->data->sblock.bsize); + if (leaf == 0) + return 0; + + nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); + keys = &node->inode.data.btree.keys[0]; + do + { + int i; + + for (i = 0; i < nrec; i++) + { + if ((grub_uint64_t) fileblock >= grub_be_to_cpu64 (keys[i])) + break; + } - if (node->inode.format != XFS_INODE_FORMAT_EXT) + /* Not found, it's a sparse block. */ + if (i == nrec) + { + grub_free (leaf); + return 0; + } + + if (grub_disk_read(node->data->disk, + grub_be_to_cpu64(keys[i + XFS_INODE_EXTENTS]) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), + 0, node->data->sblock.bsize, (char *) leaf)) + return 0; + + if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) + { + grub_free (leaf); + grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node.\n"); + return 0; + } + + nrec = grub_be_to_cpu16 (leaf->numrecs); + keys = &leaf->keys[0]; + } while (leaf->level); + exts = (grub_xfs_extent *) keys; + } + else if (node->inode.format == XFS_INODE_FORMAT_EXT) + { + nrec = grub_be_to_cpu32 (node->inode.nextents); + exts = &node->inode.data.extents[0]; + } + else { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "xfs does not support inode format %d yet", @@ -212,22 +284,23 @@ grub_xfs_read_block (grub_fshelp_node_t node, int fileblock) /* Iterate over each extent to figure out which extent has the block we are looking for. */ - for (ex = 0; ex < XFS_INODE_EXTENTS; ex++) + for (ex = 0; ex < nrec; ex++) { - grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (&node->inode, ex); - int offset = GRUB_XFS_EXTENT_OFFSET (&node->inode, ex); - int size = GRUB_XFS_EXTENT_SIZE (&node->inode, ex); - - unsigned int ag = start >> node->data->sblock.log2_agblk; - unsigned int block = start & ((1 << node->data->sblock.log2_agblk) - 1); + grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (exts, ex); + int offset = GRUB_XFS_EXTENT_OFFSET (exts, ex); + int size = GRUB_XFS_EXTENT_SIZE (exts, ex); if (fileblock < offset + size) - return (fileblock - offset + block) + ag * node->data->agsize; + { + if (leaf) + grub_free (leaf); + return (fileblock - offset + start); + } } - grub_error (GRUB_ERR_FILE_READ_ERROR, - "xfs block %d for inode %d is not in an extent.\n", - fileblock, grub_be_to_cpu64 (node->ino)); + if (leaf) + grub_free (leaf); + return 0; } @@ -306,9 +379,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_node_t node)) { struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; - auto int call_hook (grub_uint64_t ino, char *filename); + auto int __attribute__ ((regparm(1))) call_hook (grub_uint64_t ino, char *filename); - int call_hook (grub_uint64_t ino, char *filename) + int __attribute__ ((regparm(1))) call_hook (grub_uint64_t ino, char *filename) { struct grub_fshelp_node *fdiro; @@ -393,38 +466,42 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_ssize_t numread; char *dirblock; grub_uint64_t blk; + int dirblk_size, dirblk_log2; - dirblock = grub_malloc (dir->data->bsize); + dirblk_log2 = dir->data->sblock.log2_bsize + dir->data->sblock.log2_dirblk; + dirblk_size = 1 << dirblk_log2; + + dirblock = grub_malloc (dirblk_size); if (! dirblock) return 0; /* Iterate over every block the directory has. */ for (blk = 0; blk < (grub_be_to_cpu64 (dir->inode.size) - >> dir->data->sblock.log2_bsize); + >> dirblk_log2); blk++) { /* The header is skipped, the first direntry is stored from byte 16. */ int pos = 16; int entries; - int tail_start = (dir->data->bsize + 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]; numread = grub_xfs_read_file (dir, 0, - blk << dir->data->sblock.log2_bsize, - dir->data->bsize, dirblock); - if (numread != dir->data->bsize) + blk << dirblk_log2, + dirblk_size, dirblock); + if (numread != dirblk_size) return 0; entries = (grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale)); /* Iterate over all entries within this block. */ - while (pos < (dir->data->bsize + while (pos < (dirblk_size - (int) sizeof (struct grub_xfs_dir2_entry))) { struct grub_xfs_dir2_entry *direntry; -- Bean ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] btree support in xfs driver 2008-01-31 19:40 [PATCH] btree support in xfs driver Bean @ 2008-01-31 19:57 ` Marco Gerards 2008-02-01 3:31 ` Bean 2008-01-31 19:58 ` Robert Millan 1 sibling, 1 reply; 8+ messages in thread From: Marco Gerards @ 2008-01-31 19:57 UTC (permalink / raw) To: The development of GRUB 2 Bean <bean123ch@gmail.com> writes: Hi Bean! > I add btree support for the xfs driver, and fix a few bugs. Now i' m > able to list a directory of over 5000 files, please test it. You rock! Can you load big files now, that are stored in BTrees. Did you use code from elsewhere? > 2008-02-01 Bean <bean123ch@gmail.com> > > * fs/xfs.h (grub_xfs_sblock): New member log2_dirblk. > (grub_xfs_btree_node): New structure. > (grub_xfs_btree_root): New structure. > (grub_xfs_inode): New member nblocks, extsize, nextents and btree. members > (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents. > (GRUB_XFS_EXTENT_BLOCK): Likewise. > (GRUB_XFS_EXTENT_SIZE): Likewise. > (grub_xfs_read_block): Support btree format type. > (grub_xfs_iterate_dir): Use regparm(1) attribute in call_hook. > Use directory block as basic unit. This won't work on non-i386. So I think this has to be fixed like that other bug, for example with the autoconf check extension you proposed. -- Marco ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] btree support in xfs driver 2008-01-31 19:57 ` Marco Gerards @ 2008-02-01 3:31 ` Bean 2008-02-01 5:44 ` Marco Gerards 0 siblings, 1 reply; 8+ messages in thread From: Bean @ 2008-02-01 3:31 UTC (permalink / raw) To: The development of GRUB 2 On Feb 1, 2008 3:57 AM, Marco Gerards <mgerards@xs4all.nl> wrote: > Bean <bean123ch@gmail.com> writes: > > Hi Bean! > > > I add btree support for the xfs driver, and fix a few bugs. Now i' m > > able to list a directory of over 5000 files, please test it. > > You rock! > > Can you load big files now, that are stored in BTrees. Did you use > code from elsewhere? it should be, grub_xfs_read_block is used by both file and directory. > > > 2008-02-01 Bean <bean123ch@gmail.com> > > > > * fs/xfs.h (grub_xfs_sblock): New member log2_dirblk. > > (grub_xfs_btree_node): New structure. > > (grub_xfs_btree_root): New structure. > > (grub_xfs_inode): New member nblocks, extsize, nextents and btree. > > members > > > (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents. > > (GRUB_XFS_EXTENT_BLOCK): Likewise. > > (GRUB_XFS_EXTENT_SIZE): Likewise. > > (grub_xfs_read_block): Support btree format type. > > (grub_xfs_iterate_dir): Use regparm(1) attribute in call_hook. > > Use directory block as basic unit. > > This won't work on non-i386. So I think this has to be fixed like > that other bug, for example with the autoconf check extension you > proposed. i take a look at the aclocal.m4, the place where NESTED_FUNC_ATTR is defined: AC_MSG_RESULT([$grub_cv_i386_check_nested_functions]) if test "x$grub_cv_i386_check_nested_functions" = xyes; then AC_DEFINE([NESTED_FUNC_ATTR], [__attribute__ ((__regparm__ (2)))], [Catch gcc bug]) else dnl Unfortunately, the above test does not detect a bug in gcc-4.0. dnl So use regparm 2 until a better test is found. AC_DEFINE([NESTED_FUNC_ATTR], [__attribute__ ((__regparm__ (2)))], [Catch gcc bug]) fi is there a problem here ? i think NESTED_FUNC_ATTR is defined regardless of the test result. -- Bean ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] btree support in xfs driver 2008-02-01 3:31 ` Bean @ 2008-02-01 5:44 ` Marco Gerards 2008-02-01 13:09 ` Bean 0 siblings, 1 reply; 8+ messages in thread From: Marco Gerards @ 2008-02-01 5:44 UTC (permalink / raw) To: The development of GRUB 2 Bean <bean123ch@gmail.com> writes: > On Feb 1, 2008 3:57 AM, Marco Gerards <mgerards@xs4all.nl> wrote: >> Bean <bean123ch@gmail.com> writes: >> >> Hi Bean! >> >> > I add btree support for the xfs driver, and fix a few bugs. Now i' m >> > able to list a directory of over 5000 files, please test it. >> >> You rock! >> >> Can you load big files now, that are stored in BTrees. Did you use >> code from elsewhere? > > it should be, grub_xfs_read_block is used by both file and directory. > >> >> > 2008-02-01 Bean <bean123ch@gmail.com> >> > >> > * fs/xfs.h (grub_xfs_sblock): New member log2_dirblk. >> > (grub_xfs_btree_node): New structure. >> > (grub_xfs_btree_root): New structure. >> > (grub_xfs_inode): New member nblocks, extsize, nextents and btree. >> >> members >> >> > (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents. >> > (GRUB_XFS_EXTENT_BLOCK): Likewise. >> > (GRUB_XFS_EXTENT_SIZE): Likewise. >> > (grub_xfs_read_block): Support btree format type. >> > (grub_xfs_iterate_dir): Use regparm(1) attribute in call_hook. >> > Use directory block as basic unit. >> >> This won't work on non-i386. So I think this has to be fixed like >> that other bug, for example with the autoconf check extension you >> proposed. > > i take a look at the aclocal.m4, the place where NESTED_FUNC_ATTR is defined: > > AC_MSG_RESULT([$grub_cv_i386_check_nested_functions]) > > if test "x$grub_cv_i386_check_nested_functions" = xyes; then > AC_DEFINE([NESTED_FUNC_ATTR], > [__attribute__ ((__regparm__ (2)))], > [Catch gcc bug]) > else > dnl Unfortunately, the above test does not detect a bug in gcc-4.0. > dnl So use regparm 2 until a better test is found. > AC_DEFINE([NESTED_FUNC_ATTR], > [__attribute__ ((__regparm__ (2)))], > [Catch gcc bug]) > fi > > is there a problem here ? i think NESTED_FUNC_ATTR is defined > regardless of the test result. Ehm, this is weird. This wasn't here from the beginning, right? But at least this is on i386 only... -- Marco ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] btree support in xfs driver 2008-02-01 5:44 ` Marco Gerards @ 2008-02-01 13:09 ` Bean 2008-02-01 16:55 ` Marco Gerards 0 siblings, 1 reply; 8+ messages in thread From: Bean @ 2008-02-01 13:09 UTC (permalink / raw) To: The development of GRUB 2 Hi, change in this new patch: Fix small bug in xfs Fix a bug in fshelp Define NESTED_FUNC_ATTR as regparm(1) and us it for call_hook. With this patch, i'm able to load a highly sparse file about 200M. 2008-02-01 Bean <bean123ch@gmail.com> * fs/xfs.c (grub_xfs_sblock): New member log2_dirblk. (grub_xfs_btree_node): New structure. (grub_xfs_btree_root): New structure. (grub_xfs_inode): New members nblocks, extsize, nextents and btree. (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents. (GRUB_XFS_EXTENT_BLOCK): Likewise. (GRUB_XFS_EXTENT_SIZE): Likewise. (grub_xfs_read_block): Support btree format type. (grub_xfs_iterate_dir): Use NESTED_FUNC_ATTR in call_hook. Use directory block as basic unit. * fs/fshelp.c (grub_fshelp_read_file): Bug fix for sparse block. * aclocal.m4 (grub_i386_CHECK_REGPARM_BUG): Define NESTED_FUNC_ATTR as __attribute__ ((__regparm__ (1))). diff --git a/aclocal.m4 b/aclocal.m4 index 803d57b..a634253 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -333,13 +333,13 @@ AC_MSG_RESULT([$grub_cv_i386_check_nested_functions]) if test "x$grub_cv_i386_check_nested_functions" = xyes; then AC_DEFINE([NESTED_FUNC_ATTR], - [__attribute__ ((__regparm__ (2)))], + [__attribute__ ((__regparm__ (1)))], [Catch gcc bug]) else dnl Unfortunately, the above test does not detect a bug in gcc-4.0. dnl So use regparm 2 until a better test is found. AC_DEFINE([NESTED_FUNC_ATTR], - [__attribute__ ((__regparm__ (2)))], + [__attribute__ ((__regparm__ (1)))], [Catch gcc bug]) fi ]) diff --git a/configure b/configure index d1918ca..aa52a94 100755 --- a/configure +++ b/configure @@ -7515,13 +7515,13 @@ echo "${ECHO_T}$grub_cv_i386_check_nested_functions" >&6; } if test "x$grub_cv_i386_check_nested_functions" = xyes; then cat >>confdefs.h <<\_ACEOF -#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (2))) +#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) _ACEOF else cat >>confdefs.h <<\_ACEOF -#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (2))) +#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) _ACEOF fi diff --git a/fs/fshelp.c b/fs/fshelp.c index ba97a2f..bbb58ac 100644 --- a/fs/fshelp.c +++ b/fs/fshelp.c @@ -282,7 +282,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, return -1; } else - grub_memset (buf, blocksize - skipfirst, 0); + grub_memset (buf, 0, blockend); buf += blocksize - skipfirst; } diff --git a/fs/xfs.c b/fs/xfs.c index b3154c7..29f7891 100644 --- a/fs/xfs.c +++ b/fs/xfs.c @@ -47,6 +47,8 @@ struct grub_xfs_sblock grub_uint8_t unused4[2]; grub_uint8_t log2_inop; grub_uint8_t log2_agblk; + grub_uint8_t unused5[67]; + grub_uint8_t log2_dirblk; } __attribute__ ((packed)); struct grub_xfs_dir_header @@ -72,6 +74,23 @@ struct grub_xfs_dir2_entry typedef grub_uint32_t grub_xfs_extent[4]; +struct grub_xfs_btree_node +{ + grub_uint8_t magic[4]; + grub_uint16_t level; + grub_uint16_t numrecs; + grub_uint64_t left; + grub_uint64_t right; + grub_uint64_t keys[1]; +} __attribute__ ((packed)); + +struct grub_xfs_btree_root +{ + grub_uint16_t level; + grub_uint16_t numrecs; + grub_uint64_t keys[1]; +} __attribute__ ((packed)); + struct grub_xfs_inode { grub_uint8_t magic[2]; @@ -80,7 +99,10 @@ struct grub_xfs_inode grub_uint8_t format; grub_uint8_t unused2[50]; grub_uint64_t size; - grub_uint8_t unused3[36]; + grub_uint64_t nblocks; + grub_uint32_t extsize; + grub_uint32_t nextents; + grub_uint8_t unused3[20]; union { char raw[156]; @@ -90,6 +112,7 @@ struct grub_xfs_inode struct grub_xfs_dir_entry direntry[1]; } dir; grub_xfs_extent extents[XFS_INODE_EXTENTS]; + struct grub_xfs_btree_root btree; } data __attribute__ ((packed)); } __attribute__ ((packed)); @@ -138,18 +161,18 @@ static grub_dl_t my_mod; #define GRUB_XFS_INO_AG(data,ino) \ (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)) -#define GRUB_XFS_EXTENT_OFFSET(inode,ex) \ - ((grub_be_to_cpu32 ((inode)->data.extents[ex][0]) & ~(1 << 31)) << 23 \ - | grub_be_to_cpu32 ((inode)->data.extents[ex][1]) >> 9) +#define GRUB_XFS_EXTENT_OFFSET(exts,ex) \ + ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 \ + | grub_be_to_cpu32 (exts[ex][1]) >> 9) -#define GRUB_XFS_EXTENT_BLOCK(inode,ex) \ - ((grub_uint64_t) (grub_be_to_cpu32 ((inode)->data.extents[ex][1]) \ - & (~255)) << 43 \ - | (grub_uint64_t) grub_be_to_cpu32 ((inode)->data.extents[ex][2]) << 11 \ - | grub_be_to_cpu32 ((inode)->data.extents[ex][3]) >> 21) +#define GRUB_XFS_EXTENT_BLOCK(exts,ex) \ + ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) \ + & (0x1ff)) << 43 \ + | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 \ + | grub_be_to_cpu32 (exts[ex][3]) >> 21) -#define GRUB_XFS_EXTENT_SIZE(inode,ex) \ - (grub_be_to_cpu32 ((inode)->data.extents[ex][3]) & ((1 << 20) - 1)) +#define GRUB_XFS_EXTENT_SIZE(exts,ex) \ + (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1)) #define GRUB_XFS_ROUND_TO_DIRENT(pos) ((((pos) + 8 - 1) / 8) * 8) #define GRUB_XFS_NEXT_DIRENT(pos,len) \ @@ -200,9 +223,63 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, static int grub_xfs_read_block (grub_fshelp_node_t node, int fileblock) { - int ex; + struct grub_xfs_btree_node *leaf = 0; + int ex, nrec; + grub_xfs_extent *exts; + grub_uint64_t ret = 0; + + if (node->inode.format == XFS_INODE_FORMAT_BTREE) + { + grub_uint64_t *keys; + + leaf = grub_malloc (node->data->sblock.bsize); + if (leaf == 0) + return 0; + + nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); + keys = &node->inode.data.btree.keys[0]; + do + { + int i; + + for (i = 0; i < nrec; i++) + { + if ((grub_uint64_t) fileblock < grub_be_to_cpu64 (keys[i])) + break; + } + + /* Sparse block. */ + if (i == 0) + { + grub_free (leaf); + return 0; + } + + if (grub_disk_read(node->data->disk, + grub_be_to_cpu64(keys[i - 1 + XFS_INODE_EXTENTS]) + << (node->data->sblock.log2_bsize + - GRUB_DISK_SECTOR_BITS), + 0, node->data->sblock.bsize, (char *) leaf)) + return 0; - if (node->inode.format != XFS_INODE_FORMAT_EXT) + if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) + { + grub_free (leaf); + grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node.\n"); + return 0; + } + + nrec = grub_be_to_cpu16 (leaf->numrecs); + keys = &leaf->keys[0]; + } while (leaf->level); + exts = (grub_xfs_extent *) keys; + } + else if (node->inode.format == XFS_INODE_FORMAT_EXT) + { + nrec = grub_be_to_cpu32 (node->inode.nextents); + exts = &node->inode.data.extents[0]; + } + else { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "xfs does not support inode format %d yet", @@ -212,23 +289,26 @@ grub_xfs_read_block (grub_fshelp_node_t node, int fileblock) /* Iterate over each extent to figure out which extent has the block we are looking for. */ - for (ex = 0; ex < XFS_INODE_EXTENTS; ex++) + for (ex = 0; ex < nrec; ex++) { - grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (&node->inode, ex); - int offset = GRUB_XFS_EXTENT_OFFSET (&node->inode, ex); - int size = GRUB_XFS_EXTENT_SIZE (&node->inode, ex); - - unsigned int ag = start >> node->data->sblock.log2_agblk; - unsigned int block = start & ((1 << node->data->sblock.log2_agblk) - 1); + grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (exts, ex); + int offset = GRUB_XFS_EXTENT_OFFSET (exts, ex); + int size = GRUB_XFS_EXTENT_SIZE (exts, ex); - if (fileblock < offset + size) - return (fileblock - offset + block) + ag * node->data->agsize; + /* Sparse block. */ + if (fileblock < offset) + break; + else if (fileblock < offset + size) + { + ret = (fileblock - offset + start); + break; + } } - grub_error (GRUB_ERR_FILE_READ_ERROR, - "xfs block %d for inode %d is not in an extent.\n", - fileblock, grub_be_to_cpu64 (node->ino)); - return 0; + if (leaf) + grub_free (leaf); + + return ret; } @@ -306,9 +386,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_node_t node)) { struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; - auto int call_hook (grub_uint64_t ino, char *filename); + auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename); - int call_hook (grub_uint64_t ino, char *filename) + int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename) { struct grub_fshelp_node *fdiro; @@ -393,38 +473,43 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_ssize_t numread; char *dirblock; grub_uint64_t blk; + int dirblk_size, dirblk_log2; - dirblock = grub_malloc (dir->data->bsize); + dirblk_log2 = (dir->data->sblock.log2_bsize + + dir->data->sblock.log2_dirblk); + dirblk_size = 1 << dirblk_log2; + + dirblock = grub_malloc (dirblk_size); if (! dirblock) return 0; /* Iterate over every block the directory has. */ for (blk = 0; blk < (grub_be_to_cpu64 (dir->inode.size) - >> dir->data->sblock.log2_bsize); + >> dirblk_log2); blk++) { /* The header is skipped, the first direntry is stored from byte 16. */ int pos = 16; int entries; - int tail_start = (dir->data->bsize + 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]; numread = grub_xfs_read_file (dir, 0, - blk << dir->data->sblock.log2_bsize, - dir->data->bsize, dirblock); - if (numread != dir->data->bsize) + blk << dirblk_log2, + dirblk_size, dirblock); + if (numread != dirblk_size) return 0; entries = (grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale)); /* Iterate over all entries within this block. */ - while (pos < (dir->data->bsize + while (pos < (dirblk_size - (int) sizeof (struct grub_xfs_dir2_entry))) { struct grub_xfs_dir2_entry *direntry; -- Bean ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] btree support in xfs driver 2008-02-01 13:09 ` Bean @ 2008-02-01 16:55 ` Marco Gerards 2008-02-02 14:16 ` Bean 0 siblings, 1 reply; 8+ messages in thread From: Marco Gerards @ 2008-02-01 16:55 UTC (permalink / raw) To: The development of GRUB 2 Bean <bean123ch@gmail.com> writes: Hi! > change in this new patch: > > Fix small bug in xfs > Fix a bug in fshelp > Define NESTED_FUNC_ATTR as regparm(1) and us it for call_hook. > > With this patch, i'm able to load a highly sparse file about 200M. > > > 2008-02-01 Bean <bean123ch@gmail.com> > > * fs/xfs.c (grub_xfs_sblock): New member log2_dirblk. > (grub_xfs_btree_node): New structure. > (grub_xfs_btree_root): New structure. > (grub_xfs_inode): New members nblocks, extsize, nextents and btree. > (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents. > (GRUB_XFS_EXTENT_BLOCK): Likewise. > (GRUB_XFS_EXTENT_SIZE): Likewise. > (grub_xfs_read_block): Support btree format type. > (grub_xfs_iterate_dir): Use NESTED_FUNC_ATTR in call_hook. > Use directory block as basic unit. > > * fs/fshelp.c (grub_fshelp_read_file): Bug fix for sparse block. > > * aclocal.m4 (grub_i386_CHECK_REGPARM_BUG): Define NESTED_FUNC_ATTR as > __attribute__ ((__regparm__ (1))). Looks fine to me! :-) -- Marco ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] btree support in xfs driver 2008-02-01 16:55 ` Marco Gerards @ 2008-02-02 14:16 ` Bean 0 siblings, 0 replies; 8+ messages in thread From: Bean @ 2008-02-02 14:16 UTC (permalink / raw) To: The development of GRUB 2 Committed. -- Bean ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] btree support in xfs driver 2008-01-31 19:40 [PATCH] btree support in xfs driver Bean 2008-01-31 19:57 ` Marco Gerards @ 2008-01-31 19:58 ` Robert Millan 1 sibling, 0 replies; 8+ messages in thread From: Robert Millan @ 2008-01-31 19:58 UTC (permalink / raw) To: The development of GRUB 2 On Fri, Feb 01, 2008 at 03:40:20AM +0800, Bean wrote: > Hi, > > I add btree support for the xfs driver, and fix a few bugs. Now i' m > able to list a directory of over 5000 files, please test it. You're truly impressive... One comment: > { > struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; > - auto int call_hook (grub_uint64_t ino, char *filename); > + auto int __attribute__ ((regparm(1))) call_hook (grub_uint64_t ino, > char *filename); > > - int call_hook (grub_uint64_t ino, char *filename) > + int __attribute__ ((regparm(1))) call_hook (grub_uint64_t ino, char > *filename) would this break on non-i386 ? -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-02-02 14:17 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-01-31 19:40 [PATCH] btree support in xfs driver Bean 2008-01-31 19:57 ` Marco Gerards 2008-02-01 3:31 ` Bean 2008-02-01 5:44 ` Marco Gerards 2008-02-01 13:09 ` Bean 2008-02-01 16:55 ` Marco Gerards 2008-02-02 14:16 ` Bean 2008-01-31 19:58 ` Robert Millan
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.