diff mbox

[2/4] xfs_db: use iocursor type to guess btree geometry if bad magic

Message ID 149162063502.22901.11947139521251833946.stgit@birch.djwong.org (mailing list archive)
State Superseded
Headers show

Commit Message

Darrick J. Wong April 8, 2017, 3:03 a.m. UTC
From: Darrick J. Wong <darrick.wong@oracle.com>

The function block_to_bt plays an integral role in determining the btree
geometry of a block that we want to manipulate with the debugger.
Normally we use the block magic to find the geometry profile, but if the
magic is bad we'll never find it and return NULL.  The callers of this
function do not check for NULL and crash.

Therefore, if we can't find a geometry profile matching the magic
number, use the iocursor type to guess the profile and scowl about that
to stdout.  This makes it so that even with a corrupt magic we can try
to print the fields instead of crashing the debugger.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 db/btblock.c |   51 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 43 insertions(+), 8 deletions(-)



--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Dave Chinner April 8, 2017, 11:19 p.m. UTC | #1
On Fri, Apr 07, 2017 at 08:03:55PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> The function block_to_bt plays an integral role in determining the btree
> geometry of a block that we want to manipulate with the debugger.
> Normally we use the block magic to find the geometry profile, but if the
> magic is bad we'll never find it and return NULL.  The callers of this
> function do not check for NULL and crash.
> 
> Therefore, if we can't find a geometry profile matching the magic
> number, use the iocursor type to guess the profile and scowl about that
> to stdout.  This makes it so that even with a corrupt magic we can try
> to print the fields instead of crashing the debugger.

....

