Merge branch 'hwpoison' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux...
[safe/jmp/linux-2.6] / fs / xfs / xfs_log_recover.c
index 6326898..1099395 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
-#include "xfs_imap.h"
 #include "xfs_alloc.h"
 #include "xfs_ialloc.h"
 #include "xfs_log_priv.h"
@@ -48,6 +45,7 @@
 #include "xfs_trans_priv.h"
 #include "xfs_quota.h"
 #include "xfs_rw.h"
+#include "xfs_utils.h"
 
 STATIC int     xlog_find_zeroed(xlog_t *, xfs_daddr_t *);
 STATIC int     xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t);
@@ -55,10 +53,8 @@ STATIC void  xlog_recover_insert_item_backq(xlog_recover_item_t **q,
                                               xlog_recover_item_t *item);
 #if defined(DEBUG)
 STATIC void    xlog_recover_check_summary(xlog_t *);
-STATIC void    xlog_recover_check_ail(xfs_mount_t *, xfs_log_item_t *, int);
 #else
 #define        xlog_recover_check_summary(log)
-#define        xlog_recover_check_ail(mp, lip, gen)
 #endif
 
 
@@ -74,16 +70,21 @@ STATIC void xlog_recover_check_ail(xfs_mount_t *, xfs_log_item_t *, int);
 xfs_buf_t *
 xlog_get_bp(
        xlog_t          *log,
-       int             num_bblks)
+       int             nbblks)
 {
-       ASSERT(num_bblks > 0);
+       if (nbblks <= 0 || nbblks > log->l_logBBsize) {
+               xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks);
+               XFS_ERROR_REPORT("xlog_get_bp(1)",
+                                XFS_ERRLEVEL_HIGH, log->l_mp);
+               return NULL;
+       }
 
        if (log->l_sectbb_log) {
-               if (num_bblks > 1)
-                       num_bblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1);
-               num_bblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, num_bblks);
+               if (nbblks > 1)
+                       nbblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1);
+               nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
        }
-       return xfs_buf_get_noaddr(BBTOB(num_bblks), log->l_mp->m_logdev_targp);
+       return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp);
 }
 
 void
@@ -93,12 +94,30 @@ xlog_put_bp(
        xfs_buf_free(bp);
 }
 
