[PATCH 9/8] libxlog: fix log buffer alignment

Dave Chinner
2013-05-01T00:17:26Z

From: Dave Chinner <dchinner@redhat.com>

The libxlog sync changed the way log buffers used in recovery are
aligned to sector sizes. The old code used to check for a zero log
sector size and not do any alignment - this check was removed from
the kernel code because there is always log sector size configured.
It turns out that userspace *never* sets the log sector size, so
userspace has always simply ignored the alignment in log replay
(oops!).

This problem manifested itself as detecting a freshly mkfs'd
filesystem as having a totally zeroed log and hence xfs_check was
emitting output and hence xfstests was refusing to run.

This patch correctly configures the callers that use the log
recovery code so that the log sector size is set appropriately and
ensures that log recovery operates as expected.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/sb.c | 5 +++++
libxlog/xfs_log_recover.c | 5 ++++-
logprint/logprint.c | 6 ++++++
repair/phase2.c | 4 ++++
4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/db/sb.c b/db/sb.c
index d83db9c..4da1f6a 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -235,10 +235,15 @@ sb_logcheck(void)
x.logdev = x.ddev;
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_sb.sb_logstart == 0) ? x.logdev : x.ddev;
log.l_logsize = BBTOB(log.l_logBBsize);
log.l_logBBsize = x.logBBsize;
log.l_logBBstart = x.logBBstart;
+ log.l_sectBBsize = BTOBB(x.lbsize);
log.l_mp = mp;

if (xlog_find_tail(&log, &head_blk, &tail_blk)) {
diff --git a/libxlog/xfs_log_recover.c b/libxlog/xfs_log_recover.c
index ad53e86..028d1e3 100644
--- a/libxlog/xfs_log_recover.c
+++ b/libxlog/xfs_log_recover.c
@@ -21,7 +21,10 @@
#define xfs_readonly_buftarg(buftarg) (0)

/* avoid set-but-unused var warning. gcc is not very bright. */
-#define xlog_clear_stale_blocks(log, taillsn) ((taillsn) = (taillsn))
+#define xlog_clear_stale_blocks(log, taillsn) ({ \
+ (taillsn) = (taillsn); \
+ (0); \
+})

/*
diff --git a/logprint/logprint.c b/logprint/logprint.c
index 813424a..3fbcdba 100644
--- a/logprint/logprint.c
+++ b/logprint/logprint.c
@@ -94,6 +94,10 @@ logstat(xfs_mount_t *mp)

x.logBBsize = XFS_FSB_TO_BB(mp, sb->sb_logblocks);
x.logBBstart = XFS_FSB_TO_DADDR(mp, sb->sb_logstart);
+ x.lbsize = BBSIZE;
+ if (xfs_sb_version_hassector(sb))
+ x.lbsize <<= (sb->sb_logsectlog - BBSHIFT);
+
if (!x.logname && sb->sb_logstart == 0) {
fprintf(stderr, _(" external log device not specified\n\n"));
usage();
@@ -105,6 +109,7 @@ logstat(xfs_mount_t *mp)
stat(x.dname, &s);
x.logBBsize = s.st_size >> 9;
x.logBBstart = 0;
+ x.lbsize = BBSIZE;
}

@@ -235,6 +240,7 @@ main(int argc, char **argv)
log.l_logsize = BBTOB(x.logBBsize);
log.l_logBBstart = x.logBBstart;
log.l_logBBsize = x.logBBsize;
+ log.l_sectBBsize = BTOBB(x.lbsize);
log.l_mp = &mount;

switch (print_operation) {
diff --git a/repair/phase2.c b/repair/phase2.c
index 23b457a..382cd7b 100644
--- a/repair/phase2.c
+++ b/repair/phase2.c
@@ -47,11 +47,15 @@ zero_log(xfs_mount_t *mp)
x.logdev = x.ddev;
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 = logdev;
log.l_logsize = BBTOB(x.logBBsize);
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;