xfs
[Top] [All Lists]

[PATCH 02/12] xfsprogs: updata libxlog to current kernel code

To: xfs@xxxxxxxxxxx
Subject: [PATCH 02/12] xfsprogs: updata libxlog to current kernel code
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Tue, 22 Jan 2013 00:53:01 +1100
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1358776391-22140-1-git-send-email-david@xxxxxxxxxxxxx>
References: <1358776391-22140-1-git-send-email-david@xxxxxxxxxxxxx>
From: Dave Chinner <dchinner@xxxxxxxxxx>

Update the log recovery code to match the current 3.8-rc2 kernel code.

Note: while this introduces CRC validation infrastructure, it is
currently short-circuited as we cannot validate the CRC from
userspace because we do not know what the size of the log buffer was
that wrote the header. This information is not written into the log
header anywhere, so we have no way of working out the correct number
of extra headers that need to be summed. This is also a problem for
the kernel code, and needs fixing.

Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
---
 db/sb.c                    |    7 +-
 include/libxlog.h          |   32 ++---
 libxlog/xfs_log_recover.c  |  301 +++++++++++++++++++++++++++-----------------
 logprint/log_copy.c        |    2 +-
 logprint/log_dump.c        |    2 +-
 logprint/log_misc.c        |    4 +-
 logprint/log_print_all.c   |    2 +-
 logprint/log_print_trans.c |    4 +-
 logprint/logprint.c        |    2 +-
 logprint/logprint.h        |   10 +-
 repair/phase2.c            |    7 +-
 11 files changed, 229 insertions(+), 144 deletions(-)

diff --git a/db/sb.c b/db/sb.c
index 21f38c5..d83db9c 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -205,12 +205,15 @@ get_sb(xfs_agnumber_t agno, xfs_sb_t *sb)
 }
 
 /* workaround craziness in the xlog routines */
