Skip to content

Commit

Permalink
xfs_copy: check for dirty log on non-duplicate copies
Browse files Browse the repository at this point in the history
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@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
  • Loading branch information
Brian Foster authored and dchinner committed Oct 13, 2015
1 parent 1c12a81 commit 3616eb8
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -81,7 +81,7 @@ growfs: libxcmd
io: libxcmd libhandle
quota: libxcmd
repair: libxlog

copy: libxlog

ifeq ($(HAVE_BUILDDEFS), yes)
include $(BUILDRULES)
Expand Down
4 changes: 2 additions & 2 deletions copy/Makefile
Expand Up @@ -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)
Expand Down
33 changes: 33 additions & 0 deletions copy/xfs_copy.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 3616eb8

Please sign in to comment.