#include "xfs_mount.h"
 #include "xfs_trace.h"
 #include "xfs_log.h"
+#include "xfs_log_recover.h"
 #include "xfs_trans.h"
 #include "xfs_buf_item.h"
 #include "xfs_errortag.h"
        if (read)
                goto out_finish;
 
+       /*
+        * If this is a log recovery buffer, we aren't doing transactional IO
+        * yet so we need to let it handle IO completions.
+        */
+       if (bp->b_flags & _XBF_LOGRECOVERY) {
+               xlog_recover_iodone(bp);
+               return;
+       }
+
        if (bp->b_flags & _XBF_INODES) {
                xfs_buf_inode_iodone(bp);
                return;
 
 /* buffer type flags for write callbacks */
 #define _XBF_INODES     (1 << 16)/* inode buffer */
 #define _XBF_DQUOTS     (1 << 17)/* dquot buffer */
+#define _XBF_LOGRECOVERY        (1 << 18)/* log recovery buffer */
 
 /* flags used only internally */
 #define _XBF_PAGES      (1 << 20)/* backed by refcounted pages */
        { XBF_WRITE_FAIL,       "WRITE_FAIL" }, \
        { _XBF_INODES,          "INODES" }, \
        { _XBF_DQUOTS,          "DQUOTS" }, \
+       { _XBF_LOGRECOVERY,             "LOG_RECOVERY" }, \
        { _XBF_PAGES,           "PAGES" }, \
        { _XBF_KMEM,            "KMEM" }, \
        { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
 
        if (bp->b_ops) {
                struct xfs_buf_log_item *bip;
 
-               ASSERT(!bp->b_iodone || bp->b_iodone == xlog_recover_iodone);
-               bp->b_iodone = xlog_recover_iodone;
+               bp->b_flags |= _XBF_LOGRECOVERY;
                xfs_buf_item_init(bp, mp);
                bip = bp->b_log_item;
                bip->bli_item.li_lsn = current_lsn;
                error = xfs_bwrite(bp);
        } else {
                ASSERT(bp->b_mount == mp);
-               bp->b_iodone = xlog_recover_iodone;
+               bp->b_flags |= _XBF_LOGRECOVERY;
                xfs_buf_delwri_queue(bp, buffer_list);
        }
 
 
 
        ASSERT(dq_f->qlf_size == 2);
        ASSERT(bp->b_mount == mp);
-       bp->b_iodone = xlog_recover_iodone;
+       bp->b_flags |= _XBF_LOGRECOVERY;
        xfs_buf_delwri_queue(bp, buffer_list);
 
 out_release:
 
        xfs_dinode_calc_crc(log->l_mp, dip);
 
        ASSERT(bp->b_mount == mp);
-       bp->b_iodone = xlog_recover_iodone;
+       bp->b_flags |= _XBF_LOGRECOVERY;
        xfs_buf_delwri_queue(bp, buffer_list);
 
 out_release:
 
        if (bp->b_log_item)
                xfs_buf_item_relse(bp);
        ASSERT(bp->b_log_item == NULL);
-
-       bp->b_iodone = NULL;
-       xfs_buf_ioend(bp);
+       bp->b_flags &= ~_XBF_LOGRECOVERY;
+       xfs_buf_ioend_finish(bp);
 }
 
 /*