All of lore.kernel.org
 help / color / mirror / Atom feed
From: hal@deer-run.com
To: linux-xfs@vger.kernel.org
Subject: [PATCH] xfs_db: add blockget -L option
Date: Thu, 10 May 2018 21:36:36 +0000	[thread overview]
Message-ID: <20180510213636.GA5045@deer-run.com> (raw)

From: Hal Pomeranz <hal@deer-run.com>

Allow blockget on a mounted file system or "dirty" file system image
with pending log entries-- by simply ignoring the log.  This makes
xfs_db more useful for forensics where we are often dealing with these
types of images.  Flushing log entries to disk by mounting/unmounting
the file system would allow us to use blockget, but would make changes
to the file system state which are not desirable in forensics contexts.

Signed-off-by: Hal Pomeranz <hal@deer-run.com>
---
 db/check.c        | 74 +++++++++++++++++++++++++++++++------------------------
 db/sb.c           | 12 ++++-----
 man/man8/xfs_db.8 |  8 +++++-
 3 files changed, 55 insertions(+), 39 deletions(-)

diff --git a/db/check.c b/db/check.c
index 2f8dee5..034676a 100644
--- a/db/check.c
+++ b/db/check.c
@@ -378,7 +378,7 @@ static const cmdinfo_t	blockfree_cmd =
 	  NULL, N_("free block usage information"), NULL };
 static const cmdinfo_t	blockget_cmd =
 	{ "blockget", "check", blockget_f, 0, -1, 0,
-	  N_("[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..."),
+	  N_("[-s|-v] [-L] [-n] [-t] [-b bno]... [-i ino] ..."),
 	  N_("get block usage and check consistency"), NULL };
 static const cmdinfo_t	blocktrash_cmd =
 	{ "blocktrash", NULL, blocktrash_f, 0, -1, 0,
@@ -1850,38 +1850,11 @@ init(
 	int		c;
 	xfs_ino_t	ino;
 	int		rt;
+	int		ignore_log;
+	int		lc;
 
-	serious_error = 0;
-	if (mp->m_sb.sb_magicnum != XFS_SB_MAGIC) {
-		dbprintf(_("bad superblock magic number %x, giving up\n"),
-			mp->m_sb.sb_magicnum);
-		serious_error = 1;
-		return 0;
-	}
-	if (!sb_logcheck())
-		return 0;
-	rt = mp->m_sb.sb_rextents != 0;
-	dbmap = xmalloc((mp->m_sb.sb_agcount + rt) * sizeof(*dbmap));
-	inomap = xmalloc((mp->m_sb.sb_agcount + rt) * sizeof(*inomap));
-	inodata = xmalloc(mp->m_sb.sb_agcount * sizeof(*inodata));
-	inodata_hash_size =
-		(int)MAX(MIN(mp->m_sb.sb_icount /
-				(INODATA_AVG_HASH_LENGTH * mp->m_sb.sb_agcount),
-			     MAX_INODATA_HASH_SIZE),
-			 MIN_INODATA_HASH_SIZE);
-	for (c = 0; c < mp->m_sb.sb_agcount; c++) {
-		dbmap[c] = xcalloc(mp->m_sb.sb_agblocks, sizeof(**dbmap));
-		inomap[c] = xcalloc(mp->m_sb.sb_agblocks, sizeof(**inomap));
-		inodata[c] = xcalloc(inodata_hash_size, sizeof(**inodata));
-	}
-	if (rt) {
-		dbmap[c] = xcalloc(mp->m_sb.sb_rblocks, sizeof(**dbmap));
-		inomap[c] = xcalloc(mp->m_sb.sb_rblocks, sizeof(**inomap));
-		sumfile = xcalloc(mp->m_rsumsize, 1);
-		sumcompute = xcalloc(mp->m_rsumsize, 1);
-	}
-	nflag = sflag = tflag = verbose = optind = 0;
-	while ((c = getopt(argc, argv, "b:i:npstv")) != EOF) {
+	ignore_log = nflag = sflag = tflag = verbose = optind = 0;
+	while ((c = getopt(argc, argv, "b:i:Lnpstv")) != EOF) {
 		switch (c) {
 		case 'b':
 			bno = strtoll(optarg, NULL, 10);
@@ -1891,6 +1864,9 @@ init(
 			ino = strtoll(optarg, NULL, 10);
 			add_ilist(ino);
 			break;
+		case 'L':
+			ignore_log = 1;
+			break;
 		case 'n':
 			nflag = 1;
 			break;
@@ -1911,6 +1887,40 @@ init(
 			return 0;
 		}
 	}
+
+	serious_error = 0;
+	if (mp->m_sb.sb_magicnum != XFS_SB_MAGIC) {
+		dbprintf(_("bad superblock magic number %x, giving up\n"),
+			mp->m_sb.sb_magicnum);
+		serious_error = 1;
+		return 0;
+	}
+
+	lc = sb_logcheck();
+	if (lc < 0 || (lc == 0 && ignore_log == 0))
+		return 0;
+
+	rt = mp->m_sb.sb_rextents != 0;
+	dbmap = xmalloc((mp->m_sb.sb_agcount + rt) * sizeof(*dbmap));
+	inomap = xmalloc((mp->m_sb.sb_agcount + rt) * sizeof(*inomap));
+	inodata = xmalloc(mp->m_sb.sb_agcount * sizeof(*inodata));
+	inodata_hash_size =
+		(int)MAX(MIN(mp->m_sb.sb_icount /
+				(INODATA_AVG_HASH_LENGTH * mp->m_sb.sb_agcount),
+			     MAX_INODATA_HASH_SIZE),
+			 MIN_INODATA_HASH_SIZE);
+	for (c = 0; c < mp->m_sb.sb_agcount; c++) {
+		dbmap[c] = xcalloc(mp->m_sb.sb_agblocks, sizeof(**dbmap));
+		inomap[c] = xcalloc(mp->m_sb.sb_agblocks, sizeof(**inomap));
+		inodata[c] = xcalloc(inodata_hash_size, sizeof(**inodata));
+	}
+	if (rt) {
+		dbmap[c] = xcalloc(mp->m_sb.sb_rblocks, sizeof(**dbmap));
+		inomap[c] = xcalloc(mp->m_sb.sb_rblocks, sizeof(**inomap));
+		sumfile = xcalloc(mp->m_rsumsize, 1);
+		sumcompute = xcalloc(mp->m_rsumsize, 1);
+	}
+
 	error = sbver_err = serious_error = 0;
 	fdblocks = frextents = icount = ifree = 0;
 	sbversion = XFS_SB_VERSION_4;
diff --git a/db/sb.c b/db/sb.c
index c7fbfd6..ba51910 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -235,13 +235,13 @@ sb_logcheck(void)
 		if (x.logdev && x.logdev != x.ddev) {
 			dbprintf(_("aborting - external log specified for FS "
 				 "with an internal log\n"));
-			return 0;
+			return -1;
 		}
 	} else {
 		if (!x.logdev || (x.logdev == x.ddev)) {
 			dbprintf(_("aborting - no external log specified for FS "
 				 "with an external log\n"));
-			return 0;
+			return -1;
 		}
 	}
 
@@ -250,14 +250,14 @@ sb_logcheck(void)
 	dirty = xlog_is_dirty(mp, mp->m_log, &x, 0);
 	if (dirty == -1) {
 		dbprintf(_("ERROR: cannot find log head/tail, run xfs_repair\n"));
-		return 0;
+		return -1;
 	} else if (dirty == 1) {
 		dbprintf(_(
 "ERROR: The filesystem has valuable metadata changes in a log which needs to\n"
 "be replayed.  Mount the filesystem to replay the log, and unmount it before\n"
 "re-running %s.  If you are unable to mount the filesystem, then use\n"
-"the xfs_repair -L option to destroy the log and attempt a repair.\n"
-"Note that destroying the log may cause corruption -- please attempt a mount\n"
+"the -L option to ignore the log. Note that ignoring the log may cause\n"
+"the program to crash or produce erroneous output. Please attempt a mount\n"
 "of the filesystem before doing this.\n"), progname);
 		return 0;
 	}
@@ -271,7 +271,7 @@ sb_logzero(uuid_t *uuidp)
 	int	cycle = XLOG_INIT_CYCLE;
 	int	error;
 
-	if (!sb_logcheck())
+	if (sb_logcheck() < 1)
 		return 0;
 
 	/*
diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
index 524b1ef..ec6a5ed 100644
--- a/man/man8/xfs_db.8
+++ b/man/man8/xfs_db.8
@@ -194,7 +194,7 @@ command. This must be done before another
 .B blockget
 command can be given, presumably with different arguments than the previous one.
 .TP
-.BI "blockget [\-npvs] [\-b " bno "] ... [\-i " ino "] ..."
+.BI "blockget [\-Lnpvs] [\-b " bno "] ... [\-i " ino "] ..."
 Get block usage and check filesystem consistency.
 The information is saved for use by a subsequent
 .BR blockuse ", " ncheck ", or " blocktrash
@@ -209,6 +209,12 @@ information should be printed.
 is used to specify inode numbers about which verbose information
 should be printed.
 .TP
+.B \-L
+is used to ignore unplayed log entries and attempt to run
+.B blockget
+anyway. Note that using this option may cause the program to crash
+or produce erroneous output.
+.TP
 .B \-n
 is used to save pathnames for inodes visited, this is used to support the
 .BR xfs_ncheck (8)
-- 
1.8.3.1


             reply	other threads:[~2018-05-10 21:37 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-10 21:36 hal [this message]
2018-05-15  3:14 ` [PATCH] xfs_db: add blockget -L option Eric Sandeen
2018-05-15  4:27   ` Hal Pomeranz
2018-05-15  5:27     ` Dave Chinner
2018-05-15 14:14       ` 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=20180510213636.GA5045@deer-run.com \
    --to=hal@deer-run.com \
    --cc=linux-xfs@vger.kernel.org \
    /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.