+STATIC xfs_caddr_t
+xlog_align(
+       xlog_t          *log,
+       xfs_daddr_t     blk_no,
+       int             nbblks,
+       xfs_buf_t       *bp)
+{
+       xfs_caddr_t     ptr;
+
+       if (!log->l_sectbb_log)
+               return XFS_BUF_PTR(bp);
+
+       ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
+       ASSERT(XFS_BUF_SIZE(bp) >=
+               BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
+       return ptr;
+}
+
 
 /*
  * nbblks should be uint, but oh well.  Just want to catch that 32-bit length.
  */
-int
-xlog_bread(
+STATIC int
+xlog_bread_noalign(
        xlog_t          *log,
        xfs_daddr_t     blk_no,
        int             nbblks,
@@ -106,6 +125,13 @@ xlog_bread(
 {
        int             error;
 
+       if (nbblks <= 0 || nbblks > log->l_logBBsize) {
+               xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks);
+               XFS_ERROR_REPORT("xlog_bread(1)",
+                                XFS_ERRLEVEL_HIGH, log->l_mp);
+               return EFSCORRUPTED;
+       }
+
        if (log->l_sectbb_log) {
                blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no);
                nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
@@ -122,12 +148,31 @@ xlog_bread(
        XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
 
        xfsbdstrat(log->l_mp, bp);
-       if ((error = xfs_iowait(bp)))
+       error = xfs_iowait(bp);
+       if (error)
                xfs_ioerror_alert("xlog_bread", log->l_mp,
                                  bp, XFS_BUF_ADDR(bp));
        return error;
 }
 
+STATIC int
+xlog_bread(
+       xlog_t          *log,
+       xfs_daddr_t     blk_no,
+       int             nbblks,
+       xfs_buf_t       *bp,
+       xfs_caddr_t     *offset)
+{
+       int             error;
+
+       error = xlog_bread_noalign(log, blk_no, nbblks, bp);
+       if (error)
+               return error;
+
+       *offset = xlog_align(log, blk_no, nbblks, bp);
+       return 0;
+}
+
 /*
  * Write out the buffer at the given block for the given number of blocks.
  * The buffer is kept locked across the write and is returned locked.
@@ -142,6 +187,13 @@ xlog_bwrite(
 {
        int             error;
 
+       if (nbblks <= 0 || nbblks > log->l_logBBsize) {
+               xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks);
+               XFS_ERROR_REPORT("xlog_bwrite(1)",
+                                XFS_ERRLEVEL_HIGH, log->l_mp);
+               return EFSCORRUPTED;
+       }
+
        if (log->l_sectbb_log) {
                blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no);
                nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
@@ -164,24 +216,6 @@ xlog_bwrite(
        return error;
 }
 
-STATIC xfs_caddr_t
-xlog_align(
-       xlog_t          *log,
-       xfs_daddr_t     blk_no,
-       int             nbblks,
-       xfs_buf_t       *bp)
-{
-       xfs_caddr_t     ptr;
-
-       if (!log->l_sectbb_log)
-               return XFS_BUF_PTR(bp);
-
-       ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
-       ASSERT(XFS_BUF_SIZE(bp) >=
-               BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
-       return ptr;
-}
-
 #ifdef DEBUG
 /*
  * dump debug superblock and log record information
@@ -193,14 +227,14 @@ xlog_header_check_dump(
 {
        int                     b;
 
-       printk("%s:  SB : uuid = ", __FUNCTION__);
+       cmn_err(CE_DEBUG, "%s:  SB : uuid = ", __func__);
        for (b = 0; b < 16; b++)
-               printk("%02x",((unsigned char *)&mp->m_sb.sb_uuid)[b]);
-       printk(", fmt = %d\n", XLOG_FMT);
-       printk("    log : uuid = ");
+               cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&mp->m_sb.sb_uuid)[b]);
+       cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT);
+       cmn_err(CE_DEBUG, "    log : uuid = ");
        for (b = 0; b < 16; b++)
-               printk("%02x",((unsigned char *)&head->h_fs_uuid)[b]);
-       printk(", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT));
+               cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&head->h_fs_uuid)[b]);
+       cmn_err(CE_DEBUG, ", fmt = %d\n", be32_to_cpu(head->h_fmt));
 }
 #else
 #define xlog_header_check_dump(mp, head)
@@ -214,14 +248,14 @@ xlog_header_check_recover(
        xfs_mount_t             *mp,
        xlog_rec_header_t       *head)
 {
-       ASSERT(INT_GET(head->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
+       ASSERT(be32_to_cpu(head->h_magicno) == XLOG_HEADER_MAGIC_NUM);
 
        /*
         * IRIX doesn't write the h_fmt field and leaves it zeroed
         * (XLOG_FMT_UNKNOWN). This stops us from trying to recover
         * a dirty log created in IRIX.
         */
-       if (unlikely(INT_GET(head->h_fmt, ARCH_CONVERT) != XLOG_FMT)) {
+       if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) {
                xlog_warn(
        "XFS: dirty log written in incompatible format - can't recover");
                xlog_header_check_dump(mp, head);
@@ -247,7 +281,7 @@ xlog_header_check_mount(
        xfs_mount_t             *mp,
        xlog_rec_header_t       *head)
 {
-       ASSERT(INT_GET(head->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
+       ASSERT(be32_to_cpu(head->h_magicno) == XLOG_HEADER_MAGIC_NUM);
 
        if (uuid_is_nil(&head->h_fs_uuid)) {
                /*
@@ -270,21 +304,16 @@ STATIC void
 xlog_recover_iodone(
        struct xfs_buf  *bp)
 {
-       xfs_mount_t     *mp;
-
-       ASSERT(XFS_BUF_FSPRIVATE(bp, void *));
-
        if (XFS_BUF_GETERROR(bp)) {
                /*
                 * We're not going to bother about retrying
                 * this during recovery. One strike!
                 */
-               mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *);
                xfs_ioerror_alert("xlog_recover_iodone",
-                                 mp, bp, XFS_BUF_ADDR(bp));
-               xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
+                                 bp->b_mount, bp, XFS_BUF_ADDR(bp));
+               xfs_force_shutdown(bp->b_mount, SHUTDOWN_META_IO_ERROR);
        }
-       XFS_BUF_SET_FSPRIVATE(bp, NULL);
+       bp->b_mount = NULL;
        XFS_BUF_CLR_IODONE_FUNC(bp);
        xfs_biodone(bp);
 }
@@ -295,7 +324,7 @@ xlog_recover_iodone(
  * Note that the algorithm can not be perfect because the disk will not
  * necessarily be perfect.
  */
-int
+STATIC int
 xlog_find_cycle_start(
        xlog_t          *log,
        xfs_buf_t       *bp,
@@ -310,10 +339,10 @@ xlog_find_cycle_start(
 
        mid_blk = BLK_AVG(first_blk, *last_blk);
        while (mid_blk != first_blk && mid_blk != *last_blk) {
-               if ((error = xlog_bread(log, mid_blk, 1, bp)))
+               error = xlog_bread(log, mid_blk, 1, bp, &offset);
+               if (error)
                        return error;
-               offset = xlog_align(log, mid_blk, 1, bp);
-               mid_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+               mid_cycle = xlog_get_cycle(offset);
                if (mid_cycle == cycle) {
                        *last_blk = mid_blk;
                        /* last_half_cycle == mid_cycle */
@@ -368,12 +397,12 @@ xlog_find_verify_cycle(
 
                bcount = min(bufblks, (start_blk + nbblks - i));
 
-               if ((error = xlog_bread(log, i, bcount, bp)))
+               error = xlog_bread(log, i, bcount, bp, &buf);
+               if (error)
                        goto out;
 
-               buf = xlog_align(log, i, bcount, bp);
                for (j = 0; j < bcount; j++) {
-                       cycle = GET_CYCLE(buf, ARCH_CONVERT);
+                       cycle = xlog_get_cycle(buf);
                        if (cycle == stop_on_cycle_no) {
                                *new_blk = i+j;
                                goto out;
@@ -425,9 +454,9 @@ xlog_find_verify_log_record(
                        return ENOMEM;
                smallmem = 1;
        } else {
-               if ((error = xlog_bread(log, start_blk, num_blks, bp)))
+               error = xlog_bread(log, start_blk, num_blks, bp, &offset);
+               if (error)
                        goto out;
-               offset = xlog_align(log, start_blk, num_blks, bp);
                offset += ((num_blks - 1) << BBSHIFT);
        }
 
@@ -442,15 +471,14 @@ xlog_find_verify_log_record(
                }
 
                if (smallmem) {
-                       if ((error = xlog_bread(log, i, 1, bp)))
+                       error = xlog_bread(log, i, 1, bp, &offset);
+                       if (error)
                                goto out;
-                       offset = xlog_align(log, i, 1, bp);
                }
 
                head = (xlog_rec_header_t *)offset;
 
-               if (XLOG_HEADER_MAGIC_NUM ==
-                   INT_GET(head->h_magicno, ARCH_CONVERT))
+               if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(head->h_magicno))
                        break;
 
                if (!smallmem)
@@ -481,8 +509,8 @@ xlog_find_verify_log_record(
         * reset last_blk.  Only when last_blk points in the middle of a log
         * record do we update last_blk.
         */
-       if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-               uint    h_size = INT_GET(head->h_size, ARCH_CONVERT);
+       if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+               uint    h_size = be32_to_cpu(head->h_size);
 
                xhdrs = h_size / XLOG_HEADER_CYCLE_SIZE;
                if (h_size % XLOG_HEADER_CYCLE_SIZE)
@@ -491,8 +519,8 @@ xlog_find_verify_log_record(
                xhdrs = 1;
        }
 
-       if (*last_blk - i + extra_bblks
-                       != BTOBB(INT_GET(head->h_len, ARCH_CONVERT)) + xhdrs)
+       if (*last_blk - i + extra_bblks !=
+           BTOBB(be32_to_cpu(head->h_len)) + xhdrs)
                *last_blk = i;
 
 out:
@@ -549,16 +577,19 @@ xlog_find_head(
        bp = xlog_get_bp(log, 1);
        if (!bp)
                return ENOMEM;
-       if ((error = xlog_bread(log, 0, 1, bp)))
+
+       error = xlog_bread(log, 0, 1, bp, &offset);
+       if (error)
                goto bp_err;
-       offset = xlog_align(log, 0, 1, bp);
-       first_half_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+
+       first_half_cycle = xlog_get_cycle(offset);
 
        last_blk = head_blk = log_bbnum - 1;    /* get cycle # of last block */
-       if ((error = xlog_bread(log, last_blk, 1, bp)))
+       error = xlog_bread(log, last_blk, 1, bp, &offset);
+       if (error)
                goto bp_err;
-       offset = xlog_align(log, last_blk, 1, bp);
-       last_half_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+
+       last_half_cycle = xlog_get_cycle(offset);
        ASSERT(last_half_cycle != 0);
 
        /*
@@ -583,7 +614,7 @@ xlog_find_head(
                 *        x | x ... | x - 1 | x
                 * Another case that fits this picture would be
                 *        x | x + 1 | x ... | x
-                * In this case the head really is somwhere at the end of the
+                * In this case the head really is somewhere at the end of the
                 * log, as one of the latest writes at the beginning was
                 * incomplete.
                 * One more case is
@@ -783,8 +814,7 @@ int
 xlog_find_tail(
        xlog_t                  *log,
        xfs_daddr_t             *head_blk,
-       xfs_daddr_t             *tail_blk,
-       int                     readonly)
+       xfs_daddr_t             *tail_blk)
 {
        xlog_rec_header_t       *rhead;
        xlog_op_header_t        *op_head;
@@ -808,10 +838,11 @@ xlog_find_tail(
        if (!bp)
                return ENOMEM;
        if (*head_blk == 0) {                           /* special case */
-               if ((error = xlog_bread(log, 0, 1, bp)))
+               error = xlog_bread(log, 0, 1, bp, &offset);
+               if (error)
                        goto bread_err;
-               offset = xlog_align(log, 0, 1, bp);
-               if (GET_CYCLE(offset, ARCH_CONVERT) == 0) {
+
+               if (xlog_get_cycle(offset) == 0) {
                        *tail_blk = 0;
                        /* leave all other log inited values alone */
                        goto exit;
@@ -823,11 +854,11 @@ xlog_find_tail(
         */
        ASSERT(*head_blk < INT_MAX);
        for (i = (int)(*head_blk) - 1; i >= 0; i--) {
-               if ((error = xlog_bread(log, i, 1, bp)))
+               error = xlog_bread(log, i, 1, bp, &offset);
+               if (error)
                        goto bread_err;
-               offset = xlog_align(log, i, 1, bp);
-               if (XLOG_HEADER_MAGIC_NUM ==
-                   INT_GET(*(uint *)offset, ARCH_CONVERT)) {
+
+               if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) {
                        found = 1;
                        break;
                }
@@ -840,11 +871,12 @@ xlog_find_tail(
         */
        if (!found) {
                for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) {
-                       if ((error = xlog_bread(log, i, 1, bp)))
+                       error = xlog_bread(log, i, 1, bp, &offset);
+                       if (error)
                                goto bread_err;
-                       offset = xlog_align(log, i, 1, bp);
+
                        if (XLOG_HEADER_MAGIC_NUM ==
-                           INT_GET(*(uint*)offset, ARCH_CONVERT)) {
+                           be32_to_cpu(*(__be32 *)offset)) {
                                found = 2;
                                break;
                        }
@@ -858,7 +890,7 @@ xlog_find_tail(
 
        /* find blk_no of tail of log */
        rhead = (xlog_rec_header_t *)offset;
-       *tail_blk = BLOCK_LSN(INT_GET(rhead->h_tail_lsn, ARCH_CONVERT));
+       *tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn));
 
        /*
         * Reset log values according to the state of the log when we
@@ -872,11 +904,11 @@ xlog_find_tail(
         */
        log->l_prev_block = i;
        log->l_curr_block = (int)*head_blk;
-       log->l_curr_cycle = INT_GET(rhead->h_cycle, ARCH_CONVERT);
+       log->l_curr_cycle = be32_to_cpu(rhead->h_cycle);
        if (found == 2)
                log->l_curr_cycle++;
-       log->l_tail_lsn = INT_GET(rhead->h_tail_lsn, ARCH_CONVERT);
-       log->l_last_sync_lsn = INT_GET(rhead->h_lsn, ARCH_CONVERT);
+       log->l_tail_lsn = be64_to_cpu(rhead->h_tail_lsn);
+       log->l_last_sync_lsn = be64_to_cpu(rhead->h_lsn);
        log->l_grant_reserve_cycle = log->l_curr_cycle;
        log->l_grant_reserve_bytes = BBTOB(log->l_curr_block);
        log->l_grant_write_cycle = log->l_curr_cycle;
@@ -893,9 +925,9 @@ xlog_find_tail(
         * unmount record if there is one, so we pass the lsn of the
         * unmount record rather than the block after it.
         */
-       if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-               int     h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
-               int     h_version = INT_GET(rhead->h_version, ARCH_CONVERT);
+       if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+               int     h_size = be32_to_cpu(rhead->h_size);
+               int     h_version = be32_to_cpu(rhead->h_version);
 
                if ((h_version & XLOG_VERSION_2) &&
                    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
@@ -909,15 +941,15 @@ xlog_find_tail(
                hblks = 1;
        }
        after_umount_blk = (i + hblks + (int)
-               BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT))) % log->l_logBBsize;
+               BTOBB(be32_to_cpu(rhead->h_len))) % log->l_logBBsize;
        tail_lsn = log->l_tail_lsn;
        if (*head_blk == after_umount_blk &&
-           INT_GET(rhead->h_num_logops, ARCH_CONVERT) == 1) {
+           be32_to_cpu(rhead->h_num_logops) == 1) {
                umount_data_blk = (i + hblks) % log->l_logBBsize;
-               if ((error = xlog_bread(log, umount_data_blk, 1, bp))) {
+               error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
+               if (error)
                        goto bread_err;
-               }
-               offset = xlog_align(log, umount_data_blk, 1, bp);
+
                op_head = (xlog_op_header_t *)offset;
                if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) {
                        /*
@@ -925,11 +957,21 @@ xlog_find_tail(
                         * log records will point recovery to after the
                         * current unmount record.
                         */
-                       ASSIGN_ANY_LSN_HOST(log->l_tail_lsn, log->l_curr_cycle,
-                                       after_umount_blk);
-                       ASSIGN_ANY_LSN_HOST(log->l_last_sync_lsn, log->l_curr_cycle,
-                                       after_umount_blk);
+                       log->l_tail_lsn =
+                               xlog_assign_lsn(log->l_curr_cycle,
+                                               after_umount_blk);
+                       log->l_last_sync_lsn =
+                               xlog_assign_lsn(log->l_curr_cycle,
+                                               after_umount_blk);
                        *tail_blk = after_umount_blk;
+
+                       /*
+                        * Note that the unmount was clean. If the unmount
+                        * was not clean, we need to know this to rebuild the
+                        * superblock counters from the perag headers if we
+                        * have a filesystem using non-persistent counters.
+                        */
+                       log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN;
                }
        }
 
@@ -981,7 +1023,7 @@ exit:
  *     -1 => use *blk_no as the first block of the log
  *     >0 => error has occurred
  */
-int
+STATIC int
 xlog_find_zeroed(
        xlog_t          *log,
        xfs_daddr_t     *blk_no)
@@ -993,14 +1035,17 @@ xlog_find_zeroed(
        xfs_daddr_t     num_scan_bblks;
        int             error, log_bbnum = log->l_logBBsize;
 
+       *blk_no = 0;
+
        /* check totally zeroed log */
        bp = xlog_get_bp(log, 1);
        if (!bp)
                return ENOMEM;
-       if ((error = xlog_bread(log, 0, 1, bp)))
+       error = xlog_bread(log, 0, 1, bp, &offset);
+       if (error)
                goto bp_err;
-       offset = xlog_align(log, 0, 1, bp);
-       first_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+
+       first_cycle = xlog_get_cycle(offset);
        if (first_cycle == 0) {         /* completely zeroed log */
                *blk_no = 0;
                xlog_put_bp(bp);
@@ -1008,10 +1053,11 @@ xlog_find_zeroed(
        }
 
        /* check partially zeroed log */
-       if ((error = xlog_bread(log, log_bbnum-1, 1, bp)))
+       error = xlog_bread(log, log_bbnum-1, 1, bp, &offset);
+       if (error)
                goto bp_err;
-       offset = xlog_align(log, log_bbnum-1, 1, bp);
-       last_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+
+       last_cycle = xlog_get_cycle(offset);
        if (last_cycle != 0) {          /* log completely written to */
                xlog_put_bp(bp);
                return 0;
@@ -1091,13 +1137,13 @@ xlog_add_record(
        xlog_rec_header_t       *recp = (xlog_rec_header_t *)buf;
 
        memset(buf, 0, BBSIZE);
-       INT_SET(recp->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
-       INT_SET(recp->h_cycle, ARCH_CONVERT, cycle);
-       INT_SET(recp->h_version, ARCH_CONVERT,
-                       XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? 2 : 1);
-       ASSIGN_ANY_LSN_DISK(recp->h_lsn, cycle, block);
-       ASSIGN_ANY_LSN_DISK(recp->h_tail_lsn, tail_cycle, tail_block);
-       INT_SET(recp->h_fmt, ARCH_CONVERT, XLOG_FMT);
+       recp->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
+       recp->h_cycle = cpu_to_be32(cycle);
+       recp->h_version = cpu_to_be32(
+                       xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? 2 : 1);
+       recp->h_lsn = cpu_to_be64(xlog_assign_lsn(cycle, block));
+       recp->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(tail_cycle, tail_block));
+       recp->h_fmt = cpu_to_be32(XLOG_FMT);
        memcpy(&recp->h_fs_uuid, &log->l_mp->m_sb.sb_uuid, sizeof(uuid_t));
 }
 
@@ -1132,10 +1178,10 @@ xlog_write_log_records(
         */
        balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block);
        if (balign != start_block) {
-               if ((error = xlog_bread(log, start_block, 1, bp))) {
-                       xlog_put_bp(bp);
-                       return error;
-               }
+               error = xlog_bread_noalign(log, start_block, 1, bp);
+               if (error)
+                       goto out_put_bp;
+
                j = start_block - balign;
        }
 
@@ -1153,10 +1199,18 @@ xlog_write_log_records(
                if (j == 0 && (start_block + endcount > ealign)) {
                        offset = XFS_BUF_PTR(bp);
                        balign = BBTOB(ealign - start_block);
-                       XFS_BUF_SET_PTR(bp, offset + balign, BBTOB(sectbb));
-                       if ((error = xlog_bread(log, ealign, sectbb, bp)))
+                       error = XFS_BUF_SET_PTR(bp, offset + balign,
+                                               BBTOB(sectbb));
+                       if (error)
+                               break;
+
+                       error = xlog_bread_noalign(log, ealign, sectbb, bp);
+                       if (error)
+                               break;
+
+                       error = XFS_BUF_SET_PTR(bp, offset, bufblks);
+                       if (error)
                                break;
-                       XFS_BUF_SET_PTR(bp, offset, bufblks);
                }
 
                offset = xlog_align(log, start_block, endcount, bp);
@@ -1171,6 +1225,8 @@ xlog_write_log_records(
                start_block += endcount;
                j = 0;
        }
+
+ out_put_bp:
        xlog_put_bp(bp);
        return error;
 }
@@ -1359,7 +1415,7 @@ xlog_recover_add_to_cont_trans(
        int                     old_len;
 
        item = trans->r_itemq;
-       if (item == 0) {
+       if (item == NULL) {
                /* finish copying rest of trans header */
                xlog_recover_add_item(&trans->r_itemq);
                ptr = (xfs_caddr_t) &trans->r_theader +
@@ -1405,8 +1461,14 @@ xlog_recover_add_to_trans(
        if (!len)
                return 0;
        item = trans->r_itemq;
-       if (item == 0) {
-               ASSERT(*(uint *)dp == XFS_TRANS_HEADER_MAGIC);
+       if (item == NULL) {
+               /* 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");
+                       ASSERT(0);
+                       return XFS_ERROR(EIO);
+               }
                if (len == sizeof(xfs_trans_header_t))
                        xlog_recover_add_item(&trans->r_itemq);
                memcpy(&trans->r_theader, dp, len); /* d, s, l */
@@ -1425,10 +1487,19 @@ xlog_recover_add_to_trans(
        item = item->ri_prev;
 
        if (item->ri_total == 0) {              /* first region to be added */
-               item->ri_total  = in_f->ilf_size;
-               ASSERT(item->ri_total <= XLOG_MAX_REGIONS_IN_ITEM);
-               item->ri_buf = kmem_zalloc((item->ri_total *
-                                           sizeof(xfs_log_iovec_t)), KM_SLEEP);
+               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",
+                                 in_f->ilf_size);
+                       ASSERT(0);
+                       return XFS_ERROR(EIO);
+               }
+
+               item->ri_total = in_f->ilf_size;
+               item->ri_buf =
+                       kmem_zalloc(item->ri_total * sizeof(xfs_log_iovec_t),
+                                   KM_SLEEP);
        }
        ASSERT(item->ri_total > item->ri_cnt);
        /* Description region is ri_buf[0] */
@@ -1460,12 +1531,12 @@ xlog_recover_unlink_tid(
        xlog_recover_t          *tp;
        int                     found = 0;
 
-       ASSERT(trans != 0);
+       ASSERT(trans != NULL);
        if (trans == *q) {
                *q = (*q)->r_next;
        } else {
                tp = *q;
-               while (tp != 0) {
+               while (tp) {
                        if (tp->r_next == trans) {
                                found = 1;
                                break;
@@ -1488,7 +1559,7 @@ xlog_recover_insert_item_backq(
        xlog_recover_item_t     **q,
        xlog_recover_item_t     *item)
 {
-       if (*q == 0) {
+       if (*q == NULL) {
                item->ri_prev = item->ri_next = item;
                *q = item;
        } else {
@@ -1510,12 +1581,10 @@ xlog_recover_insert_item_frontq(
 
 STATIC int
 xlog_recover_reorder_trans(
-       xlog_t                  *log,
        xlog_recover_t          *trans)
 {
        xlog_recover_item_t     *first_item, *itemq, *itemq_next;
        xfs_buf_log_format_t    *buf_f;
-       xfs_buf_log_format_v1_t *obuf_f;
        ushort                  flags = 0;
 
        first_item = itemq = trans->r_itemq;
@@ -1523,29 +1592,16 @@ xlog_recover_reorder_trans(
        do {
                itemq_next = itemq->ri_next;
                buf_f = (xfs_buf_log_format_t *)itemq->ri_buf[0].i_addr;
-               switch (ITEM_TYPE(itemq)) {
-               case XFS_LI_BUF:
-                       flags = buf_f->blf_flags;
-                       break;
-               case XFS_LI_6_1_BUF:
-               case XFS_LI_5_3_BUF:
-                       obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-                       flags = obuf_f->blf_flags;
-                       break;
-               }
 
                switch (ITEM_TYPE(itemq)) {
                case XFS_LI_BUF:
-               case XFS_LI_6_1_BUF:
-               case XFS_LI_5_3_BUF:
+                       flags = buf_f->blf_flags;
                        if (!(flags & XFS_BLI_CANCEL)) {
                                xlog_recover_insert_item_frontq(&trans->r_itemq,
                                                                itemq);
                                break;
                        }
                case XFS_LI_INODE:
-               case XFS_LI_6_1_INODE:
-               case XFS_LI_5_3_INODE:
                case XFS_LI_DQUOT:
                case XFS_LI_QUOTAOFF:
                case XFS_LI_EFD:
@@ -1584,7 +1640,6 @@ xlog_recover_do_buffer_pass1(
        xfs_buf_cancel_t        *nextp;
        xfs_buf_cancel_t        *prevp;
        xfs_buf_cancel_t        **bucket;
-       xfs_buf_log_format_v1_t *obuf_f;
        xfs_daddr_t             blkno = 0;
        uint                    len = 0;
        ushort                  flags = 0;
@@ -1595,13 +1650,6 @@ xlog_recover_do_buffer_pass1(
                len = buf_f->blf_len;
                flags = buf_f->blf_flags;
                break;
-       case XFS_LI_6_1_BUF:
-       case XFS_LI_5_3_BUF:
-               obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-               blkno = (xfs_daddr_t) obuf_f->blf_blkno;
-               len = obuf_f->blf_len;
-               flags = obuf_f->blf_flags;
-               break;
        }
 
        /*
@@ -1725,8 +1773,7 @@ xlog_check_buffer_cancelled(
                                        } else {
                                                prevp->bc_next = bcp->bc_next;
                                        }
-                                       kmem_free(bcp,
-                                                 sizeof(xfs_buf_cancel_t));
+                                       kmem_free(bcp);
                                }
                        }
                        return 1;
@@ -1747,7 +1794,6 @@ xlog_recover_do_buffer_pass2(
        xlog_t                  *log,
        xfs_buf_log_format_t    *buf_f)
 {
-       xfs_buf_log_format_v1_t *obuf_f;
        xfs_daddr_t             blkno = 0;
        ushort                  flags = 0;
        uint                    len = 0;
@@ -1758,13 +1804,6 @@ xlog_recover_do_buffer_pass2(
                flags = buf_f->blf_flags;
                len = buf_f->blf_len;
                break;
-       case XFS_LI_6_1_BUF:
-       case XFS_LI_5_3_BUF:
-               obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-               blkno = (xfs_daddr_t) obuf_f->blf_blkno;
-               flags = obuf_f->blf_flags;
-               len = (xfs_daddr_t) obuf_f->blf_len;
-               break;
        }
 
        return xlog_check_buffer_cancelled(log, blkno, len, flags);
@@ -1800,7 +1839,6 @@ xlog_recover_do_inode_buffer(
        int                     inodes_per_buf;
        xfs_agino_t             *logged_nextp;
        xfs_agino_t             *buffer_nextp;
-       xfs_buf_log_format_v1_t *obuf_f;
        unsigned int            *data_map = NULL;
        unsigned int            map_size = 0;
 
@@ -1809,12 +1847,6 @@ xlog_recover_do_inode_buffer(
                data_map = buf_f->blf_data_map;
                map_size = buf_f->blf_map_size;
                break;
-       case XFS_LI_6_1_BUF:
-       case XFS_LI_5_3_BUF:
-               obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-               data_map = obuf_f->blf_data_map;
-               map_size = obuf_f->blf_map_size;
-               break;
        }
        /*
         * Set the variables corresponding to the current region to
@@ -1890,7 +1922,7 @@ xlog_recover_do_inode_buffer(
 
                buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp,
                                              next_unlinked_offset);
-               INT_SET(*buffer_nextp, ARCH_CONVERT, *logged_nextp);
+               *buffer_nextp = *logged_nextp;
        }
 
        return 0;
@@ -1905,7 +1937,6 @@ xlog_recover_do_inode_buffer(
 /*ARGSUSED*/
 STATIC void
 xlog_recover_do_reg_buffer(
-       xfs_mount_t             *mp,
        xlog_recover_item_t     *item,
        xfs_buf_t               *bp,
        xfs_buf_log_format_t    *buf_f)
@@ -1913,7 +1944,6 @@ xlog_recover_do_reg_buffer(
        int                     i;
        int                     bit;
        int                     nbits;
-       xfs_buf_log_format_v1_t *obuf_f;
        unsigned int            *data_map = NULL;
        unsigned int            map_size = 0;
        int                     error;
@@ -1923,12 +1953,6 @@ xlog_recover_do_reg_buffer(
                data_map = buf_f->blf_data_map;
                map_size = buf_f->blf_map_size;
                break;
-       case XFS_LI_6_1_BUF:
-       case XFS_LI_5_3_BUF:
-               obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-               data_map = obuf_f->blf_data_map;
-               map_size = obuf_f->blf_map_size;
-               break;
        }
        bit = 0;
        i = 1;  /* 0 is the buf format structure */
@@ -1938,7 +1962,7 @@ xlog_recover_do_reg_buffer(
                        break;
                nbits = xfs_contig_bits(data_map, map_size, bit);
                ASSERT(nbits > 0);
-               ASSERT(item->ri_buf[i].i_addr != 0);
+               ASSERT(item->ri_buf[i].i_addr != NULL);
                ASSERT(item->ri_buf[i].i_len % XFS_BLI_CHUNK == 0);
                ASSERT(XFS_BUF_COUNT(bp) >=
                       ((uint)bit << XFS_BLI_SHIFT)+(nbits<<XFS_BLI_SHIFT));
@@ -1951,16 +1975,30 @@ xlog_recover_do_reg_buffer(
                error = 0;
                if (buf_f->blf_flags &
                   (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
+                       if (item->ri_buf[i].i_addr == NULL) {
+                               cmn_err(CE_ALERT,
+                                       "XFS: NULL dquot in %s.", __func__);
+                               goto next;
+                       }
+                       if (item->ri_buf[i].i_len < sizeof(xfs_dqblk_t)) {
+                               cmn_err(CE_ALERT,
+                                       "XFS: dquot too small (%d) in %s.",
+                                       item->ri_buf[i].i_len, __func__);
+                               goto next;
+                       }
                        error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
                                               item->ri_buf[i].i_addr,
                                               -1, 0, XFS_QMOPT_DOWARN,
                                               "dquot_buf_recover");
+                       if (error)
+                               goto next;
                }
-               if (!error)
-                       memcpy(xfs_buf_offset(bp,
-                               (uint)bit << XFS_BLI_SHIFT),    /* dest */
-                               item->ri_buf[i].i_addr,         /* source */
-                               nbits<<XFS_BLI_SHIFT);          /* length */
+
+               memcpy(xfs_buf_offset(bp,
+                       (uint)bit << XFS_BLI_SHIFT),    /* dest */
+                       item->ri_buf[i].i_addr,         /* source */
+                       nbits<<XFS_BLI_SHIFT);          /* length */
+ next:
                i++;
                bit += nbits;
        }
@@ -2128,7 +2166,7 @@ xlog_recover_do_dquot_buffer(
        if (log->l_quotaoffs_flag & type)
                return;
 
-       xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
+       xlog_recover_do_reg_buffer(item, bp, buf_f);
 }
 
 /*
@@ -2161,7 +2199,6 @@ xlog_recover_do_buffer_trans(
        int                     pass)
 {
        xfs_buf_log_format_t    *buf_f;
-       xfs_buf_log_format_v1_t *obuf_f;
        xfs_mount_t             *mp;
        xfs_buf_t               *bp;
        int                     error;
@@ -2198,13 +2235,6 @@ xlog_recover_do_buffer_trans(
                len = buf_f->blf_len;
                flags = buf_f->blf_flags;
                break;
-       case XFS_LI_6_1_BUF:
-       case XFS_LI_5_3_BUF:
-               obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-               blkno = obuf_f->blf_blkno;
-               len = obuf_f->blf_len;
-               flags = obuf_f->blf_flags;
-               break;
        default:
                xfs_fs_cmn_err(CE_ALERT, log->l_mp,
                        "xfs_log_recover: unknown buffer type 0x%x, logdev %s",
@@ -2237,7 +2267,7 @@ xlog_recover_do_buffer_trans(
                  (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
                xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
        } else {
-               xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
+               xlog_recover_do_reg_buffer(item, bp, buf_f);
        }
        if (error)
                return XFS_ERROR(error);
@@ -2258,15 +2288,14 @@ xlog_recover_do_buffer_trans(
         * overlap with future reads of those inodes.
         */
        if (XFS_DINODE_MAGIC ==
-           INT_GET(*((__uint16_t *)(xfs_buf_offset(bp, 0))), ARCH_CONVERT) &&
+           be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) &&
            (XFS_BUF_COUNT(bp) != MAX(log->l_mp->m_sb.sb_blocksize,
                        (__uint32_t)XFS_INODE_CLUSTER_SIZE(log->l_mp)))) {
                XFS_BUF_STALE(bp);
                error = xfs_bwrite(mp, bp);
        } else {
-               ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
-                      XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
-               XFS_BUF_SET_FSPRIVATE(bp, mp);
+               ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
+               bp->b_mount = mp;
                XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
                xfs_bdwrite(mp, bp);
        }
@@ -2283,7 +2312,6 @@ xlog_recover_do_inode_trans(
        xfs_inode_log_format_t  *in_f;
        xfs_mount_t             *mp;
        xfs_buf_t               *bp;
-       xfs_imap_t              imap;
        xfs_dinode_t            *dip;
        xfs_ino_t               ino;
        int                     len;
@@ -2292,68 +2320,64 @@ xlog_recover_do_inode_trans(
        int                     error;
        int                     attr_index;
        uint                    fields;
-       xfs_dinode_core_t       *dicp;
+       xfs_icdinode_t          *dicp;
+       int                     need_free = 0;
 
        if (pass == XLOG_RECOVER_PASS1) {
                return 0;
        }
 
-       in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
-       ino = in_f->ilf_ino;
-       mp = log->l_mp;
-       if (ITEM_TYPE(item) == XFS_LI_INODE) {
-               imap.im_blkno = (xfs_daddr_t)in_f->ilf_blkno;
-               imap.im_len = in_f->ilf_len;
-               imap.im_boffset = in_f->ilf_boffset;
+       if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) {
+               in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
        } else {
-               /*
-                * It's an old inode format record.  We don't know where
-                * its cluster is located on disk, and we can't allow
-                * xfs_imap() to figure it out because the inode btrees
-                * are not ready to be used.  Therefore do not pass the
-                * XFS_IMAP_LOOKUP flag to xfs_imap().  This will give
-                * us only the single block in which the inode lives
-                * rather than its cluster, so we must make sure to
-                * invalidate the buffer when we write it out below.
-                */
-               imap.im_blkno = 0;
-               xfs_imap(log->l_mp, NULL, ino, &imap, 0);
+               in_f = (xfs_inode_log_format_t *)kmem_alloc(
+                       sizeof(xfs_inode_log_format_t), KM_SLEEP);
+               need_free = 1;
+               error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
+               if (error)
+                       goto error;
        }
+       ino = in_f->ilf_ino;
+       mp = log->l_mp;
 
        /*
         * Inode buffers can be freed, look out for it,
         * and do not replay the inode.
         */
-       if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0))
-               return 0;
+       if (xlog_check_buffer_cancelled(log, in_f->ilf_blkno,
+                                       in_f->ilf_len, 0)) {
+               error = 0;
+               goto error;
+       }
 
-       bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
-                                                               XFS_BUF_LOCK);
+       bp = xfs_buf_read_flags(mp->m_ddev_targp, in_f->ilf_blkno,
+                               in_f->ilf_len, XFS_BUF_LOCK);
        if (XFS_BUF_ISERROR(bp)) {
                xfs_ioerror_alert("xlog_recover_do..(read#2)", mp,
-                                 bp, imap.im_blkno);
+                                 bp, in_f->ilf_blkno);
                error = XFS_BUF_GETERROR(bp);
                xfs_buf_relse(bp);
-               return error;
+               goto error;
        }
        error = 0;
        ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
-       dip = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+       dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset);
 
        /*
         * Make sure the place we're flushing out to really looks
         * like an inode!
         */
-       if (unlikely(INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC)) {
+       if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) {
                xfs_buf_relse(bp);
                xfs_fs_cmn_err(CE_ALERT, mp,
                        "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
                        dip, bp, ino);
                XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)",
                                 XFS_ERRLEVEL_LOW, mp);
-               return XFS_ERROR(EFSCORRUPTED);
+               error = EFSCORRUPTED;
+               goto error;
        }
-       dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
+       dicp = (xfs_icdinode_t *)(item->ri_buf[1].i_addr);
        if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
                xfs_buf_relse(bp);
                xfs_fs_cmn_err(CE_ALERT, mp,
@@ -2361,23 +2385,23 @@ xlog_recover_do_inode_trans(
                        item, ino);
                XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)",
                                 XFS_ERRLEVEL_LOW, mp);
-               return XFS_ERROR(EFSCORRUPTED);
+               error = EFSCORRUPTED;
+               goto error;
        }
 
        /* Skip replay when the on disk inode is newer than the log one */
-       if (dicp->di_flushiter <
-           INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)) {
+       if (dicp->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
                /*
                 * Deal with the wrap case, DI_MAX_FLUSH is less
                 * than smaller numbers
                 */
-               if ((INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)
-                                                       == DI_MAX_FLUSH) &&
-                   (dicp->di_flushiter < (DI_MAX_FLUSH>>1))) {
+               if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
+                   dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) {
                        /* do nothing */
                } else {
                        xfs_buf_relse(bp);
-                       return 0;
+                       error = 0;
+                       goto error;
                }
        }
        /* Take the opportunity to reset the flush iteration count */
@@ -2392,7 +2416,8 @@ xlog_recover_do_inode_trans(
                        xfs_fs_cmn_err(CE_ALERT, mp,
                                "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
                                item, dip, bp, ino);
-                       return XFS_ERROR(EFSCORRUPTED);
+                       error = EFSCORRUPTED;
+                       goto error;
                }
        } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
                if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
@@ -2404,7 +2429,8 @@ xlog_recover_do_inode_trans(
                        xfs_fs_cmn_err(CE_ALERT, mp,
                                "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
                                item, dip, bp, ino);
-                       return XFS_ERROR(EFSCORRUPTED);
+                       error = EFSCORRUPTED;
+                       goto error;
                }
        }
        if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
@@ -2416,7 +2442,8 @@ xlog_recover_do_inode_trans(
                        item, dip, bp, ino,
                        dicp->di_nextents + dicp->di_anextents,
                        dicp->di_nblocks);
-               return XFS_ERROR(EFSCORRUPTED);
+               error = EFSCORRUPTED;
+               goto error;
        }
        if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
                XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)",
@@ -2425,37 +2452,39 @@ xlog_recover_do_inode_trans(
                xfs_fs_cmn_err(CE_ALERT, mp,
                        "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
                        item, dip, bp, ino, dicp->di_forkoff);
-               return XFS_ERROR(EFSCORRUPTED);
+               error = EFSCORRUPTED;
+               goto error;
        }
-       if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
+       if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) {
                XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
                                     XFS_ERRLEVEL_LOW, mp, dicp);
                xfs_buf_relse(bp);
                xfs_fs_cmn_err(CE_ALERT, mp,
                        "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
                        item->ri_buf[1].i_len, item);
-               return XFS_ERROR(EFSCORRUPTED);
+               error = EFSCORRUPTED;
+               goto error;
        }
 
        /* The core is in in-core format */
-       xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
-                             (xfs_dinode_core_t*)item->ri_buf[1].i_addr, -1);
+       xfs_dinode_to_disk(dip, (xfs_icdinode_t *)item->ri_buf[1].i_addr);
 
        /* the rest is in on-disk format */
-       if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) {
-               memcpy((xfs_caddr_t) dip + sizeof(xfs_dinode_core_t),
-                       item->ri_buf[1].i_addr + sizeof(xfs_dinode_core_t),
-                       item->ri_buf[1].i_len  - sizeof(xfs_dinode_core_t));
+       if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) {
+               memcpy((xfs_caddr_t) dip + sizeof(struct xfs_icdinode),
+                       item->ri_buf[1].i_addr + sizeof(struct xfs_icdinode),
+                       item->ri_buf[1].i_len  - sizeof(struct xfs_icdinode));
        }
 
        fields = in_f->ilf_fields;
        switch (fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) {
        case XFS_ILOG_DEV:
-               INT_SET(dip->di_u.di_dev, ARCH_CONVERT, in_f->ilf_u.ilfu_rdev);
-
+               xfs_dinode_put_rdev(dip, in_f->ilf_u.ilfu_rdev);
                break;
        case XFS_ILOG_UUID:
-               dip->di_u.di_muuid = in_f->ilf_u.ilfu_uuid;
+               memcpy(XFS_DFORK_DPTR(dip),
+                      &in_f->ilf_u.ilfu_uuid,
+                      sizeof(uuid_t));
                break;
        }
 
@@ -2471,12 +2500,12 @@ xlog_recover_do_inode_trans(
        switch (fields & XFS_ILOG_DFORK) {
        case XFS_ILOG_DDATA:
        case XFS_ILOG_DEXT:
-               memcpy(&dip->di_u, src, len);
+               memcpy(XFS_DFORK_DPTR(dip), src, len);
                break;
 
        case XFS_ILOG_DBROOT:
-               xfs_bmbt_to_bmdr((xfs_bmbt_block_t *)src, len,
-                                &(dip->di_u.di_bmbt),
+               xfs_bmbt_to_bmdr(mp, (struct xfs_btree_block *)src, len,
+                                (xfs_bmdr_block_t *)XFS_DFORK_DPTR(dip),
                                 XFS_DFORK_DSIZE(dip, mp));
                break;
 
@@ -2513,8 +2542,8 @@ xlog_recover_do_inode_trans(
 
                case XFS_ILOG_ABROOT:
                        dest = XFS_DFORK_APTR(dip);
-                       xfs_bmbt_to_bmdr((xfs_bmbt_block_t *)src, len,
-                                        (xfs_bmdr_block_t*)dest,
+                       xfs_bmbt_to_bmdr(mp, (struct xfs_btree_block *)src,
+                                        len, (xfs_bmdr_block_t*)dest,
                                         XFS_DFORK_ASIZE(dip, mp));
                        break;
 
@@ -2522,23 +2551,20 @@ xlog_recover_do_inode_trans(
                        xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag");
                        ASSERT(0);
                        xfs_buf_relse(bp);
-                       return XFS_ERROR(EIO);
+                       error = EIO;
+                       goto error;
                }
        }
 
 write_inode_buffer:
-       if (ITEM_TYPE(item) == XFS_LI_INODE) {
-               ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
-                      XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
-               XFS_BUF_SET_FSPRIVATE(bp, mp);
-               XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
-               xfs_bdwrite(mp, bp);
-       } else {
-               XFS_BUF_STALE(bp);
-               error = xfs_bwrite(mp, bp);
-       }
-
-       return (error);
+       ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
+       bp->b_mount = mp;
+       XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
+       xfs_bdwrite(mp, bp);
+error:
+       if (need_free)
+               kmem_free(in_f);
+       return XFS_ERROR(error);
 }
 
 /*
@@ -2563,10 +2589,12 @@ xlog_recover_do_quotaoff_trans(
 
        /*
         * The logitem format's flag tells us if this was user quotaoff,
-        * group quotaoff or both.
+        * group/project quotaoff or both.
         */
        if (qoff_f->qf_flags & XFS_UQUOTA_ACCT)
                log->l_quotaoffs_flag |= XFS_DQ_USER;
+       if (qoff_f->qf_flags & XFS_PQUOTA_ACCT)
+               log->l_quotaoffs_flag |= XFS_DQ_PROJ;
        if (qoff_f->qf_flags & XFS_GQUOTA_ACCT)
                log->l_quotaoffs_flag |= XFS_DQ_GROUP;
 
@@ -2601,12 +2629,23 @@ xlog_recover_do_dquot_trans(
                return (0);
 
        recddq = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr;
-       ASSERT(recddq);
+
+       if (item->ri_buf[1].i_addr == NULL) {
+               cmn_err(CE_ALERT,
+                       "XFS: NULL dquot in %s.", __func__);
+               return XFS_ERROR(EIO);
+       }
+       if (item->ri_buf[1].i_len < sizeof(xfs_dqblk_t)) {
+               cmn_err(CE_ALERT,
+                       "XFS: dquot too small (%d) in %s.",
+                       item->ri_buf[1].i_len, __func__);
+               return XFS_ERROR(EIO);
+       }
+
        /*
         * This type of quotas was turned off, so ignore this record.
         */
-       type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
-                       (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
+       type = recddq->d_flags & (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
        ASSERT(type);
        if (log->l_quotaoffs_flag & type)
                return (0);
@@ -2657,9 +2696,8 @@ xlog_recover_do_dquot_trans(
        memcpy(ddq, recddq, item->ri_buf[1].i_len);
 
        ASSERT(dq_f->qlf_size == 2);
-       ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
-              XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
-       XFS_BUF_SET_FSPRIVATE(bp, mp);
+       ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
+       bp->b_mount = mp;
        XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
        xfs_bdwrite(mp, bp);
 
@@ -2673,40 +2711,40 @@ xlog_recover_do_dquot_trans(
  * structure into it, and adds the efi to the AIL with the given
  * LSN.
  */
-STATIC void
+STATIC int
 xlog_recover_do_efi_trans(
        xlog_t                  *log,
        xlog_recover_item_t     *item,
        xfs_lsn_t               lsn,
        int                     pass)
 {
+       int                     error;
        xfs_mount_t             *mp;
        xfs_efi_log_item_t      *efip;
        xfs_efi_log_format_t    *efi_formatp;
-       SPLDECL(s);
 
        if (pass == XLOG_RECOVER_PASS1) {
-               return;
+               return 0;
        }
 
        efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
-       ASSERT(item->ri_buf[0].i_len ==
-              (sizeof(xfs_efi_log_format_t) +
-               ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))));
 
        mp = log->l_mp;
        efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
-       memcpy((char *)&(efip->efi_format), (char *)efi_formatp,
-             sizeof(xfs_efi_log_format_t) +
-             ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t)));
+       if ((error = xfs_efi_copy_format(&(item->ri_buf[0]),
+                                        &(efip->efi_format)))) {
+               xfs_efi_item_free(efip);
+               return error;
+       }
        efip->efi_next_extent = efi_formatp->efi_nextents;
        efip->efi_flags |= XFS_EFI_COMMITTED;
 
-       AIL_LOCK(mp,s);
+       spin_lock(&log->l_ailp->xa_lock);
        /*
-        * xfs_trans_update_ail() drops the AIL lock.
+        * xfs_trans_ail_update() drops the AIL lock.
         */
-       xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s);
+       xfs_trans_ail_update(log->l_ailp, (xfs_log_item_t *)efip, lsn);
+       return 0;
 }
 
 
@@ -2724,55 +2762,48 @@ xlog_recover_do_efd_trans(
        xlog_recover_item_t     *item,
        int                     pass)
 {
-       xfs_mount_t             *mp;
        xfs_efd_log_format_t    *efd_formatp;
        xfs_efi_log_item_t      *efip = NULL;
        xfs_log_item_t          *lip;
-       int                     gen;
        __uint64_t              efi_id;
-       SPLDECL(s);
+       struct xfs_ail_cursor   cur;
+       struct xfs_ail          *ailp = log->l_ailp;
 
        if (pass == XLOG_RECOVER_PASS1) {
                return;
        }
 
        efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
-       ASSERT(item->ri_buf[0].i_len ==
-              (sizeof(xfs_efd_log_format_t) +
-               ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t))));
+       ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) +
+               ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) ||
+              (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) +
+               ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t)))));
        efi_id = efd_formatp->efd_efi_id;
 
        /*
         * Search for the efi with the id in the efd format structure
         * in the AIL.
         */
-       mp = log->l_mp;
-       AIL_LOCK(mp,s);
-       lip = xfs_trans_first_ail(mp, &gen);
+       spin_lock(&ailp->xa_lock);
+       lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
        while (lip != NULL) {
                if (lip->li_type == XFS_LI_EFI) {
                        efip = (xfs_efi_log_item_t *)lip;
                        if (efip->efi_format.efi_id == efi_id) {
                                /*
-                                * xfs_trans_delete_ail() drops the
+                                * xfs_trans_ail_delete() drops the
                                 * AIL lock.
                                 */
-                               xfs_trans_delete_ail(mp, lip, s);
+                               xfs_trans_ail_delete(ailp, lip);
+                               xfs_efi_item_free(efip);
+                               spin_lock(&ailp->xa_lock);
                                break;
                        }
                }
-               lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
-       }
-
-       /*
-        * If we found it, then free it up.  If it wasn't there, it
-        * must have been overwritten in the log.  Oh well.
-        */
-       if (lip != NULL) {
-               xfs_efi_item_free(efip);
-       } else {
-               AIL_UNLOCK(mp, s);
+               lip = xfs_trans_ail_cursor_next(ailp, &cur);
        }
+       xfs_trans_ail_cursor_done(ailp, &cur);
+       spin_unlock(&ailp->xa_lock);
 }
 
 /*
@@ -2790,54 +2821,48 @@ xlog_recover_do_trans(
        int                     error = 0;
        xlog_recover_item_t     *item, *first_item;
 
-       if ((error = xlog_recover_reorder_trans(log, trans)))
+       error = xlog_recover_reorder_trans(trans);
+       if (error)
                return error;
+
        first_item = item = trans->r_itemq;
        do {
-               /*
-                * we don't need to worry about the block number being
-                * truncated in > 1 TB buffers because in user-land,
-                * we're now n32 or 64-bit so xfs_daddr_t is 64-bits so
-                * the blkno's will get through the user-mode buffer
-                * cache properly.  The only bad case is o32 kernels
-                * where xfs_daddr_t is 32-bits but mount will warn us
-                * off a > 1 TB filesystem before we get here.
-                */
-               if ((ITEM_TYPE(item) == XFS_LI_BUF) ||
-                   (ITEM_TYPE(item) == XFS_LI_6_1_BUF) ||
-                   (ITEM_TYPE(item) == XFS_LI_5_3_BUF)) {
-                       if  ((error = xlog_recover_do_buffer_trans(log, item,
-                                                                pass)))
-                               break;
-               } else if ((ITEM_TYPE(item) == XFS_LI_INODE) ||
-                          (ITEM_TYPE(item) == XFS_LI_6_1_INODE) ||
-                          (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) {
-                       if ((error = xlog_recover_do_inode_trans(log, item,
-                                                               pass)))
-                               break;
-               } else if (ITEM_TYPE(item) == XFS_LI_EFI) {
-                       xlog_recover_do_efi_trans(log, item, trans->r_lsn,
-                                                 pass);
-               } else if (ITEM_TYPE(item) == XFS_LI_EFD) {
+               switch (ITEM_TYPE(item)) {
+               case XFS_LI_BUF:
+                       error = xlog_recover_do_buffer_trans(log, item, pass);
+                       break;
+               case XFS_LI_INODE:
+                       error = xlog_recover_do_inode_trans(log, item, pass);
+                       break;
+               case XFS_LI_EFI:
+                       error = xlog_recover_do_efi_trans(log, item,
+                                                         trans->r_lsn, pass);
+                       break;
+               case XFS_LI_EFD:
                        xlog_recover_do_efd_trans(log, item, pass);
-               } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) {
-                       if ((error = xlog_recover_do_dquot_trans(log, item,
-                                                                  pass)))
-                                       break;
-               } else if ((ITEM_TYPE(item) == XFS_LI_QUOTAOFF)) {
-                       if ((error = xlog_recover_do_quotaoff_trans(log, item,
-                                                                  pass)))
-                                       break;
-               } else {
-                       xlog_warn("XFS: xlog_recover_do_trans");
+                       error = 0;
+                       break;
+               case XFS_LI_DQUOT:
+                       error = xlog_recover_do_dquot_trans(log, item, pass);
+                       break;
+               case XFS_LI_QUOTAOFF:
+                       error = xlog_recover_do_quotaoff_trans(log, item,
+                                                              pass);
+                       break;
+               default:
+                       xlog_warn(
+       "XFS: invalid item type (%d) xlog_recover_do_trans", ITEM_TYPE(item));
                        ASSERT(0);
                        error = XFS_ERROR(EIO);
                        break;
                }
+
+               if (error)
+                       return error;
                item = item->ri_next;
        } while (first_item != item);
 
-       return error;
+       return 0;
 }
 
 /*
@@ -2858,16 +2883,14 @@ xlog_recover_free_trans(
                item = item->ri_next;
                 /* Free the regions in the item. */
                for (i = 0; i < free_item->ri_cnt; i++) {
-                       kmem_free(free_item->ri_buf[i].i_addr,
-                                 free_item->ri_buf[i].i_len);
+                       kmem_free(free_item->ri_buf[i].i_addr);
                }
                /* Free the item itself */
-               kmem_free(free_item->ri_buf,
-                         (free_item->ri_total * sizeof(xfs_log_iovec_t)));
-               kmem_free(free_item, sizeof(xlog_recover_item_t));
+               kmem_free(free_item->ri_buf);
+               kmem_free(free_item);
        } while (first_item != item);
        /* Free the transaction recover structure */
-       kmem_free(trans, sizeof(xlog_recover_t));
+       kmem_free(trans);
 }
 
 STATIC int
@@ -2922,8 +2945,8 @@ xlog_recover_process_data(
        unsigned long           hash;
        uint                    flags;
 
-       lp = dp + INT_GET(rhead->h_len, ARCH_CONVERT);
-       num_logops = INT_GET(rhead->h_num_logops, ARCH_CONVERT);
+       lp = dp + be32_to_cpu(rhead->h_len);
+       num_logops = be32_to_cpu(rhead->h_num_logops);
 
        /* check the log format matches our own - else we can't recover */
        if (xlog_header_check_recover(log->l_mp, rhead))
@@ -2940,15 +2963,20 @@ xlog_recover_process_data(
                        ASSERT(0);
                        return (XFS_ERROR(EIO));
                }
-               tid = INT_GET(ohead->oh_tid, ARCH_CONVERT);
+               tid = be32_to_cpu(ohead->oh_tid);
                hash = XLOG_RHASH(tid);
                trans = xlog_recover_find_tid(rhash[hash], tid);
                if (trans == NULL) {               /* not found; add new tid */
                        if (ohead->oh_flags & XLOG_START_TRANS)
                                xlog_recover_new_tid(&rhash[hash], tid,
-                                       INT_GET(rhead->h_lsn, ARCH_CONVERT));
+                                       be64_to_cpu(rhead->h_lsn));
                } else {
-                       ASSERT(dp+INT_GET(ohead->oh_len, ARCH_CONVERT) <= lp);
+                       if (dp + be32_to_cpu(ohead->oh_len) > lp) {
+                               xlog_warn(
+                       "XFS: xlog_recover_process_data: bad length");
+                               WARN_ON(1);
+                               return (XFS_ERROR(EIO));
+                       }
                        flags = ohead->oh_flags & ~XLOG_END_TRANS;
                        if (flags & XLOG_WAS_CONT_TRANS)
                                flags &= ~XLOG_CONTINUE_TRANS;
@@ -2962,8 +2990,7 @@ xlog_recover_process_data(
                                break;
                        case XLOG_WAS_CONT_TRANS:
                                error = xlog_recover_add_to_cont_trans(trans,
-                                               dp, INT_GET(ohead->oh_len,
-                                                       ARCH_CONVERT));
+                                               dp, be32_to_cpu(ohead->oh_len));
                                break;
                        case XLOG_START_TRANS:
                                xlog_warn(
@@ -2974,8 +3001,7 @@ xlog_recover_process_data(
                        case 0:
                        case XLOG_CONTINUE_TRANS:
                                error = xlog_recover_add_to_trans(trans,
-                                               dp, INT_GET(ohead->oh_len,
-                                                       ARCH_CONVERT));
+                                               dp, be32_to_cpu(ohead->oh_len));
                                break;
                        default:
                                xlog_warn(
@@ -2987,7 +3013,7 @@ xlog_recover_process_data(
                        if (error)
                                return error;
                }
-               dp += INT_GET(ohead->oh_len, ARCH_CONVERT);
+               dp += be32_to_cpu(ohead->oh_len);
                num_logops--;
        }
        return 0;
@@ -2997,7 +3023,7 @@ xlog_recover_process_data(
  * Process an extent free intent item that was recovered from
  * the log.  We need to free the extents that it describes.
  */
-STATIC void
+STATIC int
 xlog_recover_process_efi(
        xfs_mount_t             *mp,
        xfs_efi_log_item_t      *efip)
@@ -3005,6 +3031,7 @@ xlog_recover_process_efi(
        xfs_efd_log_item_t      *efdp;
        xfs_trans_t             *tp;
        int                     i;
+       int                     error = 0;
        xfs_extent_t            *extp;
        xfs_fsblock_t           startblock_fsb;
 
@@ -3028,51 +3055,33 @@ xlog_recover_process_efi(
                         * free the memory associated with it.
                         */
                        xfs_efi_release(efip, efip->efi_format.efi_nextents);
-                       return;
+                       return XFS_ERROR(EIO);
                }
        }
 
        tp = xfs_trans_alloc(mp, 0);
-       xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0);
+       error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0);
+       if (error)
+               goto abort_error;
        efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
 
        for (i = 0; i < efip->efi_format.efi_nextents; i++) {
                extp = &(efip->efi_format.efi_extents[i]);
-               xfs_free_extent(tp, extp->ext_start, extp->ext_len);
+               error = xfs_free_extent(tp, extp->ext_start, extp->ext_len);
+               if (error)
+                       goto abort_error;
                xfs_trans_log_efd_extent(tp, efdp, extp->ext_start,
                                         extp->ext_len);
        }
 
        efip->efi_flags |= XFS_EFI_RECOVERED;
-       xfs_trans_commit(tp, 0, NULL);
-}
-
-/*
- * Verify that once we've encountered something other than an EFI
- * in the AIL that there are no more EFIs in the AIL.
- */
-#if defined(DEBUG)
-STATIC void
-xlog_recover_check_ail(
-       xfs_mount_t             *mp,
-       xfs_log_item_t          *lip,
-       int                     gen)
-{
-       int                     orig_gen = gen;
+       error = xfs_trans_commit(tp, 0);
+       return error;
 
-       do {
-               ASSERT(lip->li_type != XFS_LI_EFI);
-               lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
-               /*
-                * The check will be bogus if we restart from the
-                * beginning of the AIL, so ASSERT that we don't.
-                * We never should since we're holding the AIL lock
-                * the entire time.
-                */
-               ASSERT(gen == orig_gen);
-       } while (lip != NULL);
+abort_error:
+       xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+       return error;
 }
-#endif /* DEBUG */
 
 /*
  * When this is called, all of the EFIs which did not have
@@ -3092,26 +3101,29 @@ xlog_recover_check_ail(
  * everything already in the AIL, we stop processing as soon as
  * we see something other than an EFI in the AIL.
  */
-STATIC void
+STATIC int
 xlog_recover_process_efis(
        xlog_t                  *log)
 {
        xfs_log_item_t          *lip;
        xfs_efi_log_item_t      *efip;
-       int                     gen;
-       xfs_mount_t             *mp;
-       SPLDECL(s);
-
-       mp = log->l_mp;
-       AIL_LOCK(mp,s);
+       int                     error = 0;
+       struct xfs_ail_cursor   cur;
+       struct xfs_ail          *ailp;
 
-       lip = xfs_trans_first_ail(mp, &gen);
+       ailp = log->l_ailp;
+       spin_lock(&ailp->xa_lock);
+       lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
        while (lip != NULL) {
                /*
                 * We're done when we see something other than an EFI.
+                * There should be no EFIs left in the AIL now.
                 */
                if (lip->li_type != XFS_LI_EFI) {
-                       xlog_recover_check_ail(mp, lip, gen);
+#ifdef DEBUG
+                       for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur))
+                               ASSERT(lip->li_type != XFS_LI_EFI);
+#endif
                        break;
                }
 
@@ -3120,16 +3132,21 @@ xlog_recover_process_efis(
                 */
                efip = (xfs_efi_log_item_t *)lip;
                if (efip->efi_flags & XFS_EFI_RECOVERED) {
-                       lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
+                       lip = xfs_trans_ail_cursor_next(ailp, &cur);
                        continue;
                }
 
-               AIL_UNLOCK(mp, s);
-               xlog_recover_process_efi(mp, efip);
-               AIL_LOCK(mp,s);
-               lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
+               spin_unlock(&ailp->xa_lock);
+               error = xlog_recover_process_efi(log->l_mp, efip);
+               spin_lock(&ailp->xa_lock);
+               if (error)
+                       goto out;
+               lip = xfs_trans_ail_cursor_next(ailp, &cur);
        }
-       AIL_UNLOCK(mp, s);
+out:
+       xfs_trans_ail_cursor_done(ailp, &cur);
+       spin_unlock(&ailp->xa_lock);
+       return error;
 }
 
 /*
@@ -3149,30 +3166,89 @@ xlog_recover_clear_agi_bucket(
        int             error;
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET);
-       xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0);
+       error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp),
+                                 0, 0, 0);
+       if (error)
+               goto out_abort;
 
-       error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
-                                  XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
-                                  XFS_FSS_TO_BB(mp, 1), 0, &agibp);
-       if (error) {
-               xfs_trans_cancel(tp, XFS_TRANS_ABORT);
-               return;
-       }
+       error = xfs_read_agi(mp, tp, agno, &agibp);
+       if (error)
+               goto out_abort;
 
        agi = XFS_BUF_TO_AGI(agibp);
-       if (INT_GET(agi->agi_magicnum, ARCH_CONVERT) != XFS_AGI_MAGIC) {
-               xfs_trans_cancel(tp, XFS_TRANS_ABORT);
-               return;
-       }
-       ASSERT(INT_GET(agi->agi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC);
-
-       INT_SET(agi->agi_unlinked[bucket], ARCH_CONVERT, NULLAGINO);
+       agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
        offset = offsetof(xfs_agi_t, agi_unlinked) +
                 (sizeof(xfs_agino_t) * bucket);
        xfs_trans_log_buf(tp, agibp, offset,
                          (offset + sizeof(xfs_agino_t) - 1));
 
-       (void) xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
+       if (error)
+               goto out_error;
+       return;
+
+out_abort:
+       xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+out_error:
+       xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: "
+                       "failed to clear agi %d. Continuing.", agno);
+       return;
+}
+
+STATIC xfs_agino_t
+xlog_recover_process_one_iunlink(
+       struct xfs_mount                *mp,
+       xfs_agnumber_t                  agno,
+       xfs_agino_t                     agino,
+       int                             bucket)
+{
+       struct xfs_buf                  *ibp;
+       struct xfs_dinode               *dip;
+       struct xfs_inode                *ip;
+       xfs_ino_t                       ino;
+       int                             error;
+
+       ino = XFS_AGINO_TO_INO(mp, agno, agino);
+       error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
+       if (error)
+               goto fail;
+
+       /*
+        * Get the on disk inode to find the next inode in the bucket.
+        */
+       error = xfs_itobp(mp, NULL, ip, &dip, &ibp, XFS_BUF_LOCK);
+       if (error)
+               goto fail_iput;
+
+       ASSERT(ip->i_d.di_nlink == 0);
+       ASSERT(ip->i_d.di_mode != 0);
+
+       /* setup for the next pass */
+       agino = be32_to_cpu(dip->di_next_unlinked);
+       xfs_buf_relse(ibp);
+
+       /*
+        * Prevent any DMAPI event from being sent when the reference on
+        * the inode is dropped.
+        */
+       ip->i_d.di_dmevmask = 0;
+
+       IRELE(ip);
+       return agino;
+
+ fail_iput:
+       IRELE(ip);
+ fail:
+       /*
+        * We can't read in the inode this bucket points to, or this inode
+        * is messed up.  Just ditch this bucket of inodes.  We will lose
+        * some inodes and space, but at least we won't hang.
+        *
+        * Call xlog_recover_clear_agi_bucket() to perform a transaction to
+        * clear the inode pointer in the bucket.
+        */
+       xlog_recover_clear_agi_bucket(mp, agno, bucket);
+       return NULLAGINO;
 }
 
 /*
@@ -3187,7 +3263,7 @@ xlog_recover_clear_agi_bucket(
  * freeing of the inode and its removal from the list must be
  * atomic.
  */
-void
+STATIC void
 xlog_recover_process_iunlinks(
        xlog_t          *log)
 {
@@ -3195,11 +3271,7 @@ xlog_recover_process_iunlinks(
        xfs_agnumber_t  agno;
        xfs_agi_t       *agi;
        xfs_buf_t       *agibp;
-       xfs_buf_t       *ibp;
-       xfs_dinode_t    *dip;
-       xfs_inode_t     *ip;
        xfs_agino_t     agino;
-       xfs_ino_t       ino;
        int             bucket;
        int             error;
        uint            mp_dmevmask;
@@ -3216,23 +3288,21 @@ xlog_recover_process_iunlinks(
                /*
                 * Find the agi for this ag.
                 */
-               agibp = xfs_buf_read(mp->m_ddev_targp,
-                               XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
-                               XFS_FSS_TO_BB(mp, 1), 0);
-               if (XFS_BUF_ISERROR(agibp)) {
-                       xfs_ioerror_alert("xlog_recover_process_iunlinks(#1)",
-                               log->l_mp, agibp,
-                               XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)));
+               error = xfs_read_agi(mp, NULL, agno, &agibp);
+               if (error) {
+                       /*
+                        * AGI is b0rked. Don't process it.
+                        *
+                        * We should probably mark the filesystem as corrupt
+                        * after we've recovered all the ag's we can....
+                        */
+                       continue;
                }
                agi = XFS_BUF_TO_AGI(agibp);
-               ASSERT(XFS_AGI_MAGIC ==
-                       INT_GET(agi->agi_magicnum, ARCH_CONVERT));
 
                for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
-
-                       agino = INT_GET(agi->agi_unlinked[bucket], ARCH_CONVERT);
+                       agino = be32_to_cpu(agi->agi_unlinked[bucket]);
                        while (agino != NULLAGINO) {
-
                                /*
                                 * Release the agi buffer so that it can
                                 * be acquired in the normal course of the
@@ -3240,86 +3310,17 @@ xlog_recover_process_iunlinks(
                                 */
                                xfs_buf_relse(agibp);
 
-                               ino = XFS_AGINO_TO_INO(mp, agno, agino);
-                               error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
-                               ASSERT(error || (ip != NULL));
-
-                               if (!error) {
-                                       /*
-                                        * Get the on disk inode to find the
-                                        * next inode in the bucket.
-                                        */
-                                       error = xfs_itobp(mp, NULL, ip, &dip,
-                                                       &ibp, 0);
-                                       ASSERT(error || (dip != NULL));
-                               }
-
-                               if (!error) {
-                                       ASSERT(ip->i_d.di_nlink == 0);
-
-                                       /* setup for the next pass */
-                                       agino = INT_GET(dip->di_next_unlinked,
-                                                       ARCH_CONVERT);
-                                       xfs_buf_relse(ibp);
-                                       /*
-                                        * Prevent any DMAPI event from
-                                        * being sent when the
-                                        * reference on the inode is
-                                        * dropped.
-                                        */
-                                       ip->i_d.di_dmevmask = 0;
-
-                                       /*
-                                        * If this is a new inode, handle
-                                        * it specially.  Otherwise,
-                                        * just drop our reference to the
-                                        * inode.  If there are no
-                                        * other references, this will
-                                        * send the inode to
-                                        * xfs_inactive() which will
-                                        * truncate the file and free
-                                        * the inode.
-                                        */
-                                       if (ip->i_d.di_mode == 0)
-                                               xfs_iput_new(ip, 0);
-                                       else
-                                               VN_RELE(XFS_ITOV(ip));
-                               } else {
-                                       /*
-                                        * We can't read in the inode
-                                        * this bucket points to, or
-                                        * this inode is messed up.  Just
-                                        * ditch this bucket of inodes.  We
-                                        * will lose some inodes and space,
-                                        * but at least we won't hang.  Call
-                                        * xlog_recover_clear_agi_bucket()
-                                        * to perform a transaction to clear
-                                        * the inode pointer in the bucket.
-                                        */
-                                       xlog_recover_clear_agi_bucket(mp, agno,
-                                                       bucket);
-
-                                       agino = NULLAGINO;
-                               }
+                               agino = xlog_recover_process_one_iunlink(mp,
+                                                       agno, agino, bucket);
 
                                /*
                                 * Reacquire the agibuffer and continue around
-                                * the loop.
+                                * the loop. This should never fail as we know
+                                * the buffer was good earlier on.
                                 */
-                               agibp = xfs_buf_read(mp->m_ddev_targp,
-                                               XFS_AG_DADDR(mp, agno,
-                                                       XFS_AGI_DADDR(mp)),
-                                               XFS_FSS_TO_BB(mp, 1), 0);
-                               if (XFS_BUF_ISERROR(agibp)) {
-                                       xfs_ioerror_alert(
-                               "xlog_recover_process_iunlinks(#2)",
-                                               log->l_mp, agibp,
-                                               XFS_AG_DADDR(mp, agno,
-                                                       XFS_AGI_DADDR(mp)));
-                               }
+                               error = xfs_read_agi(mp, NULL, agno, &agibp);
+                               ASSERT(error == 0);
                                agi = XFS_BUF_TO_AGI(agibp);
-                               ASSERT(XFS_AGI_MAGIC == INT_GET(
-                                       agi->agi_magicnum, ARCH_CONVERT));
                        }
                }
 
@@ -3342,16 +3343,16 @@ xlog_pack_data_checksum(
        int             size)
 {
        int             i;
-       uint            *up;
+       __be32          *up;
        uint            chksum = 0;
 
-       up = (uint *)iclog->ic_datap;
+       up = (__be32 *)iclog->ic_datap;
        /* divide length by 4 to get # words */
        for (i = 0; i < (size >> 2); i++) {
-               chksum ^= INT_GET(*up, ARCH_CONVERT);
+               chksum ^= be32_to_cpu(*up);
                up++;
        }
-       INT_SET(iclog->ic_header.h_chksum, ARCH_CONVERT, chksum);
+       iclog->ic_header.h_chksum = cpu_to_be32(chksum);
 }
 #else
 #define xlog_pack_data_checksum(log, iclog, size)
@@ -3368,9 +3369,8 @@ xlog_pack_data(
 {
        int                     i, j, k;
        int                     size = iclog->ic_offset + roundoff;
-       uint                    cycle_lsn;
+       __be32                  cycle_lsn;
        xfs_caddr_t             dp;
-       xlog_in_core_2_t        *xhdr;
 
        xlog_pack_data_checksum(log, iclog, size);
 
@@ -3379,18 +3379,19 @@ xlog_pack_data(
        dp = iclog->ic_datap;
        for (i = 0; i < BTOBB(size) &&
                i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
-               iclog->ic_header.h_cycle_data[i] = *(uint *)dp;
-               *(uint *)dp = cycle_lsn;
+               iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
+               *(__be32 *)dp = cycle_lsn;
                dp += BBSIZE;
        }
 
-       if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-               xhdr = (xlog_in_core_2_t *)&iclog->ic_header;
+       if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+               xlog_in_core_2_t *xhdr = iclog->ic_data;
+
                for ( ; i < BTOBB(size); i++) {
                        j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
                        k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-                       xhdr[j].hic_xheader.xh_cycle_data[k] = *(uint *)dp;
-                       *(uint *)dp = cycle_lsn;
+                       xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
+                       *(__be32 *)dp = cycle_lsn;
                        dp += BBSIZE;
                }
 
@@ -3407,26 +3408,26 @@ xlog_unpack_data_checksum(
        xfs_caddr_t             dp,
        xlog_t                  *log)
 {
-       uint                    *up = (uint *)dp;
+       __be32                  *up = (__be32 *)dp;
        uint                    chksum = 0;
        int                     i;
 
        /* divide length by 4 to get # words */
-       for (i=0; i < INT_GET(rhead->h_len, ARCH_CONVERT) >> 2; i++) {
-               chksum ^= INT_GET(*up, ARCH_CONVERT);
+       for (i=0; i < be32_to_cpu(rhead->h_len) >> 2; i++) {
+               chksum ^= be32_to_cpu(*up);
                up++;
        }
-       if (chksum != INT_GET(rhead->h_chksum, ARCH_CONVERT)) {
+       if (chksum != be32_to_cpu(rhead->h_chksum)) {
            if (rhead->h_chksum ||
                ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
                    cmn_err(CE_DEBUG,
-                       "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)",
-                           INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum);
+                       "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n",
+                           be32_to_cpu(rhead->h_chksum), chksum);
                    cmn_err(CE_DEBUG,
 "XFS: Disregard message if filesystem was created with non-DEBUG kernel");
-                   if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+                   if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
                            cmn_err(CE_DEBUG,
-                               "XFS: LogR this is a LogV2 filesystem");
+                               "XFS: LogR this is a LogV2 filesystem\n");
                    }
                    log->l_flags |= XLOG_CHKSUM_MISMATCH;
            }
@@ -3443,20 +3444,19 @@ xlog_unpack_data(
        xlog_t                  *log)
 {
        int                     i, j, k;
-       xlog_in_core_2_t        *xhdr;
 
-       for (i = 0; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)) &&
+       for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
                  i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
-               *(uint *)dp = *(uint *)&rhead->h_cycle_data[i];
+               *(__be32 *)dp = *(__be32 *)&rhead->h_cycle_data[i];
                dp += BBSIZE;
        }
 
-       if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-               xhdr = (xlog_in_core_2_t *)rhead;
-               for ( ; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)); i++) {
+       if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+               xlog_in_core_2_t *xhdr = (xlog_in_core_2_t *)rhead;
+               for ( ; i < BTOBB(be32_to_cpu(rhead->h_len)); i++) {
                        j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
                        k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-                       *(uint *)dp = xhdr[j].hic_xheader.xh_cycle_data[k];
+                       *(__be32 *)dp = xhdr[j].hic_xheader.xh_cycle_data[k];
                        dp += BBSIZE;
                }
        }
@@ -3472,24 +3472,21 @@ xlog_valid_rec_header(
 {
        int                     hlen;
 
-       if (unlikely(
-           (INT_GET(rhead->h_magicno, ARCH_CONVERT) !=
-                       XLOG_HEADER_MAGIC_NUM))) {
+       if (unlikely(be32_to_cpu(rhead->h_magicno) != XLOG_HEADER_MAGIC_NUM)) {
                XFS_ERROR_REPORT("xlog_valid_rec_header(1)",
                                XFS_ERRLEVEL_LOW, log->l_mp);
                return XFS_ERROR(EFSCORRUPTED);
        }
        if (unlikely(
            (!rhead->h_version ||
-           (INT_GET(rhead->h_version, ARCH_CONVERT) &
-                       (~XLOG_VERSION_OKBITS)) != 0))) {
+           (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
                xlog_warn("XFS: %s: unrecognised log version (%d).",
-                       __FUNCTION__, INT_GET(rhead->h_version, ARCH_CONVERT));
+                       __func__, be32_to_cpu(rhead->h_version));
                return XFS_ERROR(EIO);
        }
 
        /* LR body must have data or it wouldn't have been written */
-       hlen = INT_GET(rhead->h_len, ARCH_CONVERT);
+       hlen = be32_to_cpu(rhead->h_len);
        if (unlikely( hlen <= 0 || hlen > INT_MAX )) {
                XFS_ERROR_REPORT("xlog_valid_rec_header(2)",
                                XFS_ERRLEVEL_LOW, log->l_mp);
@@ -3533,7 +3530,7 @@ xlog_do_recovery_pass(
         * Read the header of the tail block and get the iclog buffer size from
         * h_size.  Use this to tell how many sectors make up the log header.
         */
-       if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+       if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
                /*
                 * When using variable length iclogs, read first sector of
                 * iclog header and extract the header size from it.  Get a
@@ -3542,16 +3539,17 @@ xlog_do_recovery_pass(
                hbp = xlog_get_bp(log, 1);
                if (!hbp)
                        return ENOMEM;
-               if ((error = xlog_bread(log, tail_blk, 1, hbp)))
+
+               error = xlog_bread(log, tail_blk, 1, hbp, &offset);
+               if (error)
                        goto bread_err1;
-               offset = xlog_align(log, tail_blk, 1, hbp);
+
                rhead = (xlog_rec_header_t *)offset;
                error = xlog_valid_rec_header(log, rhead, tail_blk);
                if (error)
                        goto bread_err1;
-               h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
-               if ((INT_GET(rhead->h_version, ARCH_CONVERT)
-                               & XLOG_VERSION_2) &&
+               h_size = be32_to_cpu(rhead->h_size);
+               if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) &&
                    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
                        hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
                        if (h_size % XLOG_HEADER_CYCLE_SIZE)
@@ -3579,20 +3577,22 @@ xlog_do_recovery_pass(
        memset(rhash, 0, sizeof(rhash));
        if (tail_blk <= head_blk) {
                for (blk_no = tail_blk; blk_no < head_blk; ) {
-                       if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+                       error = xlog_bread(log, blk_no, hblks, hbp, &offset);
+                       if (error)
                                goto bread_err2;
-                       offset = xlog_align(log, blk_no, hblks, hbp);
+
                        rhead = (xlog_rec_header_t *)offset;
                        error = xlog_valid_rec_header(log, rhead, blk_no);
                        if (error)
                                goto bread_err2;
 
                        /* blocks in data section */
-                       bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
-                       error = xlog_bread(log, blk_no + hblks, bblks, dbp);
+                       bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
+                       error = xlog_bread(log, blk_no + hblks, bblks, dbp,
+                                          &offset);
                        if (error)
                                goto bread_err2;
-                       offset = xlog_align(log, blk_no + hblks, bblks, dbp);
+
                        xlog_unpack_data(rhead, offset, log);
                        if ((error = xlog_recover_process_data(log,
                                                rhash, rhead, offset, pass)))
@@ -3615,10 +3615,10 @@ xlog_do_recovery_pass(
                        wrapped_hblks = 0;
                        if (blk_no + hblks <= log->l_logBBsize) {
                                /* Read header in one read */
-                               error = xlog_bread(log, blk_no, hblks, hbp);
+                               error = xlog_bread(log, blk_no, hblks, hbp,
+                                                  &offset);
                                if (error)
                                        goto bread_err2;
-                               offset = xlog_align(log, blk_no, hblks, hbp);
                        } else {
                                /* This LR is split across physical log end */
                                if (blk_no != log->l_logBBsize) {
@@ -3626,12 +3626,13 @@ xlog_do_recovery_pass(
                                        ASSERT(blk_no <= INT_MAX);
                                        split_hblks = log->l_logBBsize - (int)blk_no;
                                        ASSERT(split_hblks > 0);
-                                       if ((error = xlog_bread(log, blk_no,
-                                                       split_hblks, hbp)))
+                                       error = xlog_bread(log, blk_no,
+                                                          split_hblks, hbp,
+                                                          &offset);
+                                       if (error)
                                                goto bread_err2;
-                                       offset = xlog_align(log, blk_no,
-                                                       split_hblks, hbp);
                                }
+
                                /*
                                 * Note: this black magic still works with
                                 * large sector sizes (non-512) only because:
@@ -3644,15 +3645,24 @@ xlog_do_recovery_pass(
                                 *   _first_, then the log start (LR header end)
                                 *   - order is important.
                                 */
+                               wrapped_hblks = hblks - split_hblks;
                                bufaddr = XFS_BUF_PTR(hbp);
-                               XFS_BUF_SET_PTR(hbp,
+                               error = XFS_BUF_SET_PTR(hbp,
                                                bufaddr + BBTOB(split_hblks),
                                                BBTOB(hblks - split_hblks));
-                               wrapped_hblks = hblks - split_hblks;
-                               error = xlog_bread(log, 0, wrapped_hblks, hbp);
                                if (error)
                                        goto bread_err2;
-                               XFS_BUF_SET_PTR(hbp, bufaddr, BBTOB(hblks));
+
+                               error = xlog_bread_noalign(log, 0,
+                                                          wrapped_hblks, hbp);
+                               if (error)
+                                       goto bread_err2;
+
+                               error = XFS_BUF_SET_PTR(hbp, bufaddr,
+                                                       BBTOB(hblks));
+                               if (error)
+                                       goto bread_err2;
+
                                if (!offset)
                                        offset = xlog_align(log, 0,
                                                        wrapped_hblks, hbp);
@@ -3663,15 +3673,15 @@ xlog_do_recovery_pass(
                        if (error)
                                goto bread_err2;
 
-                       bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
+                       bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
                        blk_no += hblks;
 
                        /* Read in data for log record */
                        if (blk_no + bblks <= log->l_logBBsize) {
-                               error = xlog_bread(log, blk_no, bblks, dbp);
+                               error = xlog_bread(log, blk_no, bblks, dbp,
+                                                  &offset);
                                if (error)
                                        goto bread_err2;
-                               offset = xlog_align(log, blk_no, bblks, dbp);
                        } else {
                                /* This log record is split across the
                                 * physical end of log */
@@ -3685,12 +3695,13 @@ xlog_do_recovery_pass(
                                        split_bblks =
                                                log->l_logBBsize - (int)blk_no;
                                        ASSERT(split_bblks > 0);
-                                       if ((error = xlog_bread(log, blk_no,
-                                                       split_bblks, dbp)))
+                                       error = xlog_bread(log, blk_no,
+                                                       split_bblks, dbp,
+                                                       &offset);
+                                       if (error)
                                                goto bread_err2;
-                                       offset = xlog_align(log, blk_no,
-                                                       split_bblks, dbp);
                                }
+
                                /*
                                 * Note: this black magic still works with
                                 * large sector sizes (non-512) only because:
@@ -3704,13 +3715,22 @@ xlog_do_recovery_pass(
                                 *   - order is important.
                                 */
                                bufaddr = XFS_BUF_PTR(dbp);
-                               XFS_BUF_SET_PTR(dbp,
+                               error = XFS_BUF_SET_PTR(dbp,
                                                bufaddr + BBTOB(split_bblks),
                                                BBTOB(bblks - split_bblks));
-                               if ((error = xlog_bread(log, wrapped_hblks,
-                                               bblks - split_bblks, dbp)))
+                               if (error)
+                                       goto bread_err2;
+
+                               error = xlog_bread_noalign(log, wrapped_hblks,
+                                               bblks - split_bblks,
+                                               dbp);
+                               if (error)
                                        goto bread_err2;
-                               XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
+
+                               error = XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
+                               if (error)
+                                       goto bread_err2;
+
                                if (!offset)
                                        offset = xlog_align(log, wrapped_hblks,
                                                bblks - split_bblks, dbp);
@@ -3727,17 +3747,21 @@ xlog_do_recovery_pass(
 
                /* read first part of physical log */
                while (blk_no < head_blk) {
-                       if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+                       error = xlog_bread(log, blk_no, hblks, hbp, &offset);
+                       if (error)
                                goto bread_err2;
-                       offset = xlog_align(log, blk_no, hblks, hbp);
+
                        rhead = (xlog_rec_header_t *)offset;
                        error = xlog_valid_rec_header(log, rhead, blk_no);
                        if (error)
                                goto bread_err2;
-                       bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
-                       if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp)))
+
+                       bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
+                       error = xlog_bread(log, blk_no+hblks, bblks, dbp,
+                                          &offset);
+                       if (error)
                                goto bread_err2;
-                       offset = xlog_align(log, blk_no+hblks, bblks, dbp);
+
                        xlog_unpack_data(rhead, offset, log);
                        if ((error = xlog_recover_process_data(log, rhash,
                                                        rhead, offset, pass)))
@@ -3787,8 +3811,7 @@ xlog_do_log_recovery(
        error = xlog_do_recovery_pass(log, head_blk, tail_blk,
                                      XLOG_RECOVER_PASS1);
        if (error != 0) {
-               kmem_free(log->l_buf_cancel_table,
-                         XLOG_BC_TABLE_SIZE * sizeof(xfs_buf_cancel_t*));
+               kmem_free(log->l_buf_cancel_table);
                log->l_buf_cancel_table = NULL;
                return error;
        }
@@ -3799,7 +3822,7 @@ xlog_do_log_recovery(
        error = xlog_do_recovery_pass(log, head_blk, tail_blk,
                                      XLOG_RECOVER_PASS2);
 #ifdef DEBUG
-       {
+       if (!error) {
                int     i;
 
                for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
@@ -3807,8 +3830,7 @@ xlog_do_log_recovery(
        }
 #endif /* DEBUG */
 
-       kmem_free(log->l_buf_cancel_table,
-                 XLOG_BC_TABLE_SIZE * sizeof(xfs_buf_cancel_t*));
+       kmem_free(log->l_buf_cancel_table);
        log->l_buf_cancel_table = NULL;
 
        return error;
@@ -3861,9 +3883,13 @@ xlog_do_recover(
         */
        bp = xfs_getsb(log->l_mp, 0);
        XFS_BUF_UNDONE(bp);
+       ASSERT(!(XFS_BUF_ISWRITE(bp)));
+       ASSERT(!(XFS_BUF_ISDELAYWRITE(bp)));
        XFS_BUF_READ(bp);
+       XFS_BUF_UNASYNC(bp);
        xfsbdstrat(log->l_mp, bp);
-       if ((error = xfs_iowait(bp))) {
+       error = xfs_iowait(bp);
+       if (error) {
                xfs_ioerror_alert("xlog_do_recover",
                                  log->l_mp, bp, XFS_BUF_ADDR(bp));
                ASSERT(0);
@@ -3873,11 +3899,14 @@ xlog_do_recover(
 
        /* Convert superblock from on-disk format */
        sbp = &log->l_mp->m_sb;
-       xfs_xlatesb(XFS_BUF_TO_SBP(bp), sbp, 1, XFS_SB_ALL_BITS);
+       xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
        ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
-       ASSERT(XFS_SB_GOOD_VERSION(sbp));
+       ASSERT(xfs_sb_good_version(sbp));
        xfs_buf_relse(bp);
 
+       /* We've re-read the superblock so re-initialize per-cpu counters */
+       xfs_icsb_reinit_counters(log->l_mp);
+
        xlog_recover_check_summary(log);
 
        /* Normal transactions can now occur */
@@ -3892,14 +3921,13 @@ xlog_do_recover(
  */
 int
 xlog_recover(
-       xlog_t          *log,
-       int             readonly)
+       xlog_t          *log)
 {
        xfs_daddr_t     head_blk, tail_blk;
        int             error;
 
        /* find the tail of the log */
-       if ((error = xlog_find_tail(log, &head_blk, &tail_blk, readonly)))
+       if ((error = xlog_find_tail(log, &head_blk, &tail_blk)))
                return error;
 
        if (tail_blk != head_blk) {
@@ -3914,8 +3942,7 @@ xlog_recover(
                 * under the vfs layer, so we can get away with it unless
                 * the device itself is read-only, in which case we fail.
                 */
-               if ((error = xfs_dev_is_read_only(log->l_mp,
-                                               "recovery required"))) {
+               if ((error = xfs_dev_is_read_only(log->l_mp, "recovery"))) {
                        return error;
                }
 
@@ -3941,8 +3968,7 @@ xlog_recover(
  */
 int
 xlog_recover_finish(
-       xlog_t          *log,
-       int             mfsi_flags)
+       xlog_t          *log)
 {
        /*
         * Now we're ready to do the transactions needed for the
@@ -3953,7 +3979,14 @@ xlog_recover_finish(
         * rather than accepting new requests.
         */
        if (log->l_flags & XLOG_RECOVERY_NEEDED) {
-               xlog_recover_process_efis(log);
+               int     error;
+               error = xlog_recover_process_efis(log);
+               if (error) {
+                       cmn_err(CE_ALERT,
+                               "Failed to recover EFIs on filesystem: %s",
+                               log->l_mp->m_fsname);
+                       return error;
+               }
                /*
                 * Sync the log to get all the EFIs out of the AIL.
                 * This isn't absolutely necessary, but it helps in
@@ -3963,9 +3996,7 @@ xlog_recover_finish(
                xfs_log_force(log->l_mp, (xfs_lsn_t)0,
                              (XFS_LOG_FORCE | XFS_LOG_SYNC));
 
-               if ( (mfsi_flags & XFS_MFSI_NOUNLINK) == 0 ) {
-                       xlog_recover_process_iunlinks(log);
-               }
+               xlog_recover_process_iunlinks(log);
 
                xlog_recover_check_summary(log);
 
@@ -3976,7 +4007,7 @@ xlog_recover_finish(
                log->l_flags &= ~XLOG_RECOVERY_NEEDED;
        } else {
                cmn_err(CE_DEBUG,
-                       "!Ending clean XFS mount for filesystem: %s",
+                       "!Ending clean XFS mount for filesystem: %s\n",
                        log->l_mp->m_fsname);
        }
        return 0;
@@ -3994,11 +4025,8 @@ xlog_recover_check_summary(
 {
        xfs_mount_t     *mp;
        xfs_agf_t       *agfp;
-       xfs_agi_t       *agip;
        xfs_buf_t       *agfbp;
        xfs_buf_t       *agibp;
-       xfs_daddr_t     agfdaddr;
-       xfs_daddr_t     agidaddr;
        xfs_buf_t       *sbbp;
 #ifdef XFS_LOUD_RECOVERY
        xfs_sb_t        *sbp;
@@ -4007,6 +4035,7 @@ xlog_recover_check_summary(
        __uint64_t      freeblks;
        __uint64_t      itotal;
        __uint64_t      ifree;
+       int             error;
 
        mp = log->l_mp;
 
@@ -4014,47 +4043,33 @@ xlog_recover_check_summary(
        itotal = 0LL;
        ifree = 0LL;
        for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
-               agfdaddr = XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp));
-               agfbp = xfs_buf_read(mp->m_ddev_targp, agfdaddr,
-                               XFS_FSS_TO_BB(mp, 1), 0);
-               if (XFS_BUF_ISERROR(agfbp)) {
-                       xfs_ioerror_alert("xlog_recover_check_summary(agf)",
-                                               mp, agfbp, agfdaddr);
+               error = xfs_read_agf(mp, NULL, agno, 0, &agfbp);
+               if (error) {
+                       xfs_fs_cmn_err(CE_ALERT, mp,
+                                       "xlog_recover_check_summary(agf)"
+                                       "agf read failed agno %d error %d",
+                                                       agno, error);
+               } else {
+                       agfp = XFS_BUF_TO_AGF(agfbp);
+                       freeblks += be32_to_cpu(agfp->agf_freeblks) +
+                                   be32_to_cpu(agfp->agf_flcount);
+                       xfs_buf_relse(agfbp);
                }
-               agfp = XFS_BUF_TO_AGF(agfbp);
-               ASSERT(XFS_AGF_MAGIC ==
-                       INT_GET(agfp->agf_magicnum, ARCH_CONVERT));
-               ASSERT(XFS_AGF_GOOD_VERSION(
-                       INT_GET(agfp->agf_versionnum, ARCH_CONVERT)));
-               ASSERT(INT_GET(agfp->agf_seqno, ARCH_CONVERT) == agno);
-
-               freeblks += INT_GET(agfp->agf_freeblks, ARCH_CONVERT) +
-                           INT_GET(agfp->agf_flcount, ARCH_CONVERT);
-               xfs_buf_relse(agfbp);
-
-               agidaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp));
-               agibp = xfs_buf_read(mp->m_ddev_targp, agidaddr,
-                               XFS_FSS_TO_BB(mp, 1), 0);
-               if (XFS_BUF_ISERROR(agibp)) {
-                       xfs_ioerror_alert("xlog_recover_check_summary(agi)",
-                                         mp, agibp, agidaddr);
+
+               error = xfs_read_agi(mp, NULL, agno, &agibp);
+               if (!error) {
+                       struct xfs_agi  *agi = XFS_BUF_TO_AGI(agibp);
+
+                       itotal += be32_to_cpu(agi->agi_count);
+                       ifree += be32_to_cpu(agi->agi_freecount);
+                       xfs_buf_relse(agibp);
                }
-               agip = XFS_BUF_TO_AGI(agibp);
-               ASSERT(XFS_AGI_MAGIC ==
-                       INT_GET(agip->agi_magicnum, ARCH_CONVERT));
-               ASSERT(XFS_AGI_GOOD_VERSION(
-                       INT_GET(agip->agi_versionnum, ARCH_CONVERT)));
-               ASSERT(INT_GET(agip->agi_seqno, ARCH_CONVERT) == agno);
-
-               itotal += INT_GET(agip->agi_count, ARCH_CONVERT);
-               ifree += INT_GET(agip->agi_freecount, ARCH_CONVERT);
-               xfs_buf_relse(agibp);
        }
 
        sbbp = xfs_getsb(mp, 0);
 #ifdef XFS_LOUD_RECOVERY
        sbp = &mp->m_sb;
-       xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, XFS_SB_ALL_BITS);
+       xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(sbbp));
        cmn_err(CE_NOTE,
                "xlog_recover_check_summary: sb_icount %Lu itotal %Lu",
                sbp->sb_icount, itotal);