]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: track log state throughout all recovery phases
authorBrian Foster <bfoster@redhat.com>
Tue, 13 Oct 2015 23:58:24 +0000 (10:58 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 13 Oct 2015 23:58:24 +0000 (10:58 +1100)
xfs_repair examines and clears the log in phase 2. Phase 2 acquires the
log state in local data structures that are lost upon phase exit. v5
filesystems require that the log is formatted with a higher cycle number
after the fs is repaired. This requires assessment of the log state to
determine whether a reformat is necessary.

Rather than duplicate the log processing code, update phase 2 to
populate a globally available log data structure. Add a log pointer to
xfs_mount, as exists in kernel space, that repair uses to store a
reference to the log that is available to various phases. Note that this
patch simply plumbs through the global log data structure and does not
change behavior in any way.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
include/xfs_mount.h
repair/phase2.c
repair/xfs_repair.c

index ed897a23fa472ebe2eeb6431705d4807113d9b44..5ec68663ff083d6699804313546a40aa41668ccc 100644 (file)
@@ -98,6 +98,12 @@ typedef struct xfs_mount {
                int     qi_dqperchunk;
        }                       *m_quotainfo;
 
+       /*
+        * xlog is defined in libxlog and thus is not intialized by libxfs. This
+        * allows an application to initialize and store a reference to the log
+        * if warranted.
+        */
+       struct xlog             *m_log;
 } xfs_mount_t;
 
 /*
index 0673a0cd57082506969e70018a8725c334592b1f..11504e31e95c18bc85aa15921807ccae4dc6a7a1 100644 (file)
@@ -39,33 +39,33 @@ static void
 zero_log(xfs_mount_t *mp)
 {
        int error;
-       struct xlog     log;
        xfs_daddr_t head_blk, tail_blk;
+       struct xlog     *log = mp->m_log;
 
-       memset(&log, 0, sizeof(log));
+       memset(log, 0, sizeof(struct xlog));
        x.logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
        x.logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
        x.lbsize = BBSIZE;
        if (xfs_sb_version_hassector(&mp->m_sb))
                x.lbsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT);
 
-       log.l_dev = mp->m_logdev_targp;
-       log.l_logBBsize = x.logBBsize;
-       log.l_logBBstart = x.logBBstart;
-       log.l_sectBBsize  = BTOBB(x.lbsize);
-       log.l_mp = mp;
+       log->l_dev = mp->m_logdev_targp;
+       log->l_logBBsize = x.logBBsize;
+       log->l_logBBstart = x.logBBstart;
+       log->l_sectBBsize  = BTOBB(x.lbsize);
+       log->l_mp = mp;
        if (xfs_sb_version_hassector(&mp->m_sb)) {
-               log.l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
-               ASSERT(log.l_sectbb_log <= mp->m_sectbb_log);
+               log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
+               ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
                /* for larger sector sizes, must have v2 or external log */
-               ASSERT(log.l_sectbb_log == 0 ||
-                       log.l_logBBstart == 0 ||
+               ASSERT(log->l_sectbb_log == 0 ||
+                       log->l_logBBstart == 0 ||
                        xfs_sb_version_haslogv2(&mp->m_sb));
                ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT);
        }
-       log.l_sectbb_mask = (1 << log.l_sectbb_log) - 1;
+       log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1;
 
-       if ((error = xlog_find_tail(&log, &head_blk, &tail_blk))) {
+       if ((error = xlog_find_tail(log, &head_blk, &tail_blk))) {
                do_warn(_("zero_log: cannot find log head/tail "
                          "(xlog_find_tail=%d), zeroing it anyway\n"),
                        error);
@@ -93,12 +93,16 @@ zero_log(xfs_mount_t *mp)
                }
        }
 
-       libxfs_log_clear(log.l_dev,
-               XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
+       libxfs_log_clear(log->l_dev, 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,
                xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1,
                mp->m_sb.sb_logsunit, XLOG_FMT, XLOG_INIT_CYCLE);
+
+       /* update the log data structure with new state */
+       error = xlog_find_tail(log, &head_blk, &tail_blk);
+       if (error || head_blk != tail_blk)
+               do_error(_("failed to clear log"));
 }
 
 /*
index 85a012b3ce0f0b206233f92c265f3fce6e0d44cf..0e801242c1309c20e368bc98f358f9ce44832654 100644 (file)
@@ -539,6 +539,7 @@ main(int argc, char **argv)
        xfs_dsb_t       *dsb;
        xfs_buf_t       *sbp;
        xfs_mount_t     xfs_m;
+       struct xlog     log = {0};
        char            *msgbuf;
        struct xfs_sb   psb;
        int             rval;
@@ -620,7 +621,11 @@ main(int argc, char **argv)
                }
        }
 
-       /* prepare the mount structure */
+       /*
+        * Prepare the mount structure. Point the log reference to our local
+        * copy so it's available to the various phases. The log bits are
+        * initialized in phase 2.
+        */
        memset(&xfs_m, 0, sizeof(xfs_mount_t));
        mp = libxfs_mount(&xfs_m, &psb, x.ddev, x.logdev, x.rtdev, 0);
 
@@ -630,6 +635,7 @@ main(int argc, char **argv)
                        progname);
                exit(1);
        }
+       mp->m_log = &log;
 
        /*
         * set XFS-independent status vars from the mount/sb structure