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)