> +#define M(a,b) (!xfs_sb_version_hascrc(&mp->m_sb) ? (a) : (b))
> +	switch (iocur_top->typ->typnm) {
> +	case TYP_BMAPBTA:
> +	case TYP_BMAPBTD:
> +		magic = M(XFS_BMAP_MAGIC, XFS_BMAP_CRC_MAGIC);
> +		break;

That's really quite special, Darrick. :P

This:

	(!xfs_sb_version_hascrc(&mp->m_sb) ? (a) : (b))

Could written more simply as:

	(xfs_sb_version_hascrc(&mp->m_sb) ? (b) : (a))

or you could swap the macro args so you only need to drop the
negation.

Even better, though, would be to use a local variable to only
evaluate the CRC status once and kill the macro altogether:

	has_crc = xfs_sb_version_hascrc(&mp->m_sb);
	switch (iocur_top->typ->typnm) {
	case TYP_BMAPBTA:
	case TYP_BMAPBTD:
		magic = has_crc ? XFS_ABTB_CRC_MAGIC : XFS_ABTB_MAGIC;
		break;
.....

-Dave.
Darrick J. Wong April 10, 2017, 9:08 p.m. UTC | #2
On Sun, Apr 09, 2017 at 09:19:53AM +1000, Dave Chinner wrote:
> On Fri, Apr 07, 2017 at 08:03:55PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > The function block_to_bt plays an integral role in determining the btree
> > geometry of a block that we want to manipulate with the debugger.
> > Normally we use the block magic to find the geometry profile, but if the
> > magic is bad we'll never find it and return NULL.  The callers of this
> > function do not check for NULL and crash.
> > 
> > Therefore, if we can't find a geometry profile matching the magic
> > number, use the iocursor type to guess the profile and scowl about that
> > to stdout.  This makes it so that even with a corrupt magic we can try
> > to print the fields instead of crashing the debugger.
> 
> ....
> 
> > +#define M(a,b) (!xfs_sb_version_hascrc(&mp->m_sb) ? (a) : (b))
> > +	switch (iocur_top->typ->typnm) {
> > +	case TYP_BMAPBTA:
> > +	case TYP_BMAPBTD:
> > +		magic = M(XFS_BMAP_MAGIC, XFS_BMAP_CRC_MAGIC);
> > +		break;
> 
> That's really quite special, Darrick. :P
> 
> This:
> 
> 	(!xfs_sb_version_hascrc(&mp->m_sb) ? (a) : (b))
> 
> Could written more simply as:
> 
> 	(xfs_sb_version_hascrc(&mp->m_sb) ? (b) : (a))
> 
> or you could swap the macro args so you only need to drop the
> negation.
> 
> Even better, though, would be to use a local variable to only
> evaluate the CRC status once and kill the macro altogether:
> 
> 	has_crc = xfs_sb_version_hascrc(&mp->m_sb);
> 	switch (iocur_top->typ->typnm) {
> 	case TYP_BMAPBTA:
> 	case TYP_BMAPBTD:
> 		magic = has_crc ? XFS_ABTB_CRC_MAGIC : XFS_ABTB_MAGIC;
> 		break;
> .....

Ok, done.

--D

> 
> -Dave.
> -- 
> Dave Chinner
> david@fromorbit.com
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/db/btblock.c b/db/btblock.c
index 835a5f0..ba81645 100644
--- a/db/btblock.c
+++ b/db/btblock.c
@@ -25,6 +25,8 @@ 
 #include "print.h"
 #include "bit.h"
 #include "init.h"
+#include "io.h"
+#include "output.h"
 
 /*
  * Definition of the possible btree block layouts.
@@ -122,13 +124,49 @@  static struct xfs_db_btree *
 block_to_bt(
 	struct xfs_btree_block	*bb)
 {
-	struct xfs_db_btree *btp = &btrees[0];
+	struct xfs_db_btree	*btp;
+	uint32_t		magic;
+
+	magic = be32_to_cpu((bb)->bb_magic);
+	for (btp = &btrees[0]; btp->magic != 0; btp++)
+		if (magic == btp->magic)
+			return btp;
 
-	do {
-		if (be32_to_cpu((bb)->bb_magic) == btp->magic)
+#define M(a,b) (!xfs_sb_version_hascrc(&mp->m_sb) ? (a) : (b))
+	switch (iocur_top->typ->typnm) {
+	case TYP_BMAPBTA:
+	case TYP_BMAPBTD:
+		magic = M(XFS_BMAP_MAGIC, XFS_BMAP_CRC_MAGIC);
+		break;
+	case TYP_BNOBT:
+		magic = M(XFS_ABTB_MAGIC, XFS_ABTB_CRC_MAGIC);
+		break;
+	case TYP_CNTBT:
+		magic = M(XFS_ABTC_MAGIC, XFS_ABTC_CRC_MAGIC);
+		break;
+	case TYP_INOBT:
+		magic = M(XFS_IBT_MAGIC, XFS_IBT_CRC_MAGIC);
+		break;
+	case TYP_FINOBT:
+		magic = M(XFS_FIBT_MAGIC, XFS_FIBT_CRC_MAGIC);
+		break;
+	case TYP_RMAPBT:
+		magic = M(0, XFS_RMAP_CRC_MAGIC);
+		break;
+	case TYP_REFCBT:
+		magic = M(0, XFS_REFC_CRC_MAGIC);
+		break;
+	default:
+		ASSERT(0);
+	}
+#undef M
+	dbprintf(_("Bad btree magic 0x%x; coercing to %s.\n"),
+		be32_to_cpu((bb)->bb_magic),
+		iocur_top->typ->name);
+
+	for (btp = &btrees[0]; btp->magic != 0; btp++)
+		if (magic == btp->magic)
 			return btp;
-		btp++;
-	} while (btp->magic != 0);
 
 	return NULL;
 }
@@ -193,7 +231,6 @@  btblock_key_offset(
 	int			offset;
 
 	ASSERT(startoff == 0);
-	ASSERT(block->bb_level != 0);
 
 	offset = bt->block_len + (idx - 1) * bt->key_len;
 	return bitize(offset);
@@ -214,7 +251,6 @@  btblock_ptr_offset(
 	int			maxrecs;
 
 	ASSERT(startoff == 0);
-	ASSERT(block->bb_level != 0);
 
 	maxrecs = btblock_maxrecs(bt, mp->m_sb.sb_blocksize);
 	offset = bt->block_len +
@@ -238,7 +274,6 @@  btblock_rec_offset(
 	int			offset;
 
 	ASSERT(startoff == 0);
-	ASSERT(block->bb_level == 0);
 
 	offset = bt->block_len + (idx - 1) * bt->rec_len;
 	return bitize(offset);