xfs
[Top] [All Lists]

[PATCH v3 14/18] xfs_copy: check for dirty log on non-duplicate copies

To: xfs@xxxxxxxxxxx
Subject: [PATCH v3 14/18] xfs_copy: check for dirty log on non-duplicate copies
From: Brian Foster <bfoster@xxxxxxxxxx>
Date: Fri, 2 Oct 2015 14:19:51 -0400
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1443809995-20395-1-git-send-email-bfoster@xxxxxxxxxx>
References: <1443809995-20395-1-git-send-email-bfoster@xxxxxxxxxx>
xfs_copy either copies the log as-is or formats the log of the target(s)
based on whether duplicate copy mode is enabled. The target log is
formatted when non-duplicate mode is enabled because copies gain a new
fs UUID and the new UUID must be stamped into the log.

When non-duplicate mode is enabled, however, xfs_copy does not check
whether the source filesystem log is actually clean. If the source log
is dirty, the target filesystem is silently created with a clean log and
thus ends up in a potentially corrupted state.

Update xfs_copy to check the source log state and fail the copy if in
non-duplicate mode and the log is dirty. Encourage the user to mount the
filesystem or run xfs_repair to clear the log. Note that the log is
scanned unconditionally as opposed to only in non-duplicate mode because
v5 superblock log format support requires the current cycle number to
format the log correctly.

Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>
---
 Makefile        |  2 +-
 copy/Makefile   |  4 ++--
 copy/xfs_copy.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index 19fb8c5..fca0a42 100644
--- a/Makefile
+++ b/Makefile
@@ -81,7 +81,7 @@ growfs: libxcmd
 io: libxcmd libhandle
 quota: libxcmd
 repair: libxlog
-
+copy: libxlog
 
 ifeq ($(HAVE_BUILDDEFS), yes)
 include $(BUILDRULES)
diff --git a/copy/Makefile b/copy/Makefile
index beabbd4..e630b17 100644
--- a/copy/Makefile
+++ b/copy/Makefile
@@ -9,8 +9,8 @@ LTCOMMAND = xfs_copy
 CFILES = xfs_copy.c
 HFILES = xfs_copy.h
 
-LLDLIBS = $(LIBXFS) $(LIBUUID) $(LIBPTHREAD) $(LIBRT)
-LTDEPENDENCIES = $(LIBXFS)
+LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBPTHREAD) $(LIBRT)
+LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG)
 LLDFLAGS = -static-libtool-libs
 
 default: depend $(LTCOMMAND)
diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c
index 949be5f..f3e5288 100644
--- a/copy/xfs_copy.c
+++ b/copy/xfs_copy.c
@@ -23,6 +23,7 @@
 #include <signal.h>
 #include <stdarg.h>
 #include "xfs_copy.h"
+#include "libxlog.h"
 
 #define        rounddown(x, y) (((x)/(y))*(y))
 #define uuid_equal(s,d) (platform_uuid_compare((s),(d)) == 0)
@@ -128,6 +129,12 @@ do_message(int flags, int code, const char *fmt, ...)
                        exit(1); \
                } while (0)
 
+/* workaround craziness in the xlog routines */
+int xlog_recover_do_trans(struct xlog *log, struct xlog_recover *t, int p)
+{
+       return 0;
+}
+
 void
 check_errors(void)
 {
@@ -522,6 +529,7 @@ main(int argc, char **argv)
        ag_header_t     ag_hdr;
        xfs_mount_t     *mp;
        xfs_mount_t     mbuf;
+       struct xlog     xlog;
        xfs_buf_t       *sbp;
        xfs_sb_t        *sb;
        xfs_agnumber_t  num_ags, agno;
@@ -717,6 +725,31 @@ main(int argc, char **argv)
                exit(1);
        }
 
+
+       /*
+        * Set up the mount pointer to access the log and check whether the log
+        * is clean. Fail on a dirty or corrupt log in non-duplicate mode
+        * because the log is formatted as part of the copy and we don't want to
+        * destroy data. We also need the current log cycle to format v5
+        * superblock logs correctly.
+        */
+       memset(&xlog, 0, sizeof(struct xlog));
+       mp->m_log = &xlog;
+       c = xlog_is_dirty(mp, mp->m_log, &xargs, 0);
+       if (!duplicate) {
+               if (c == 1) {
+                       do_log(_(
+"Error: source filesystem log is dirty. Mount the filesystem to replay the\n"
+"log, unmount and retry xfs_copy.\n"));
+                       exit(1);
+               } else if (c < 0) {
+                       do_log(_(
+"Error: could not determine the log head or tail of the source filesystem.\n"
+"Mount the filesystem to replay the log or run xfs_repair.\n"));
+                       exit(1);
+               }
+       }
+
        source_blocksize = mp->m_sb.sb_blocksize;
        source_sectorsize = mp->m_sb.sb_sectsize;
 
-- 
2.1.0

<Prev in Thread] Current Thread [Next in Thread>