[PATCH 3/5] xfs_db: metadump external log devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

Teach the metadump command to dump the contents of an external log to
the metadump file.

Older mdrestore programs aren't going to recognize the new metablock
info flag, change the magic number before adding new information flags
to signal that the metablock is describing blocks on either an external
log device or a realtime device.  Realtime support isn't needed now, but
it will be for realtime groups.

Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
---
 db/metadump.c           |   98 ++++++++++++++++++++++++++++++++++++++++++++++-
 db/xfs_metadump.sh      |    5 +-
 include/xfs_metadump.h  |    3 +
 man/man8/xfs_metadump.8 |   13 +++++-
 4 files changed, 111 insertions(+), 8 deletions(-)


diff --git a/db/metadump.c b/db/metadump.c
index 996c97ca6a2..f337493d505 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -3002,6 +3002,74 @@ _("Could not discern log; image will contain unobfuscated metadata in log."));
 	return !write_buf(iocur_top);
 }
 
+static int
+copy_external_log(void)
+{
+	struct xlog	log;
+	int		dirty;
+	xfs_daddr_t	logstart;
+	int		logblocks;
+	int		logversion;
+	int		cycle = XLOG_INIT_CYCLE;
+	int		error;
+
+	if (show_progress)
+		print_progress("Copying external log");
+
+	push_cur();
+	error = set_log_cur(&typtab[TYP_LOG],
+			XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
+			mp->m_sb.sb_logblocks * blkbb, DB_RING_IGN, NULL);
+	if (error)
+		return 0;
+	if (iocur_top->data == NULL) {
+		pop_cur();
+		print_warning("cannot read external log");
+		return !stop_on_read_error;
+	}
+
+	/* If not obfuscating or zeroing, just copy the log as it is */
+	if (!obfuscate && !zero_stale_data)
+		goto done;
+
+	dirty = xlog_is_dirty(mp, &log, &x, 0);
+
+	switch (dirty) {
+	case 0:
+		/* clear out a clean log */
+		if (show_progress)
+			print_progress("Zeroing clean log");
+
+		logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
+		logblocks = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
+		logversion = xfs_has_logv2(mp) ? 2 : 1;
+		if (xfs_has_crc(mp))
+			cycle = log.l_curr_cycle + 1;
+
+		libxfs_log_clear(NULL, iocur_top->data, logstart, logblocks,
+				 &mp->m_sb.sb_uuid, logversion,
+				 mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true);
+		break;
+	case 1:
+		/* keep the dirty log */
+		if (obfuscate)
+			print_warning(
+_("Warning: log recovery of an obfuscated metadata image can leak "
+"unobfuscated metadata and/or cause image corruption.  If possible, "
+"please mount the filesystem to clean the log, or disable obfuscation."));
+		break;
+	case -1:
+		/* log detection error */
+		if (obfuscate)
+			print_warning(
+_("Could not discern log; image will contain unobfuscated metadata in log."));
+		break;
+	}
+
+done:
+	return !write_buf(iocur_top);
+}
+
 static int
 metadump_f(
 	int 		argc,
@@ -3012,6 +3080,7 @@ metadump_f(
 	int		start_iocur_sp;
 	int		outfd = -1;
 	int		ret;
+	bool		copy_external = false;
 	char		*p;
 
 	exitcode = 1;
@@ -3035,7 +3104,7 @@ metadump_f(
 		return 0;
 	}
 
-	while ((c = getopt(argc, argv, "aegm:ow")) != EOF) {
+	while ((c = getopt(argc, argv, "aegm:owx")) != EOF) {
 		switch (c) {
 			case 'a':
 				zero_stale_data = 0;
@@ -3060,6 +3129,9 @@ metadump_f(
 			case 'w':
 				show_warnings = 1;
 				break;
+			case 'x':
+				copy_external = true;
+				break;
 			default:
 				print_warning("bad option for metadump command");
 				return 0;
@@ -3071,13 +3143,23 @@ metadump_f(
 		return 0;
 	}
 
+	/*
+	 * Use the old format if there are no external devices with metadata to
+	 * dump.
+	 */
+	if (mp->m_sb.sb_logstart != 0)
+		copy_external = false;
+
 	metablock = (xfs_metablock_t *)calloc(BBSIZE + 1, BBSIZE);
 	if (metablock == NULL) {
 		print_warning("memory allocation failure");
 		return 0;
 	}
 	metablock->mb_blocklog = BBSHIFT;
-	metablock->mb_magic = cpu_to_be32(XFS_MD_MAGIC);
+	if (copy_external)
+		metablock->mb_magic = cpu_to_be32(XFS_MDX_MAGIC);
+	else
+		metablock->mb_magic = cpu_to_be32(XFS_MD_MAGIC);
 
 	/* Set flags about state of metadump */
 	metablock->mb_info = XFS_METADUMP_INFO_FLAGS;
@@ -3165,7 +3247,7 @@ metadump_f(
 
 	exitcode = 0;
 
-	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
+	for (agno = 0; !exitcode && agno < mp->m_sb.sb_agcount; agno++) {
 		if (!scan_ag(agno)) {
 			exitcode = 1;
 			break;
@@ -3184,6 +3266,16 @@ metadump_f(
 	if (!exitcode)
 		exitcode = write_index() < 0;
 
+	/* write the external log, if desired */
+	if (!exitcode && mp->m_sb.sb_logstart == 0 && copy_external) {
+		metablock->mb_info |= XFS_METADUMP_LOGDEV;
+
+		if (!copy_external_log())
+			exitcode = 1;
+		if (!exitcode)
+			exitcode = write_index() < 0;
+	}
+
 	if (progress_since_warning)
 		fputc('\n', stdout_metadump ? stderr : stdout);
 
diff --git a/db/xfs_metadump.sh b/db/xfs_metadump.sh
index 9852a5bc2b0..06bfc4e7bd4 100755
--- a/db/xfs_metadump.sh
+++ b/db/xfs_metadump.sh
@@ -6,9 +6,9 @@
 
 OPTS=" "
 DBOPTS=" "
-USAGE="Usage: xfs_metadump [-aefFogwV] [-m max_extents] [-l logdev] source target"
+USAGE="Usage: xfs_metadump [-aefFgoVwx] [-m max_extents] [-l logdev] source target"
 
-while getopts "aefgl:m:owFV" c
+while getopts "aefgl:m:owFVx" c
 do
 	case $c in
 	a)	OPTS=$OPTS"-a ";;
@@ -24,6 +24,7 @@ do
 		status=$?
 		exit $status
 		;;
+	x)	OPTS=$OPTS"-x ";;
 	\?)	echo $USAGE 1>&2
 		exit 2
 		;;
diff --git a/include/xfs_metadump.h b/include/xfs_metadump.h
index fbd9902327b..2373b0d8b50 100644
--- a/include/xfs_metadump.h
+++ b/include/xfs_metadump.h
@@ -8,6 +8,7 @@
 #define _XFS_METADUMP_H_
 
 #define	XFS_MD_MAGIC		0x5846534d	/* 'XFSM' */
+#define	XFS_MDX_MAGIC		0x584d4458	/* 'XMDX' */
 
 typedef struct xfs_metablock {
 	__be32		mb_magic;
@@ -22,5 +23,7 @@ typedef struct xfs_metablock {
 #define XFS_METADUMP_OBFUSCATED	(1 << 1)
 #define XFS_METADUMP_FULLBLOCKS	(1 << 2)
 #define XFS_METADUMP_DIRTYLOG	(1 << 3)
+#define XFS_METADUMP_LOGDEV	(1 << 4) /* targets external log device */
+#define XFS_METADUMP_RTDEV	(1 << 5) /* targets realtime volume */
 
 #endif /* _XFS_METADUMP_H_ */
diff --git a/man/man8/xfs_metadump.8 b/man/man8/xfs_metadump.8
index c0e79d77993..b940cb084b5 100644
--- a/man/man8/xfs_metadump.8
+++ b/man/man8/xfs_metadump.8
@@ -4,7 +4,7 @@ xfs_metadump \- copy XFS filesystem metadata to a file
 .SH SYNOPSIS
 .B xfs_metadump
 [
-.B \-aefFgow
+.B \-aefFgowx
 ] [
 .B \-m
 .I max_extents
@@ -123,8 +123,10 @@ is stdout.
 .TP
 .BI \-l " logdev"
 For filesystems which use an external log, this specifies the device where the
-external log resides. The external log is not copied, only internal logs are
-copied.
+external log resides.
+To record the contents of the external log in the dump, the
+.B \-x
+option must also be specified.
 .TP
 .B \-m
 Set the maximum size of an allowed metadata extent.  Extremely large metadata
@@ -138,6 +140,11 @@ Disables obfuscation of file names and extended attributes.
 Prints warnings of inconsistent metadata encountered to stderr. Bad metadata
 is still copied.
 .TP
+.B \-x
+Dump the external log device, if present.
+The metadump file will not be compatible with older versions of
+.BR xfs_mdrestore (1).
+.TP
 .B \-V
 Prints the version number and exits.
 .SH DIAGNOSTICS




[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux