All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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 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.