From 1d6cb11574d2432d20c6f283ac77b15d69a986d9 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 14 Oct 2015 10:58:24 +1100 Subject: [PATCH] xfs_repair: track log state throughout all recovery phases 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 Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- include/xfs_mount.h | 6 ++++++ repair/phase2.c | 34 +++++++++++++++++++--------------- repair/xfs_repair.c | 8 +++++++- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/xfs_mount.h b/include/xfs_mount.h index ed897a23f..5ec68663f 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -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; /* diff --git a/repair/phase2.c b/repair/phase2.c index 0673a0cd5..11504e31e 100644 --- a/repair/phase2.c +++ b/repair/phase2.c @@ -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")); } /* diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 85a012b3c..0e801242c 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -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 -- 2.47.2