From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: sandeen@redhat.com
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH v2 4/7] xfs_db: dump dir/attr btrees
Date: Tue, 1 Aug 2017 08:40:53 -0700 [thread overview]
Message-ID: <20170801154053.GH4477@magnolia> (raw)
In-Reply-To: <150153523353.26081.1989249017494623271.stgit@magnolia>
Dump the directory or extended attribute btree contents.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
db/btdump.c | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++
man/man8/xfs_db.8 | 1
2 files changed, 255 insertions(+), 1 deletion(-)
diff --git a/db/btdump.c b/db/btdump.c
index 3b76e17..f525a4a 100644
--- a/db/btdump.c
+++ b/db/btdump.c
@@ -32,7 +32,9 @@ btdump_help(void)
"\n"
" If the cursor points to a btree block, 'btdump' dumps the btree\n"
" downward from that block. If the cursor points to an inode,\n"
-" the data fork btree root is selected by default.\n"
+" the data fork btree root is selected by default. If the cursor\n"
+" points to a directory or extended attribute btree node, the tree\n"
+" will be printed downward from that block.\n"
"\n"
" Options:\n"
" -a -- Display an inode's extended attribute fork btree.\n"
@@ -227,6 +229,252 @@ dump_inode(
return ret;
}
+static bool
+dir_has_rightsib(
+ void *block,
+ int level)
+{
+ struct xfs_dir3_icleaf_hdr lhdr;
+ struct xfs_da3_icnode_hdr nhdr;
+
+ if (level > 0) {
+ M_DIROPS(mp)->node_hdr_from_disk(&nhdr, block);
+ return nhdr.forw != 0;
+ }
+ M_DIROPS(mp)->leaf_hdr_from_disk(&lhdr, block);
+ return lhdr.forw != 0;
+}
+
+static int
+dir_level(
+ void *block)
+{
+ struct xfs_dir3_icleaf_hdr lhdr;
+ struct xfs_da3_icnode_hdr nhdr;
+
+ switch (((struct xfs_da_intnode *)block)->hdr.info.magic) {
+ case cpu_to_be16(XFS_DIR2_LEAF1_MAGIC):
+ case cpu_to_be16(XFS_DIR2_LEAFN_MAGIC):
+ M_DIROPS(mp)->leaf_hdr_from_disk(&lhdr, block);
+ return 0;
+ case cpu_to_be16(XFS_DA_NODE_MAGIC):
+ M_DIROPS(mp)->node_hdr_from_disk(&nhdr, block);
+ return nhdr.level;
+ default:
+ return -1;
+ }
+}
+
+static int
+dir3_level(
+ void *block)
+{
+ struct xfs_dir3_icleaf_hdr lhdr;
+ struct xfs_da3_icnode_hdr nhdr;
+
+ switch (((struct xfs_da_intnode *)block)->hdr.info.magic) {
+ case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC):
+ case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC):
+ M_DIROPS(mp)->leaf_hdr_from_disk(&lhdr, block);
+ return 0;
+ case cpu_to_be16(XFS_DA3_NODE_MAGIC):
+ M_DIROPS(mp)->node_hdr_from_disk(&nhdr, block);
+ return nhdr.level;
+ default:
+ return -1;
+ }
+}
+
+static bool
+attr_has_rightsib(
+ void *block,
+ int level)
+{
+ struct xfs_attr_leafblock lhdr;
+ struct xfs_da3_icnode_hdr nhdr;
+
+ if (level > 0) {
+ M_DIROPS(mp)->node_hdr_from_disk(&nhdr, block);
+ return nhdr.forw != 0;
+ }
+ xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo, &lhdr, block);
+ return lhdr.hdr.info.forw != 0;
+}
+
+static int
+attr_level(
+ void *block)
+{
+ struct xfs_attr_leafblock lhdr;
+ struct xfs_da3_icnode_hdr nhdr;
+
+ switch (((struct xfs_da_intnode *)block)->hdr.info.magic) {
+ case cpu_to_be16(XFS_ATTR_LEAF_MAGIC):
+ xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo, &lhdr, block);
+ return 0;
+ case cpu_to_be16(XFS_DA_NODE_MAGIC):
+ M_DIROPS(mp)->node_hdr_from_disk(&nhdr, block);
+ return nhdr.level;
+ default:
+ return -1;
+ }
+}
+
+static int
+attr3_level(
+ void *block)
+{
+ struct xfs_attr_leafblock lhdr;
+ struct xfs_da3_icnode_hdr nhdr;
+
+ switch (((struct xfs_da_intnode *)block)->hdr.info.magic) {
+ case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC):
+ xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo, &lhdr, block);
+ return 0;
+ case cpu_to_be16(XFS_DA3_NODE_MAGIC):
+ M_DIROPS(mp)->node_hdr_from_disk(&nhdr, block);
+ return nhdr.level;
+ default:
+ return -1;
+ }
+}
+
+struct dabprinter_ops {
+ const char *print_node_entries;
+ const char *print_leaf_entries;
+ const char *go_node_forward;
+ const char *go_leaf_forward;
+ const char *go_down;
+ bool (*has_rightsib)(void *, int);
+ int (*level)(void *);
+};
+
+static struct dabprinter_ops attr_print = {
+ .print_node_entries = "btree",
+ .print_leaf_entries = "entries nvlist",
+ .go_node_forward = "hdr.info.forw",
+ .go_leaf_forward = "hdr.info.forw",
+ .go_down = "btree[0].before",
+ .has_rightsib = attr_has_rightsib,
+ .level = attr_level,
+};
+
+static struct dabprinter_ops attr3_print = {
+ .print_node_entries = "btree",
+ .print_leaf_entries = "entries nvlist",
+ .go_node_forward = "hdr.info.hdr.forw",
+ .go_leaf_forward = "hdr.info.hdr.forw",
+ .go_down = "btree[0].before",
+ .has_rightsib = attr_has_rightsib,
+ .level = attr3_level,
+};
+
+static struct dabprinter_ops dir_print = {
+ .print_node_entries = "nbtree",
+ .print_leaf_entries = "lents",
+ .go_node_forward = "nhdr.info.hdr.forw",
+ .go_leaf_forward = "lhdr.info.hdr.forw",
+ .go_down = "nbtree[0].before",
+ .has_rightsib = dir_has_rightsib,
+ .level = dir_level,
+};
+
+static struct dabprinter_ops dir3_print = {
+ .print_node_entries = "nbtree",
+ .print_leaf_entries = "lents",
+ .go_node_forward = "nhdr.info.forw",
+ .go_leaf_forward = "lhdr.info.forw",
+ .go_down = "nbtree[0].before",
+ .has_rightsib = dir_has_rightsib,
+ .level = dir3_level,
+};
+
+static int
+dump_dablevel(
+ int level,
+ struct dabprinter_ops *dbp)
+{
+ xfs_daddr_t orig_daddr = iocur_top->bb;
+ xfs_daddr_t last_daddr;
+ unsigned int nr;
+ int ret;
+
+ ret = eval("push");
+ if (ret)
+ return ret;
+
+ nr = 1;
+ do {
+ last_daddr = iocur_top->bb;
+ dbprintf(_("%s level %u block %u daddr %llu\n"),
+ iocur_top->typ->name, level, nr, last_daddr);
+ ret = eval("print %s", level > 0 ? dbp->print_node_entries :
+ dbp->print_leaf_entries);
+ if (ret)
+ goto err;
+ if (dbp->has_rightsib(iocur_top->data, level)) {
+ ret = eval("addr %s", level > 0 ? dbp->go_node_forward :
+ dbp->go_leaf_forward);
+ if (ret)
+ goto err;
+ }
+ nr++;
+ } while (iocur_top->bb != orig_daddr && iocur_top->bb != last_daddr);
+
+ ret = eval("pop");
+ return ret;
+err:
+ eval("pop");
+ return ret;
+}
+
+static int
+dump_dabtree(
+ bool dump_node_blocks,
+ struct dabprinter_ops *dbp)
+{
+ xfs_daddr_t orig_daddr = iocur_top->bb;
+ xfs_daddr_t last_daddr;
+ int level;
+ int ret;
+
+ ret = eval("push");
+ if (ret)
+ return ret;
+
+ cur_agno = XFS_FSB_TO_AGNO(mp, XFS_DADDR_TO_FSB(mp, iocur_top->bb));
+ level = dbp->level(iocur_top->data);
+ if (level < 0) {
+ printf(_("Current location is not part of a dir/attr btree.\n"));
+ goto err;
+ }
+
+ do {
+ last_daddr = iocur_top->bb;
+ if (level > 0) {
+ if (dump_node_blocks) {
+ ret = dump_dablevel(level, dbp);
+ if (ret)
+ goto err;
+ }
+ ret = eval("addr %s", dbp->go_down);
+ } else {
+ ret = dump_dablevel(level, dbp);
+ }
+ if (ret)
+ goto err;
+ level--;
+ } while (level >= 0 &&
+ iocur_top->bb != orig_daddr &&
+ iocur_top->bb != last_daddr);
+
+ ret = eval("pop");
+ return ret;
+err:
+ eval("pop");
+ return ret;
+}
+
static int
btdump_f(
int argc,
@@ -234,6 +482,7 @@ btdump_f(
{
bool aflag = false;
bool iflag = false;
+ bool crc = xfs_sb_version_hascrc(&mp->m_sb);
int c;
if (cur_typ == NULL) {
@@ -276,6 +525,10 @@ btdump_f(
return dump_btree_long(iflag);
case TYP_INODE:
return dump_inode(iflag, aflag);
+ case TYP_ATTR:
+ return dump_dabtree(iflag, crc ? &attr3_print : &attr_print);
+ case TYP_DIR2:
+ return dump_dabtree(iflag, crc ? &dir3_print : &dir_print);
default:
dbprintf(_("type \"%s\" is not a btree type or inode\n"),
cur_typ->name);
diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
index 6a97504..b3129f7 100644
--- a/man/man8/xfs_db.8
+++ b/man/man8/xfs_db.8
@@ -335,6 +335,7 @@ area of the inode, if neither option is given then both areas are shown.
.B btdump [-a] [-i]
If the cursor points to a btree node, dump the btree from that block downward.
If instead the cursor points to an inode, dump the data fork block mapping btree if there is one.
+If the cursor points to a directory or extended attribute btree node, dump that.
By default, only records stored in the btree are dumped.
.RS 1.0i
.TP 0.4i
next prev parent reply other threads:[~2017-08-01 15:41 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-31 21:06 [PATCH 0/7] xfsprogs: 4.13 rollup Darrick J. Wong
2017-07-31 21:06 ` [PATCH 1/7] xfs: remove double-underscore integer types Darrick J. Wong
2017-07-31 21:23 ` Eric Sandeen
2017-07-31 21:25 ` Darrick J. Wong
2017-08-02 9:13 ` Carlos Maiolino
2017-08-02 16:01 ` Darrick J. Wong
2017-07-31 21:07 ` [PATCH 2/7] xfs_repair: fix symlink target length checks by changing MAXPATHLEN to XFS_SYMLINK_MAXLEN Darrick J. Wong
2017-07-31 21:42 ` Eric Sandeen
2017-08-02 9:14 ` Carlos Maiolino
2017-07-31 21:07 ` [PATCH 3/7] xfs_db: fix metadump redirection (again) Darrick J. Wong
2017-07-31 21:57 ` Eric Sandeen
2017-08-01 16:23 ` [PATCH v2 " Darrick J. Wong
2017-08-02 9:17 ` Carlos Maiolino
2017-07-31 21:07 ` [PATCH 4/7] xfs_db: dump dir/attr btrees Darrick J. Wong
2017-07-31 22:05 ` Eric Sandeen
2017-08-01 14:59 ` Darrick J. Wong
2017-08-01 15:40 ` Darrick J. Wong [this message]
2017-08-01 16:21 ` [PATCH v2 " Eric Sandeen
2017-08-02 9:22 ` Carlos Maiolino
2017-08-02 9:24 ` Carlos Maiolino
2017-08-02 16:03 ` Darrick J. Wong
2017-07-31 21:07 ` [PATCH 5/7] xfs_db: print attribute remote value blocks Darrick J. Wong
2017-08-01 17:15 ` Eric Sandeen
2017-08-01 20:29 ` Darrick J. Wong
2017-08-01 21:04 ` [PATCH v2 " Darrick J. Wong
2017-08-02 9:36 ` Carlos Maiolino
2017-07-31 21:07 ` [PATCH 6/7] xfs_db: write values into dir/attr blocks and recalculate CRCs Darrick J. Wong
2017-08-02 9:40 ` Carlos Maiolino
2017-08-03 16:02 ` Eric Sandeen
2017-08-03 16:40 ` Darrick J. Wong
2017-07-31 21:07 ` [PATCH 7/7] xfs_db: introduce fuzz command Darrick J. Wong
2017-08-02 11:06 ` Carlos Maiolino
2017-08-03 16:47 ` [PATCH 8/7] xfs_db: use TYP_F_CRC_FUNC for inodes & dquots Eric Sandeen
2017-08-03 16:58 ` Darrick J. Wong
2017-08-03 17:15 ` [PATCH 8/7 V2] " Eric Sandeen
2017-08-03 18:05 ` Darrick J. Wong
2017-08-03 17:04 ` [PATCH 9/7] xfs_db: btdump should avoid eval for push and pop of cursor Darrick J. Wong
2017-08-03 17:18 ` Eric Sandeen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170801154053.GH4477@magnolia \
--to=darrick.wong@oracle.com \
--cc=linux-xfs@vger.kernel.org \
--cc=sandeen@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox