]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfsprogs: updata libxlog to current kernel code
authorDave Chinner <dchinner@redhat.com>
Thu, 9 May 2013 13:19:06 +0000 (08:19 -0500)
committerRich Johnston <rjohnston@sgi.com>
Thu, 9 May 2013 13:19:06 +0000 (08:19 -0500)
Update the libxlog log recovery code to match the current 3.8-rc2
kernel code and ensure all the callers work correctly.

Note: while this introduces CRC validation infrastructure, it is
currently short-circuited as it is not clear what to do with log
buffers that fail CRC checking. We're only reading the log to
determine it is clean/dirty or dumping the contents for analysis, so
it's not clear what to do with CRC validation errors yet, or even
if there is any commonality with the kernel handling. This will need
to be revisited as the situation clarifies.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Rich Johnston <rjohnston@sgi.com>
db/sb.c
include/libxlog.h
libxlog/xfs_log_recover.c
logprint/log_copy.c
logprint/log_dump.c
logprint/log_misc.c
logprint/log_print_all.c
logprint/log_print_trans.c
logprint/logprint.c
logprint/logprint.h
repair/phase2.c

diff --git a/db/sb.c b/db/sb.c
index 21f38c5486dcd8841d7db4afa40c200986cafa15..4da1f6a60921278913a9a1ac0c1fcdfa46eb7518 100644 (file)
--- 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) {
@@ -232,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)) {
index d1142ab010b9714af96509dcba0d24ef0a6067a3..36ede5992343140aed56c53616ead963523ed905 100644 (file)
@@ -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);
index 23fe6fd544afc62e9804d669adfca3df66a42d79..7f5a41c67ae8b4495c9e50861f1cde7993334808 100644 (file)
 
 #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); \
+       (0); \
+})
+
 
 /*
  * Verify the given count of basic blocks is valid number of blocks
@@ -31,7 +35,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 +48,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 +61,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 +72,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 +94,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;
@@ -154,6 +154,35 @@ xlog_bread(
        return 0;
 }
 
+/*
+ * 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.
@@ -162,8 +191,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 +234,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 +254,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 +303,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 +333,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 +348,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 +413,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 +434,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 +662,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 +684,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 +730,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 +747,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 +781,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 +871,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 +893,7 @@ done:
  */
 int
 xlog_find_zeroed(
-       xlog_t          *log,
+       struct xlog     *log,
        xfs_daddr_t     *blk_no)
 {
        xfs_buf_t       *bp;
@@ -904,7 +935,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 +1034,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 +1057,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 +1080,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 +1094,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 +1122,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 +1176,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 +1195,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 +1210,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 +1238,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 +1252,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 +1273,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 +1284,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 +1299,62 @@ 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 do not calculate the CRC here yet. It's not clear what we should do
+ * with CRC errors here in userspace, so we'll address that problem later on.
+ */
+#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 +1371,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 +1391,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 +1421,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 +1504,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 +1525,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 +1561,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 +1585,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 +1614,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 +1652,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;
                }
index fd363173b49c8201d0135f1866df28b715e92b7f..f6ef0e91b7ff7406f9e06ba72897ceb62ce821a0 100644 (file)
@@ -24,7 +24,7 @@
 
 void
 xfs_log_copy(
-       xlog_t          *log,
+       struct xlog     *log,
        int             fd,
        char            *filename)
 {
index 1975b1b30c997382ca2670b13e200aea4afa4775..a333077cc70d00b85884ae8afabb3a8fa3bd5e29 100644 (file)
@@ -24,7 +24,7 @@
 
 void
 xfs_log_dump(
-       xlog_t                  *log,
+       struct xlog             *log,
        int                     fd,
        int                     print_block_start)
 {
index 567cdf22558b27ef999dbafc17b25ae8318b192f..30b7ea635f147e23178fdd52a3b39aa5918de64e 100644 (file)
@@ -794,7 +794,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;
@@ -1245,7 +1245,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)
 {
index 8f1c8abe74ff7bc004b583562111a1477173fae6..dfd76b7c598b0ddca4ea5ea3881dcdd9a1c749d3 100644 (file)
@@ -23,7 +23,7 @@
  */
 int
 xlog_print_find_oldest(
-       struct log      *log,
+       struct xlog     *log,
        xfs_daddr_t     *last_blk)
 {
        xfs_buf_t       *bp;
index 7405772f950621e2e6baaf5da16715b2127fa29c..86e1c4243b6fc8cc56a565c34d8b8c56d7896a8d 100644 (file)
@@ -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;
index 0923b0aa09767c2782d685f331069f64064886de..3fbcdba45265b030cffd0b150d3311057725183d 100644 (file)
@@ -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;
        }
 
 
@@ -129,7 +134,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, "");
@@ -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) {
index df4cea3743199135766a2b51e08a48d0cb2c4ef4..933c9e6d2ce22550618f554caf38204c69cc7171 100644 (file)
@@ -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);
index 9fd591c1df7fc3e3d9bb8aa94b2e7b74f47aefeb..382cd7b99717b78655ac669dcad404720bca31fb 100644 (file)
 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;
 
@@ -44,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;