-int xlog_recover_do_trans(xlog_t *log, xlog_recover_t *t, int p) { return 0; }
+int xlog_recover_do_trans(struct xlog *log, xlog_recover_t *t, int p)
+{
+       return 0;
+}
 
 int
 sb_logcheck(void)
 {
-       xlog_t          log;
+       struct xlog     log;
        xfs_daddr_t     head_blk, tail_blk;
 
        if (mp->m_sb.sb_logstart) {
diff --git a/include/libxlog.h b/include/libxlog.h
index d1142ab..36ede59 100644
--- a/include/libxlog.h
+++ b/include/libxlog.h
@@ -24,7 +24,7 @@
  * xlog_t that we actually need to get our work done, avoiding
  * the need to define any exotic kernel types in userland.
  */
-typedef struct log {
+struct xlog {
        xfs_lsn_t       l_tail_lsn;     /* lsn of 1st LR w/ unflush buffers */
        xfs_lsn_t       l_last_sync_lsn;/* lsn of last LR on disk */
        xfs_mount_t     *l_mp;          /* mount point */
@@ -45,7 +45,7 @@ typedef struct log {
        uint            l_sectbb_mask;  /* sector size (in BBs)
                                         * alignment mask */
        int             l_sectBBsize;   /* size of log sector in 512 byte 
chunks */
-} xlog_t;
+};
 
 #include <xfs/xfs_log_recover.h>
 #include <xfs/xfs_buf_item.h>
@@ -76,6 +76,10 @@ typedef union {
 #define unlikely(x)                    (x)
 #define min(a,b)                       ((a) < (b) ? (a) : (b))
 
+#define xfs_warn(mp,fmt,args...)               cmn_err(CE_WARN,fmt, ## args)
+#define xfs_alert(mp,fmt,args...)              cmn_err(CE_ALERT,fmt, ## args)
+#define xfs_hex_dump(d,n)              ((void) 0)
+
 extern void xlog_warn(char *fmt,...);
 extern void xlog_exit(char *fmt,...);
 extern void xlog_panic(char *fmt,...);
@@ -88,34 +92,34 @@ extern int  print_record_header;
 /* libxfs parameters */
 extern libxfs_init_t   x;
 
-extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
+extern struct xfs_buf *xlog_get_bp(struct xlog *, int);
 extern void    xlog_put_bp(struct xfs_buf *);
-extern int     xlog_bread(xlog_t *log, xfs_daddr_t blk_no, int nbblks,
+extern int     xlog_bread(struct xlog *log, xfs_daddr_t blk_no, int nbblks,
                                xfs_buf_t *bp, xfs_caddr_t *offset);
-extern int     xlog_bread_noalign(xlog_t *log, xfs_daddr_t blk_no, int nbblks,
-                               xfs_buf_t *bp);
+extern int     xlog_bread_noalign(struct xlog *log, xfs_daddr_t blk_no,
+                               int nbblks, xfs_buf_t *bp);
 
-extern int     xlog_find_zeroed(xlog_t *log, xfs_daddr_t *blk_no);
-extern int     xlog_find_cycle_start(xlog_t *log, xfs_buf_t *bp,
+extern int     xlog_find_zeroed(struct xlog *log, xfs_daddr_t *blk_no);
+extern int     xlog_find_cycle_start(struct xlog *log, xfs_buf_t *bp,
                                xfs_daddr_t first_blk, xfs_daddr_t *last_blk, 
                                uint cycle);
-extern int     xlog_find_tail(xlog_t *log, xfs_daddr_t *head_blk,
+extern int     xlog_find_tail(struct xlog *log, xfs_daddr_t *head_blk,
                                xfs_daddr_t *tail_blk);
 
-extern int     xlog_test_footer(xlog_t *log);
-extern int     xlog_recover(xlog_t *log, int readonly);
+extern int     xlog_test_footer(struct xlog *log);
+extern int     xlog_recover(struct xlog *log, int readonly);
 extern void    xlog_recover_print_data(xfs_caddr_t p, int len);
 extern void    xlog_recover_print_logitem(xlog_recover_item_t *item);
 extern void    xlog_recover_print_trans_head(xlog_recover_t *tr);
-extern int     xlog_print_find_oldest(xlog_t *log, xfs_daddr_t *last_blk);
+extern int     xlog_print_find_oldest(struct xlog *log, xfs_daddr_t *last_blk);
 
 /* for transactional view */
 extern void    xlog_recover_print_trans_head(xlog_recover_t *tr);
 extern void    xlog_recover_print_trans(xlog_recover_t *trans,
                                struct list_head *itemq, int print);
-extern int     xlog_do_recovery_pass(xlog_t *log, xfs_daddr_t head_blk,
+extern int     xlog_do_recovery_pass(struct xlog *log, xfs_daddr_t head_blk,
                                xfs_daddr_t tail_blk, int pass);
-extern int     xlog_recover_do_trans(xlog_t *log, xlog_recover_t *trans,
+extern int     xlog_recover_do_trans(struct xlog *log, xlog_recover_t *trans,
                                int pass);
 extern int     xlog_header_check_recover(xfs_mount_t *mp, 
                                xlog_rec_header_t *head);
diff --git a/libxlog/xfs_log_recover.c b/libxlog/xfs_log_recover.c
index 23fe6fd..ad53e86 100644
--- a/libxlog/xfs_log_recover.c
+++ b/libxlog/xfs_log_recover.c
@@ -18,10 +18,11 @@
 
 #include <xfs/libxlog.h>
 
-#define xlog_unpack_data_checksum(rhead, dp, log)      ((void)0)
-#define xlog_clear_stale_blocks(log, tail_lsn)         (0)
 #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))
+
 
 /*
  * Verify the given count of basic blocks is valid number of blocks
@@ -31,7 +32,7 @@
 
 static inline int
 xlog_buf_bbcount_valid(
-       xlog_t          *log,
+       struct xlog     *log,
        int             bbcount)
 {
        return bbcount > 0 && bbcount <= log->l_logBBsize;
@@ -44,11 +45,11 @@ xlog_buf_bbcount_valid(
  */
 xfs_buf_t *
 xlog_get_bp(
-       xlog_t          *log,
+       struct xlog     *log,
        int             nbblks)
 {
        if (!xlog_buf_bbcount_valid(log, nbblks)) {
-               xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+               xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
                        nbblks);
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
                return NULL;
@@ -57,7 +58,7 @@ xlog_get_bp(
        /*
         * We do log I/O in units of log sectors (a power-of-2
         * multiple of the basic block size), so we round up the
-        * requested size to acommodate the basic blocks required
+        * requested size to accommodate the basic blocks required
         * for complete log sectors.
         *
         * In addition, the buffer may be used for a non-sector-
@@ -68,12 +69,11 @@ xlog_get_bp(
         * an issue.  Nor will this be a problem if the log I/O is
         * done in basic blocks (sector size 1).  But otherwise we
         * extend the buffer by one extra log sector to ensure
-        * there's space to accomodate this possiblility.
+        * there's space to accommodate this possibility.
         */
        if (nbblks > 1 && log->l_sectBBsize > 1)
                nbblks += log->l_sectBBsize;
-       if (log->l_sectBBsize)
-               nbblks = round_up(nbblks, log->l_sectBBsize);
+       nbblks = round_up(nbblks, log->l_sectBBsize);
 
        return libxfs_getbufr(log->l_dev, (xfs_daddr_t)-1, nbblks);
 }
@@ -91,57 +91,54 @@ xlog_put_bp(
  */
 STATIC xfs_caddr_t
 xlog_align(
-       xlog_t          *log,
+       struct xlog     *log,
        xfs_daddr_t     blk_no,
        int             nbblks,
-       xfs_buf_t       *bp)
+       struct xfs_buf  *bp)
 {
-       xfs_daddr_t     offset = 0;
-
-       if (log->l_sectBBsize)
-               offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1);
+       xfs_daddr_t     offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1);
 
-       ASSERT(BBTOB(offset + nbblks) <= XFS_BUF_SIZE(bp));
-       return XFS_BUF_PTR(bp) + BBTOB(offset);
+       ASSERT(offset + nbblks <= bp->b_length);
+       return bp->b_addr + BBTOB(offset);
 }
 
+
 /*
  * nbblks should be uint, but oh well.  Just want to catch that 32-bit length.
  */
 int
 xlog_bread_noalign(
-       xlog_t          *log,
+       struct xlog     *log,
        xfs_daddr_t     blk_no,
        int             nbblks,
-       xfs_buf_t       *bp)
+       struct xfs_buf  *bp)
 {
        if (!xlog_buf_bbcount_valid(log, nbblks)) {
-               xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+               xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
                        nbblks);
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
                return EFSCORRUPTED;
        }
 
-       if (log->l_sectBBsize > 1) {
-               blk_no = round_down(blk_no, log->l_sectBBsize);
-               nbblks = round_up(nbblks, log->l_sectBBsize);
-       }
+       blk_no = round_down(blk_no, log->l_sectBBsize);
+       nbblks = round_up(nbblks, log->l_sectBBsize);
 
        ASSERT(nbblks > 0);
        ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp));
 
        XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no);
        XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
+       bp->b_error = 0;
 
        return libxfs_readbufr(log->l_dev, XFS_BUF_ADDR(bp), bp, nbblks, 0);
 }
 
 int
 xlog_bread(
-       xlog_t          *log,
+       struct xlog     *log,
        xfs_daddr_t     blk_no,
        int             nbblks,
-       xfs_buf_t       *bp,
+       struct xfs_buf  *bp,
        xfs_caddr_t     *offset)
 {
        int             error;
@@ -155,6 +152,35 @@ xlog_bread(
 }
 
 /*
+ * Read at an offset into the buffer. Returns with the buffer in it's original
+ * state regardless of the result of the read.
+ */
+STATIC int
+xlog_bread_offset(
+       struct xlog     *log,
+       xfs_daddr_t     blk_no,         /* block to read from */
+       int             nbblks,         /* blocks to read */
+       struct xfs_buf  *bp,
+       xfs_caddr_t     offset)
+{
+       xfs_caddr_t     orig_offset = bp->b_addr;
+       int             orig_len = bp->b_bcount;
+       int             error, error2;
+
+       error = XFS_BUF_SET_PTR(bp, offset, BBTOB(nbblks));
+       if (error)
+               return error;
+
+       error = xlog_bread_noalign(log, blk_no, nbblks, bp);
+
+       /* must reset buffer pointer even on error */
+       error2 = XFS_BUF_SET_PTR(bp, orig_offset, orig_len);
+       if (error)
+               return error;
+       return error2;
+}
+
+/*
  * This routine finds (to an approximation) the first block in the physical
  * log which contains the given cycle.  It uses a binary search algorithm.
  * Note that the algorithm can not be perfect because the disk will not
@@ -162,8 +188,8 @@ xlog_bread(
  */
 int
 xlog_find_cycle_start(
-       xlog_t          *log,
-       xfs_buf_t       *bp,
+       struct xlog     *log,
+       struct xfs_buf  *bp,
        xfs_daddr_t     first_blk,
        xfs_daddr_t     *last_blk,
        uint            cycle)
@@ -205,7 +231,7 @@ xlog_find_cycle_start(
  */
 STATIC int
 xlog_find_verify_cycle(
-       xlog_t          *log,
+       struct xlog     *log,
        xfs_daddr_t     start_blk,
        int             nbblks,
        uint            stop_on_cycle_no,
@@ -225,9 +251,11 @@ xlog_find_verify_cycle(
         * a log sector, or we're out of luck.
         */
        bufblks = 1 << ffs(nbblks);
+       while (bufblks > log->l_logBBsize)
+               bufblks >>= 1;
        while (!(bp = xlog_get_bp(log, bufblks))) {
                bufblks >>= 1;
-               if (bufblks < MAX(log->l_sectBBsize, 1))
+               if (bufblks < log->l_sectBBsize)
                        return ENOMEM;
        }
 
@@ -272,7 +300,7 @@ out:
  */
 STATIC int
 xlog_find_verify_log_record(
-       xlog_t                  *log,
+       struct xlog             *log,
        xfs_daddr_t             start_blk,
        xfs_daddr_t             *last_blk,
        int                     extra_bblks)
@@ -302,8 +330,8 @@ xlog_find_verify_log_record(
        for (i = (*last_blk) - 1; i >= 0; i--) {
                if (i < start_blk) {
                        /* valid log record not found */
-                       xlog_warn(
-               "XFS: Log inconsistent (didn't find previous header)");
+                       xfs_warn(log->l_mp,
+               "Log inconsistent (didn't find previous header)");
                        ASSERT(0);
                        error = XFS_ERROR(EIO);
                        goto out;
@@ -317,7 +345,7 @@ xlog_find_verify_log_record(
 
                head = (xlog_rec_header_t *)offset;
 
-               if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(head->h_magicno))
+               if (head->h_magicno == cpu_to_be32(XLOG_HEADER_MAGIC_NUM))
                        break;
 
                if (!smallmem)
@@ -382,7 +410,7 @@ out:
  */
 STATIC int
 xlog_find_head(
-       xlog_t          *log,
+       struct xlog     *log,
        xfs_daddr_t     *return_head_blk)
 {
        xfs_buf_t       *bp;
@@ -403,12 +431,12 @@ xlog_find_head(
                         * mkfs etc write a dummy unmount record to a fresh
                         * log so we can store the uuid in there
                         */
-                       xlog_warn("XFS: totally zeroed log");
+                       xfs_warn(log->l_mp, "totally zeroed log");
                }
 
                return 0;
        } else if (error) {
-               xlog_warn("XFS: empty log check failed");
+               xfs_warn(log->l_mp, "empty log check failed");
                return error;
        }
 
@@ -631,7 +659,7 @@ validate_head:
        xlog_put_bp(bp);
 
        if (error)
-           xlog_warn("XFS: failed to find log head");
+               xfs_warn(log->l_mp, "failed to find log head");
        return error;
 }
 
@@ -653,7 +681,7 @@ validate_head:
  */
 int
 xlog_find_tail(
-       xlog_t                  *log,
+       struct xlog             *log,
        xfs_daddr_t             *head_blk,
        xfs_daddr_t             *tail_blk)
 {
@@ -699,7 +727,7 @@ xlog_find_tail(
                if (error)
                        goto done;
 
-               if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) {
+               if (*(__be32 *)offset == cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) {
                        found = 1;
                        break;
                }
@@ -716,15 +744,15 @@ xlog_find_tail(
                        if (error)
                                goto done;
 
-                       if (XLOG_HEADER_MAGIC_NUM ==
-                           be32_to_cpu(*(__be32 *)offset)) {
+                       if (*(__be32 *)offset ==
+                           cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) {
                                found = 2;
                                break;
                        }
                }
        }
        if (!found) {
-               xlog_warn("XFS: xlog_find_tail: couldn't find sync record");
+               xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__);
                ASSERT(0);
                return XFS_ERROR(EIO);
        }
@@ -750,9 +778,9 @@ xlog_find_tail(
                log->l_curr_cycle++;
        atomic64_set(&log->l_tail_lsn, be64_to_cpu(rhead->h_tail_lsn));
        atomic64_set(&log->l_last_sync_lsn, be64_to_cpu(rhead->h_lsn));
-       xlog_assign_grant_head(&log->l_grant_reserve_head, log->l_curr_cycle,
+       xlog_assign_grant_head(&log->l_reserve_head.grant, log->l_curr_cycle,
                                        BBTOB(log->l_curr_block));
-       xlog_assign_grant_head(&log->l_grant_write_head, log->l_curr_cycle,
+       xlog_assign_grant_head(&log->l_write_head.grant, log->l_curr_cycle,
                                        BBTOB(log->l_curr_block));
 
        /*
@@ -840,7 +868,7 @@ done:
        xlog_put_bp(bp);
 
        if (error)
-               xlog_warn("XFS: failed to locate log tail");
+               xfs_warn(log->l_mp, "failed to locate log tail");
        return error;
 }
 
@@ -862,7 +890,7 @@ done:
  */
 int
 xlog_find_zeroed(
-       xlog_t          *log,
+       struct xlog     *log,
        xfs_daddr_t     *blk_no)
 {
        xfs_buf_t       *bp;
@@ -904,7 +932,8 @@ xlog_find_zeroed(
                 * the first block must be 1. If it's not, maybe we're
                 * not looking at a log... Bail out.
                 */
-               xlog_warn("XFS: Log inconsistent or not a log (last==0, 
first!=1)");
+               xfs_warn(log->l_mp,
+                       "Log inconsistent or not a log (last==0, first!=1)");
                return XFS_ERROR(EINVAL);
        }
 
@@ -1002,8 +1031,8 @@ xlog_recover_add_item(
 
 STATIC int
 xlog_recover_add_to_cont_trans(
-       struct log              *log,
-       xlog_recover_t          *trans,
+       struct xlog             *log,
+       struct xlog_recover     *trans,
        xfs_caddr_t             dp,
        int                     len)
 {
@@ -1025,7 +1054,7 @@ xlog_recover_add_to_cont_trans(
        old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
        old_len = item->ri_buf[item->ri_cnt-1].i_len;
 
-       ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u);
+       ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP);
        memcpy(&ptr[old_len], dp, len); /* d, s, l */
        item->ri_buf[item->ri_cnt-1].i_len += len;
        item->ri_buf[item->ri_cnt-1].i_addr = ptr;
@@ -1048,8 +1077,8 @@ xlog_recover_add_to_cont_trans(
  */
 STATIC int
 xlog_recover_add_to_trans(
-       struct log              *log,
-       xlog_recover_t          *trans,
+       struct xlog             *log,
+       struct xlog_recover     *trans,
        xfs_caddr_t             dp,
        int                     len)
 {
@@ -1062,8 +1091,8 @@ xlog_recover_add_to_trans(
        if (list_empty(&trans->r_itemq)) {
                /* we need to catch log corruptions here */
                if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) {
-                       xlog_warn("XFS: xlog_recover_add_to_trans: "
-                                 "bad header magic number");
+                       xfs_warn(log->l_mp, "%s: bad header magic number",
+                               __func__);
                        ASSERT(0);
                        return XFS_ERROR(EIO);
                }
@@ -1090,8 +1119,8 @@ xlog_recover_add_to_trans(
        if (item->ri_total == 0) {              /* first region to be added */
                if (in_f->ilf_size == 0 ||
                    in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) {
-                       xlog_warn(
-       "XFS: bad number of regions (%d) in inode log format",
+                       xfs_warn(log->l_mp,
+               "bad number of regions (%d) in inode log format",
                                  in_f->ilf_size);
                        ASSERT(0);
                        return XFS_ERROR(EIO);
@@ -1144,7 +1173,7 @@ xlog_recover_free_trans(
  */
 STATIC int
 xlog_recover_commit_trans(
-       struct log              *log,
+       struct xlog             *log,
        struct xlog_recover     *trans,
        int                     pass)
 {
@@ -1163,7 +1192,7 @@ xlog_recover_unmount_trans(
        xlog_recover_t          *trans)
 {
        /* Do nothing now */
-       xlog_warn("XFS: xlog_recover_unmount_trans: Unmount LR");
+       xfs_warn(log->l_mp, "%s: Unmount LR", __func__);
        return 0;
 }
 
@@ -1178,9 +1207,9 @@ xlog_recover_unmount_trans(
  */
 STATIC int
 xlog_recover_process_data(
-       xlog_t                  *log,
+       struct xlog             *log,
        struct hlist_head       rhash[],
-       xlog_rec_header_t       *rhead,
+       struct xlog_rec_header  *rhead,
        xfs_caddr_t             dp,
        int                     pass)
 {
@@ -1206,8 +1235,8 @@ xlog_recover_process_data(
                dp += sizeof(xlog_op_header_t);
                if (ohead->oh_clientid != XFS_TRANSACTION &&
                    ohead->oh_clientid != XFS_LOG) {
-                       xlog_warn(
-               "XFS: xlog_recover_process_data: bad clientid");
+                       xfs_warn(log->l_mp, "%s: bad clientid 0x%x",
+                                       __func__, ohead->oh_clientid);
                        ASSERT(0);
                        return (XFS_ERROR(EIO));
                }
@@ -1220,8 +1249,8 @@ xlog_recover_process_data(
                                        be64_to_cpu(rhead->h_lsn));
                } else {
                        if (dp + be32_to_cpu(ohead->oh_len) > lp) {
-                               xlog_warn(
-                       "XFS: xlog_recover_process_data: bad length");
+                               xfs_warn(log->l_mp, "%s: bad length 0x%x",
+                                       __func__, be32_to_cpu(ohead->oh_len));
                                return (XFS_ERROR(EIO));
                        }
                        flags = ohead->oh_flags & ~XLOG_END_TRANS;
@@ -1241,8 +1270,8 @@ xlog_recover_process_data(
                                                be32_to_cpu(ohead->oh_len));
                                break;
                        case XLOG_START_TRANS:
-                               xlog_warn(
-                       "XFS: xlog_recover_process_data: bad transaction");
+                               xfs_warn(log->l_mp, "%s: bad transaction",
+                                       __func__);
                                ASSERT(0);
                                error = XFS_ERROR(EIO);
                                break;
@@ -1252,8 +1281,8 @@ xlog_recover_process_data(
                                                dp, be32_to_cpu(ohead->oh_len));
                                break;
                        default:
-                               xlog_warn(
-                       "XFS: xlog_recover_process_data: bad flag");
+                               xfs_warn(log->l_mp, "%s: bad flag 0x%x",
+                                       __func__, flags);
                                ASSERT(0);
                                error = XFS_ERROR(EIO);
                                break;
@@ -1267,13 +1296,64 @@ xlog_recover_process_data(
        return 0;
 }
 
-STATIC void
+/*
+ * Upack the log buffer data and crc check it. If the check fails, issue a
+ * warning if and only if the CRC in the header is non-zero. This makes the
+ * check an advisory warning, and the zero CRC check will prevent failure
+ * warnings from being emitted when upgrading the kernel from one that does not
+ * add CRCs by default.
+ *
+ * When filesystems are CRC enabled, this CRC mismatch becomes a fatal log
+ * corruption failure
+ *
+ * XXX: we cannot calculate the CRC here without knowing the number of extra
+ * headers taht were CRC'd in log write. This information is derived from the
+ * in-core log buffer size, and is not written to the log! Hence for now we
+ * simple *cannot* verify the CRCs, and so we short circuit it.
+ */
+#define xlog_cksum(l,r,dp,len) ((r)->h_crc)
+STATIC int
+xlog_unpack_data_crc(
+       struct xlog_rec_header  *rhead,
+       xfs_caddr_t             dp,
+       struct xlog             *log)
+{
+       __le32                  crc;
+
+       crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len));
+       if (crc != rhead->h_crc) {
+               if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+                       xfs_alert(log->l_mp,
+               "log record CRC mismatch: found 0x%x, expected 0x%x.\n",
+                                       le32_to_cpu(rhead->h_crc),
+                                       le32_to_cpu(crc));
+                       xfs_hex_dump(dp, 32);
+               }
+
+               /*
+                * If we've detected a log record corruption, then we can't
+                * recover past this point. Abort recovery if we are enforcing
+                * CRC protection by punting an error back up the stack.
+                */
+               if (xfs_sb_version_hascrc(&log->l_mp->m_sb))
+                       return EFSCORRUPTED;
+       }
+
+       return 0;
+}
+
+STATIC int
 xlog_unpack_data(
-       xlog_rec_header_t       *rhead,
+       struct xlog_rec_header  *rhead,
        xfs_caddr_t             dp,
-       xlog_t                  *log)
+       struct xlog             *log)
 {
        int                     i, j, k;
+       int                     error;
+
+       error = xlog_unpack_data_crc(rhead, dp, log);
+       if (error)
+               return error;
 
        for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
                  i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
@@ -1290,17 +1370,19 @@ xlog_unpack_data(
                        dp += BBSIZE;
                }
        }
+
+       return 0;
 }
 
 STATIC int
 xlog_valid_rec_header(
-       xlog_t                  *log,
-       xlog_rec_header_t       *rhead,
+       struct xlog             *log,
+       struct xlog_rec_header  *rhead,
        xfs_daddr_t             blkno)
 {
        int                     hlen;
 
-       if (unlikely(be32_to_cpu(rhead->h_magicno) != XLOG_HEADER_MAGIC_NUM)) {
+       if (unlikely(rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))) {
                XFS_ERROR_REPORT("xlog_valid_rec_header(1)",
                                XFS_ERRLEVEL_LOW, log->l_mp);
                return XFS_ERROR(EFSCORRUPTED);
@@ -1308,7 +1390,7 @@ xlog_valid_rec_header(
        if (unlikely(
            (!rhead->h_version ||
            (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
-               xlog_warn("XFS: %s: unrecognised log version (%d).",
+               xfs_warn(log->l_mp, "%s: unrecognised log version (%d).",
                        __func__, be32_to_cpu(rhead->h_version));
                return XFS_ERROR(EIO);
        }
@@ -1338,7 +1420,7 @@ xlog_valid_rec_header(
  */
 int
 xlog_do_recovery_pass(
-       xlog_t                  *log,
+       struct xlog             *log,
        xfs_daddr_t             head_blk,
        xfs_daddr_t             tail_blk,
        int                     pass)
@@ -1421,9 +1503,13 @@ xlog_do_recovery_pass(
                        if (error)
                                goto bread_err2;
 
-                       xlog_unpack_data(rhead, offset, log);
-                       if ((error = xlog_recover_process_data(log,
-                                               rhash, rhead, offset, pass)))
+                       error = xlog_unpack_data(rhead, offset, log);
+                       if (error)
+                               goto bread_err2;
+
+                       error = xlog_recover_process_data(log,
+                                               rhash, rhead, offset, pass);
+                       if (error)
                                goto bread_err2;
                        blk_no += bblks + hblks;
                }
@@ -1438,7 +1524,7 @@ xlog_do_recovery_pass(
                        /*
                         * Check for header wrapping around physical end-of-log
                         */
-                       offset = XFS_BUF_PTR(hbp);
+                       offset = hbp->b_addr;
                        split_hblks = 0;
                        wrapped_hblks = 0;
                        if (blk_no + hblks <= log->l_logBBsize) {
@@ -1474,19 +1560,9 @@ xlog_do_recovery_pass(
                                 *   - order is important.
                                 */
                                wrapped_hblks = hblks - split_hblks;
-                               error = XFS_BUF_SET_PTR(hbp,
-                                               offset + BBTOB(split_hblks),
-                                               BBTOB(hblks - split_hblks));
-                               if (error)
-                                       goto bread_err2;
-
-                               error = xlog_bread_noalign(log, 0,
-                                                          wrapped_hblks, hbp);
-                               if (error)
-                                       goto bread_err2;
-
-                               error = XFS_BUF_SET_PTR(hbp, offset,
-                                                       BBTOB(hblks));
+                               error = xlog_bread_offset(log, 0,
+                                               wrapped_hblks, hbp,
+                                               offset + BBTOB(split_hblks));
                                if (error)
                                        goto bread_err2;
                        }
@@ -1508,7 +1584,7 @@ xlog_do_recovery_pass(
                        } else {
                                /* This log record is split across the
                                 * physical end of log */
-                               offset = XFS_BUF_PTR(dbp);
+                               offset = dbp->b_addr;
                                split_bblks = 0;
                                if (blk_no != log->l_logBBsize) {
                                        /* some data is before the physical
@@ -1537,25 +1613,20 @@ xlog_do_recovery_pass(
                                 *   _first_, then the log start (LR header end)
                                 *   - order is important.
                                 */
-                               error = XFS_BUF_SET_PTR(dbp,
-                                               offset + BBTOB(split_bblks),
-                                               BBTOB(bblks - split_bblks));
+                               error = xlog_bread_offset(log, 0,
+                                               bblks - split_bblks, dbp,
+                                               offset + BBTOB(split_bblks));
                                if (error)
                                        goto bread_err2;
+                       }
 
-                               error = xlog_bread_noalign(log, wrapped_hblks,
-                                               bblks - split_bblks,
-                                               dbp);
-                               if (error)
-                                       goto bread_err2;
+                       error = xlog_unpack_data(rhead, offset, log);
+                       if (error)
+                               goto bread_err2;
 
-                               error = XFS_BUF_SET_PTR(dbp, offset, h_size);
-                               if (error)
-                                       goto bread_err2;
-                       }
-                       xlog_unpack_data(rhead, offset, log);
-                       if ((error = xlog_recover_process_data(log, rhash,
-                                                       rhead, offset, pass)))
+                       error = xlog_recover_process_data(log, rhash,
+                                                       rhead, offset, pass);
+                       if (error)
                                goto bread_err2;
                        blk_no += bblks;
                }
@@ -1580,9 +1651,13 @@ xlog_do_recovery_pass(
                        if (error)
                                goto bread_err2;
 
-                       xlog_unpack_data(rhead, offset, log);
-                       if ((error = xlog_recover_process_data(log, rhash,
-                                                       rhead, offset, pass)))
+                       error = xlog_unpack_data(rhead, offset, log);
+                       if (error)
+                               goto bread_err2;
+
+                       error = xlog_recover_process_data(log, rhash,
+                                                       rhead, offset, pass);
+                       if (error)
                                goto bread_err2;
                        blk_no += bblks + hblks;
                }
diff --git a/logprint/log_copy.c b/logprint/log_copy.c
index fd36317..f6ef0e9 100644
--- a/logprint/log_copy.c
+++ b/logprint/log_copy.c
@@ -24,7 +24,7 @@
 
 void
 xfs_log_copy(
-       xlog_t          *log,
+       struct xlog     *log,
        int             fd,
        char            *filename)
 {
diff --git a/logprint/log_dump.c b/logprint/log_dump.c
index 1975b1b..a333077 100644
--- a/logprint/log_dump.c
+++ b/logprint/log_dump.c
@@ -24,7 +24,7 @@
 
 void
 xfs_log_dump(
-       xlog_t                  *log,
+       struct xlog             *log,
        int                     fd,
        int                     print_block_start)
 {
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index c480795..4277a48 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -816,7 +816,7 @@ xlog_print_trans_dquot(xfs_caddr_t *ptr, int len, int *i, 
int num_ops)
  */
 
 void
-xlog_print_lseek(xlog_t *log, int fd, xfs_daddr_t blkno, int whence)
+xlog_print_lseek(struct xlog *log, int fd, xfs_daddr_t blkno, int whence)
 {
 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
        xfs_off_t offset;
@@ -1265,7 +1265,7 @@ xlog_print_extended_headers(
 /*
  * This code is gross and needs to be rewritten.
  */
-void xfs_log_print(xlog_t       *log,
+void xfs_log_print(struct xlog  *log,
                   int          fd,
                   int          print_block_start)
 {
diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c
index cbc51d9..44fb4c4 100644
--- a/logprint/log_print_all.c
+++ b/logprint/log_print_all.c
@@ -23,7 +23,7 @@
  */
 int
 xlog_print_find_oldest(
-       struct log      *log,
+       struct xlog     *log,
        xfs_daddr_t     *last_blk)
 {
        xfs_buf_t       *bp;
diff --git a/logprint/log_print_trans.c b/logprint/log_print_trans.c
index 7405772..86e1c42 100644
--- a/logprint/log_print_trans.c
+++ b/logprint/log_print_trans.c
@@ -30,7 +30,7 @@ xlog_recover_print_trans_head(
 
 int
 xlog_recover_do_trans(
-       xlog_t          *log,
+       struct xlog     *log,
        xlog_recover_t  *trans,
        int             pass)
 {
@@ -40,7 +40,7 @@ xlog_recover_do_trans(
 
 void
 xfs_log_print_trans(
-       xlog_t          *log,
+       struct xlog     *log,
        int             print_block_start)
 {
        xfs_daddr_t     head_blk, tail_blk;
diff --git a/logprint/logprint.c b/logprint/logprint.c
index 482fd4e..2a01780 100644
--- a/logprint/logprint.c
+++ b/logprint/logprint.c
@@ -128,7 +128,7 @@ main(int argc, char **argv)
        int             c;
        int             logfd;
        char            *copy_file = NULL;
-       xlog_t          log = {0};
+       struct xlog     log = {0};
        xfs_mount_t     mount;
 
        setlocale(LC_ALL, "");
diff --git a/logprint/logprint.h b/logprint/logprint.h
index df4cea3..933c9e6 100644
--- a/logprint/logprint.h
+++ b/logprint/logprint.h
@@ -34,12 +34,12 @@ extern int  print_no_print;
 /* exports */
 extern char *trans_type[];
 
-extern void xlog_print_lseek(xlog_t *, int, xfs_daddr_t, int);
+extern void xlog_print_lseek(struct xlog *, int, xfs_daddr_t, int);
 
-extern void xfs_log_copy(xlog_t *, int, char *);
-extern void xfs_log_dump(xlog_t *, int, int);
-extern void xfs_log_print(xlog_t *, int, int);
-extern void xfs_log_print_trans(xlog_t *, int);
+extern void xfs_log_copy(struct xlog *, int, char *);
+extern void xfs_log_dump(struct xlog *, int, int);
+extern void xfs_log_print(struct xlog *, int, int);
+extern void xfs_log_print_trans(struct xlog *, int);
 
 extern void print_xlog_record_line(void);
 extern void print_xlog_op_line(void);
diff --git a/repair/phase2.c b/repair/phase2.c
index 9fd591c..23b457a 100644
--- a/repair/phase2.c
+++ b/repair/phase2.c
@@ -29,13 +29,16 @@
 void   set_mp(xfs_mount_t *mpp);
 
 /* workaround craziness in the xlog routines */
-int xlog_recover_do_trans(xlog_t *log, xlog_recover_t *t, int p) { return 0; }
+int xlog_recover_do_trans(struct xlog *log, xlog_recover_t *t, int p)
+{
+       return 0;
+}
 
 static void
 zero_log(xfs_mount_t *mp)
 {
        int error;
-       xlog_t  log;
+       struct xlog     log;
        xfs_daddr_t head_blk, tail_blk;
        dev_t logdev = (mp->m_sb.sb_logstart == 0) ? x.logdev : x.ddev;
 
-- 
1.7.10

<Prev in Thread] Current Thread [Next in Thread>