]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
db/metadump: bump lsn when log is cleared on v5 supers
authorBrian Foster <bfoster@redhat.com>
Tue, 13 Oct 2015 23:58:25 +0000 (10:58 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 13 Oct 2015 23:58:25 +0000 (10:58 +1100)
xfs_metadump handles the log in different ways depending on the mode of
operation. If the log is dirty or obfuscation and stale data zeroing are
disabled, the log is copied as is. In all other scenarios, the log is
explicitly zeroed. This is incorrect for version 5 superblocks where the
current LSN is always expected to be ahead of all fs metadata.

Update metadump to use libxfs_log_clear() to format the log with an
elevated LSN rather than zero the log and reset the current the LSN.
Metadump does not use buffers for the dump target, instead using a
cursor implementation to access the log via a single memory buffer.
Therefore, update libxfs_log_clear() to receive an optional (but
exclusive to the buftarg parameter) memory buffer pointer for the log.
If the pointer is provided, the log format is written out to this
buffer. Otherwise, fall back to the original behavior and access the log
through buftarg buffers.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
db/metadump.c
db/sb.c
include/libxfs.h
libxfs/rdwr.c
mkfs/xfs_mkfs.c
repair/phase2.c
repair/xfs_repair.c

index 129670ebdb4699eccbb6f42b5121f925d177e9bb..56b733ef085586b1e61cb93362d111fa19630fb4 100644 (file)
@@ -2514,6 +2514,10 @@ copy_log(void)
 {
        struct xlog     log;
        int             dirty;
+       xfs_daddr_t     logstart;
+       int             logblocks;
+       int             logversion;
+       int             cycle = XLOG_INIT_CYCLE;
 
        if (show_progress)
                print_progress("Copying log");
@@ -2538,8 +2542,16 @@ copy_log(void)
                /* clear out a clean log */
                if (show_progress)
                        print_progress("Zeroing clean log");
-               memset(iocur_top->data, 0,
-                       mp->m_sb.sb_logblocks * mp->m_sb.sb_blocksize);
+
+               logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
+               logblocks = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
+               logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1;
+               if (xfs_sb_version_hascrc(&mp->m_sb))
+                       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);
                break;
        case 1:
                /* keep the dirty log */
diff --git a/db/sb.c b/db/sb.c
index 30c622dcd39cbed82a922e514ff4d6d1cdcf9107..17d446ceca739252850727ec246aef6c816adea9 100644 (file)
--- a/db/sb.c
+++ b/db/sb.c
@@ -283,7 +283,7 @@ sb_logzero(uuid_t *uuidp)
 
        dbprintf(_("Clearing log and setting UUID\n"));
 
-       error =  libxfs_log_clear(mp->m_logdev_targp,
+       error =  libxfs_log_clear(mp->m_logdev_targp, NULL,
                        XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
                        (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
                        uuidp,
index 6c8793433952ee452aa7e609e032f81debdccbab..f733c36d97bd7fcdd3439e14cf3d554fd8e00cd8 100644 (file)
@@ -153,8 +153,8 @@ typedef char        *(libxfs_get_block_t)(char *, int, void *);
  * Helpers to clear the log to a particular log cycle.
  */
 #define XLOG_INIT_CYCLE        1
-extern int     libxfs_log_clear(struct xfs_buftarg *, xfs_daddr_t, uint,
-                                uuid_t *, int, int, int, int);
+extern int     libxfs_log_clear(struct xfs_buftarg *, char *, xfs_daddr_t,
+                                uint, uuid_t *, int, int, int, int);
 extern int     libxfs_log_header(char *, uuid_t *, int, int, int, xfs_lsn_t,
                                  xfs_lsn_t, libxfs_get_block_t *, void *);
 
index 93f6eb7542e6d03aa048474631ba2e5a4d4990ef..c19070fb6923ca04035cf4a27d8ae93b9b815c37 100644 (file)
@@ -133,38 +133,54 @@ static void unmount_record(void *p)
        memcpy((char *)p + sizeof(xlog_op_header_t), &magic, sizeof(magic));
 }
 
-static char *next(char *ptr, int offset, void *private)
+static char *next(
+       char            *ptr,
+       int             offset,
+       void            *private)
 {
-       xfs_buf_t       *buf = (xfs_buf_t *)private;
+       struct xfs_buf  *buf = (struct xfs_buf *)private;
 
-       if (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset)
+       if (buf &&
+           (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset))
                abort();
+
        return ptr + offset;
 }
 
+/*
+ * Format the log. The caller provides either a buftarg which is used to access
+ * the log via buffers or a direct pointer to a buffer that encapsulates the
+ * entire log.
+ */
 int
 libxfs_log_clear(
        struct xfs_buftarg      *btp,
+       char                    *dptr,
        xfs_daddr_t             start,
-       uint                    length,
+       uint                    length,         /* basic blocks */
        uuid_t                  *fs_uuid,
        int                     version,
-       int                     sunit,
+       int                     sunit,          /* bytes */
        int                     fmt,
        int                     cycle)
 {
-       xfs_buf_t               *bp;
+       struct xfs_buf          *bp = NULL;
        int                     len;
        xfs_lsn_t               lsn;
        xfs_lsn_t               tail_lsn;
        xfs_daddr_t             blk;
        xfs_daddr_t             end_blk;
+       char                    *ptr;
 
-       if (!btp->dev || !fs_uuid)
+       if (((btp && dptr) || (!btp && !dptr)) ||
+           (btp && !btp->dev) || !fs_uuid)
                return -EINVAL;
 
        /* first zero the log */
-       libxfs_device_zero(btp, start, length);
+       if (btp)
+               libxfs_device_zero(btp, start, length);
+       else
+               memset(dptr, 0, BBTOB(length));
 
        /*
         * Initialize the log record length and LSNs. XLOG_INIT_CYCLE is a
@@ -182,11 +198,17 @@ libxfs_log_clear(
                tail_lsn = xlog_assign_lsn(cycle - 1, length - len);
 
        /* write out the first log record */
-       bp = libxfs_getbufr(btp, start, len);
-       libxfs_log_header(XFS_BUF_PTR(bp), fs_uuid, version, sunit, fmt,
-                         lsn, tail_lsn, next, bp);
-       bp->b_flags |= LIBXFS_B_DIRTY;
-       libxfs_putbufr(bp);
+       ptr = dptr;
+       if (btp) {
+               bp = libxfs_getbufr(btp, start, len);
+               ptr = XFS_BUF_PTR(bp);
+       }
+       libxfs_log_header(ptr, fs_uuid, version, sunit, fmt, lsn, tail_lsn,
+                         next, bp);
+       if (bp) {
+               bp->b_flags |= LIBXFS_B_DIRTY;
+               libxfs_putbufr(bp);
+       }
 
        /*
         * There's nothing else to do if this is a log reset. The kernel detects
@@ -207,6 +229,8 @@ libxfs_log_clear(
         */
        cycle--;
        blk = start + len;
+       if (dptr)
+               dptr += BBTOB(len);
        end_blk = start + length;
 
        len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
@@ -214,18 +238,26 @@ libxfs_log_clear(
                lsn = xlog_assign_lsn(cycle, blk - start);
                tail_lsn = xlog_assign_lsn(cycle, blk - start - len);
 
-               bp = libxfs_getbufr(btp, blk, len);
+               ptr = dptr;
+               if (btp) {
+                       bp = libxfs_getbufr(btp, blk, len);
+                       ptr = XFS_BUF_PTR(bp);
+               }
                /*
                 * Note: pass the full buffer length as the sunit to initialize
                 * the entire buffer.
                 */
-               libxfs_log_header(XFS_BUF_PTR(bp), fs_uuid, version, BBTOB(len),
-                                 fmt, lsn, tail_lsn, next, bp);
-               bp->b_flags |= LIBXFS_B_DIRTY;
-               libxfs_putbufr(bp);
+               libxfs_log_header(ptr, fs_uuid, version, BBTOB(len), fmt, lsn,
+                                 tail_lsn, next, bp);
+               if (bp) {
+                       bp->b_flags |= LIBXFS_B_DIRTY;
+                       libxfs_putbufr(bp);
+               }
 
-               len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
                blk += len;
+               if (dptr)
+                       dptr += BBTOB(len);
+               len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
        }
 
        return 0;
index 9fb811e0d35c4f87c18d5d04db2d0c50fb24de12..7cba41a69dcbbc325394cc94c8130c27321d8349 100644 (file)
@@ -2710,7 +2710,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
        /*
         * Zero the log....
         */
-       libxfs_log_clear(mp->m_logdev_targp,
+       libxfs_log_clear(mp->m_logdev_targp, NULL,
                XFS_FSB_TO_DADDR(mp, logstart),
                (xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
                &sbp->sb_uuid, logversion, lsunit, XLOG_FMT, XLOG_INIT_CYCLE);
index f9d0e22662cb5503754c0874557a0d07d065846d..cb24711d23fe4a7a4e7da772863932ce9d90afe1 100644 (file)
@@ -114,7 +114,7 @@ zero_log(
         * filesystems.
         */
        if (!no_modify && zap_log) {
-               libxfs_log_clear(log->l_dev,
+               libxfs_log_clear(log->l_dev, NULL,
                        XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
                        (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
                        &mp->m_sb.sb_uuid,
index 8285d9d1c1258550429ebb0bd316eed718228868..bed2ff5a8f291061ca301fc3b39fbdfb6d2fc94f 100644 (file)
@@ -584,8 +584,9 @@ format_log_max_lsn(
        }
 
        do_warn(_("Format log to cycle %d.\n"), new_cycle);
-       libxfs_log_clear(log->l_dev, logstart, logblocks, &mp->m_sb.sb_uuid,
-                        logversion, mp->m_sb.sb_logsunit, XLOG_FMT, new_cycle);
+       libxfs_log_clear(log->l_dev, NULL, logstart, logblocks,
+                        &mp->m_sb.sb_uuid, logversion, mp->m_sb.sb_logsunit,
+                        XLOG_FMT, new_cycle);
 }
 
 int