commit e7b57dae8cfd096514b970d200e1e97648b495a6 Author: Andrew Price Date: Thu Feb 6 16:19:02 2014 +0000 libgfs2: Add support for new leaf hint fields Kernel commit 01bcb0de introduces new gfs2_leaf fields. This patch adds support for those fields to libgfs2, conditional upon them being discovered in the configure stage. Includes meta.c changes by Steve Whitehouse. Resolves: rhbz#1063842 Signed-off-by: Andrew Price diff --git a/configure.ac b/configure.ac index 628d85e..80310be 100644 --- a/configure.ac +++ b/configure.ac @@ -116,12 +116,10 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h libintl.h limits.h locale.h mnt AC_CHECK_HEADERS([linux/dlmconstants.h linux/limits.h linux/types.h linux/netlink.h linux/fs.h],, [AC_MSG_ERROR([Unable to find all required kernel headers.])]) -AC_CHECK_HEADERS([linux/gfs2_ondisk.h], - [AC_CHECK_MEMBERS([struct gfs2_sb.sb_uuid],, - [AC_MSG_ERROR([Unable to find gfs2 uuid support in your headers. -Please update your kernel headers to a more recent version])], - [#include ])], - [AC_MSG_ERROR([Unable to find required kernel headers.])]) +AC_CHECK_HEADER([linux/gfs2_ondisk.h], [], [AC_MSG_ERROR([Unable to find linux/gfs2_ondisk.h])]) +AC_CHECK_MEMBER([struct gfs2_sb.sb_uuid], [], [], [[#include ]]) +AC_CHECK_MEMBER([struct gfs2_leaf.lf_inode],[AC_DEFINE([GFS2_HAS_LEAF_HINTS],[],[Leaf block hints])], + [], [[#include ]]) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE diff --git a/gfs2/edit/extended.c b/gfs2/edit/extended.c index 27c32a9..328e35c 100644 --- a/gfs2/edit/extended.c +++ b/gfs2/edit/extended.c @@ -296,8 +296,18 @@ static void print_inode_type(__be16 de_type) } } +#ifdef GFS2_HAS_LEAF_HINTS +#define LEAF_HINT_FMTS "lf_inode: 0x%"PRIx64", lf_dist: %"PRIu32", " \ + "lf_nsec: %"PRIu32", lf_sec: %"PRIu64", " +#define LEAF_HINT_FIELDS(lp) lp->lf_inode, lp->lf_dist, lp->lf_nsec, lp->lf_sec, +#else +#define LEAF_HINT_FMTS +#define LEAF_HINT_FIELDS(lp) +#endif + static int display_leaf(struct iinfo *ind) { + struct gfs2_leaf *leaf = &ind->ii[0].lf; int start_line, total_dirents = start_row[dmode]; int d; @@ -305,11 +315,13 @@ static int display_leaf(struct iinfo *ind) if (gfs2_struct_type == GFS2_METATYPE_SB) print_gfs2("The superblock has 2 directories"); else - print_gfs2("Directory block: lf_depth:%d, lf_entries:%d," + print_gfs2("Directory block: lf_depth:%d, lf_entries:%d, " + LEAF_HINT_FMTS "fmt:%d next=0x%llx (%d dirents).", - ind->ii[0].lf_depth, ind->ii[0].lf_entries, - ind->ii[0].lf_dirent_format, - ind->ii[0].lf_next, + leaf->lf_depth, leaf->lf_entries, + LEAF_HINT_FIELDS(leaf) + leaf->lf_dirent_format, + leaf->lf_next, ind->ii[0].dirents); start_line = line; diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c index cc0ceb6..cda4dbe 100644 --- a/gfs2/edit/gfs2hex.c +++ b/gfs2/edit/gfs2hex.c @@ -341,17 +341,12 @@ uint64_t do_leaf_extended(char *dlebuf, struct iinfo *indir) { int x, i; struct gfs2_dirent de; - struct gfs2_leaf leaf; struct gfs2_buffer_head tbh; /* kludge */ x = 0; memset(indir, 0, sizeof(*indir)); tbh.b_data = dlebuf; - gfs2_leaf_in(&leaf, &tbh); - indir->ii[0].lf_depth = leaf.lf_depth; - indir->ii[0].lf_entries = leaf.lf_entries; - indir->ii[0].lf_dirent_format = leaf.lf_dirent_format; - indir->ii[0].lf_next = leaf.lf_next; + gfs2_leaf_in(&indir->ii[0].lf, &tbh); /* Directory Entries: */ for (i = sizeof(struct gfs2_leaf); i < sbd.bsize; i += de.de_rec_len) { @@ -372,7 +367,7 @@ uint64_t do_leaf_extended(char *dlebuf, struct iinfo *indir) if (de.de_rec_len <= sizeof(struct gfs2_dirent)) break; } - return leaf.lf_next; + return indir->ii[0].lf.lf_next; } static void do_eattr_extended(struct gfs2_buffer_head *ebh) diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index 0708445..1738652 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -219,7 +219,15 @@ static int gfs2_leaf_printval(struct gfs2_leaf *lf, const char *strfield) checkprint(strfield, lf, lf_entries); checkprint(strfield, lf, lf_dirent_format); checkprint(strfield, lf, lf_next); +#ifdef GFS2_HAS_LEAF_HINTS + checkprint(strfield, lf, lf_inode); + checkprint(strfield, lf, lf_dist); + checkprint(strfield, lf, lf_nsec); + checkprint(strfield, lf, lf_sec); + checkprints(strfield, lf, lf_reserved2); +#else checkprints(strfield, lf, lf_reserved); +#endif return -1; } @@ -231,6 +239,12 @@ static int gfs2_leaf_assignval(struct gfs2_leaf *lf, const char *strfield, checkassign(strfield, lf, lf_entries, value); checkassign(strfield, lf, lf_dirent_format, value); checkassign(strfield, lf, lf_next, value); +#ifdef GFS2_HAS_LEAF_HINTS + checkassign(strfield, lf, lf_inode, value); + checkassign(strfield, lf, lf_dist, value); + checkassign(strfield, lf, lf_nsec, value); + checkassign(strfield, lf, lf_sec, value); +#endif return -1; } diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h index 706909c..ebe3855 100644 --- a/gfs2/edit/hexedit.h +++ b/gfs2/edit/hexedit.h @@ -78,10 +78,7 @@ struct indirect_info { int height; uint64_t block; uint32_t dirents; - uint16_t lf_depth; - uint16_t lf_entries; - uint32_t lf_dirent_format; - uint64_t lf_next; + struct gfs2_leaf lf; struct metapath mp; struct gfs2_dirents dirent[64]; }; diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index b8cef87..59fbde8 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -657,7 +657,6 @@ static void dir_leaf_reada(struct gfs2_inode *ip, uint64_t *tbl, unsigned hsize) static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass) { int error = 0; - struct gfs2_leaf leaf; unsigned hsize = (1 << ip->i_di.di_depth); uint64_t leaf_no, leaf_next; uint64_t first_ok_leaf, orig_di_blocks; @@ -767,6 +766,7 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass) chained_leaf = 0; do { + struct gfs2_leaf leaf; if (fsck_abort) { free(tbl); posix_fadvise(sdp->device_fd, 0, 0, POSIX_FADV_NORMAL); diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c index 4a84687..1790421 100644 --- a/gfs2/libgfs2/fs_ops.c +++ b/gfs2/libgfs2/fs_ops.c @@ -1024,6 +1024,9 @@ void dir_split_leaf(struct gfs2_inode *dip, uint32_t start, uint64_t leaf_no, oleaf->lf_depth = cpu_to_be16(oleaf->lf_depth); nleaf->lf_depth = oleaf->lf_depth; +#ifdef GFS2_HAS_LEAF_HINTS + nleaf->lf_inode = cpu_to_be64(dip->i_di.di_num.no_addr); +#endif dip->i_di.di_blocks++; bmodified(dip->i_bh); @@ -1206,7 +1209,9 @@ restart: nleaf = (struct gfs2_leaf *)nbh->b_data; nleaf->lf_depth = leaf->lf_depth; nleaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE); - +#ifdef GFS2_HAS_LEAF_HINTS + nleaf->lf_inode = cpu_to_be64(dip->i_di.di_num.no_addr); +#endif err = dirent_alloc(dip, nbh, len, &dent); if (err) return err; @@ -1256,7 +1261,9 @@ static void dir_make_exhash(struct gfs2_inode *dip) leaf = (struct gfs2_leaf *)bh->b_data; leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE); leaf->lf_entries = cpu_to_be16(dip->i_di.di_entries); - +#ifdef GFS2_HAS_LEAF_HINTS + leaf->lf_inode = cpu_to_be64(dip->i_di.di_num.no_addr); +#endif buffer_copy_tail(sdp, bh, sizeof(struct gfs2_leaf), dip->i_bh, sizeof(struct gfs2_dinode)); diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c index 94be823..4305393 100644 --- a/gfs2/libgfs2/meta.c +++ b/gfs2/libgfs2/meta.c @@ -317,7 +317,15 @@ F(lf_depth) F(lf_entries) F(lf_dirent_format) F(lf_next) +#ifdef GFS2_HAS_LEAF_HINTS +FP(lf_inode, .points_to = (1 << LGFS2_MT_GFS2_DINODE)) +F(lf_dist) +F(lf_nsec, .flags = LGFS2_MFF_NSECS) +F(lf_sec, .flags = LGFS2_MFF_SECS) +RF(lf_reserved2) +#else RF(lf_reserved) +#endif }; #undef STRUCT diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c index 43618bc..dcc537e 100644 --- a/gfs2/libgfs2/ondisk.c +++ b/gfs2/libgfs2/ondisk.c @@ -433,8 +433,15 @@ void gfs2_leaf_in(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh) CPIN_16(lf, str, lf_entries); CPIN_32(lf, str, lf_dirent_format); CPIN_64(lf, str, lf_next); - +#ifdef GFS2_HAS_LEAF_HINTS + CPIN_64(lf, str, lf_inode); + CPIN_32(lf, str, lf_dist); + CPIN_32(lf, str, lf_nsec); + CPIN_64(lf, str, lf_sec); + CPIN_08(lf, str, lf_reserved2, 40); +#else CPIN_08(lf, str, lf_reserved, 32); +#endif } void gfs2_leaf_out(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh) @@ -446,8 +453,15 @@ void gfs2_leaf_out(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh) CPOUT_16(lf, str, lf_entries); CPOUT_32(lf, str, lf_dirent_format); CPOUT_64(lf, str, lf_next); - - CPOUT_08(lf, str, lf_reserved, 32); +#ifdef GFS2_HAS_LEAF_HINTS + CPOUT_64(lf, str, lf_inode); + CPOUT_32(lf, str, lf_dist); + CPOUT_32(lf, str, lf_nsec); + CPOUT_64(lf, str, lf_sec); + CPOUT_08(lf, str, lf_reserved2, 40); +#else + CPOUT_08(lf, str, lf_reserved, 64); +#endif bmodified(bh); } @@ -458,6 +472,12 @@ void gfs2_leaf_print(struct gfs2_leaf *lf) pv(lf, lf_entries, "%u", "0x%x"); pv(lf, lf_dirent_format, "%u", "0x%x"); pv(lf, lf_next, "%llu", "0x%llx"); +#ifdef GFS2_HAS_LEAF_HINTS + pv(lf, lf_inode, "%llu", "0x%llx"); + pv(lf, lf_dist, "%u", "0x%x"); + pv(lf, lf_nsec, "%u", "0x%x"); + pv(lf, lf_sec, "%llu", "0x%llx"); +#endif } void gfs2_ea_header_in(struct gfs2_ea_header *ea, char *buf)