Blob Blame History Raw
commit e7b57dae8cfd096514b970d200e1e97648b495a6
Author: Andrew Price <anprice@redhat.com>
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 <anprice@redhat.com>

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 <linux/gfs2_ondisk.h>])],
-		 [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 <linux/gfs2_ondisk.h>]])
+AC_CHECK_MEMBER([struct gfs2_leaf.lf_inode],[AC_DEFINE([GFS2_HAS_LEAF_HINTS],[],[Leaf block hints])],
+                [], [[#include <linux/gfs2_ondisk.h>]])
 
 # 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)