*/
 static struct xfs_defer_capture *
 xfs_defer_ops_capture(
-       struct xfs_trans                *tp,
-       struct xfs_inode                *capture_ip)
+       struct xfs_trans                *tp)
 {
        struct xfs_defer_capture        *dfc;
+       unsigned short                  i;
+       int                             error;
 
        if (list_empty(&tp->t_dfops))
                return NULL;
        /* Preserve the log reservation size. */
        dfc->dfc_logres = tp->t_log_res;
 
+       error = xfs_defer_save_resources(&dfc->dfc_held, tp);
+       if (error) {
+               /*
+                * Resource capture should never fail, but if it does, we
+                * still have to shut down the log and release things
+                * properly.
+                */
+               xfs_force_shutdown(tp->t_mountp, SHUTDOWN_CORRUPT_INCORE);
+       }
+
        /*
-        * Grab an extra reference to this inode and attach it to the capture
-        * structure.
+        * Grab extra references to the inodes and buffers because callers are
+        * expected to release their held references after we commit the
+        * transaction.
         */
-       if (capture_ip) {
-               ihold(VFS_I(capture_ip));
-               dfc->dfc_capture_ip = capture_ip;
+       for (i = 0; i < dfc->dfc_held.dr_inos; i++) {
+               ASSERT(xfs_isilocked(dfc->dfc_held.dr_ip[i], XFS_ILOCK_EXCL));
+               ihold(VFS_I(dfc->dfc_held.dr_ip[i]));
        }
 
+       for (i = 0; i < dfc->dfc_held.dr_bufs; i++)
+               xfs_buf_hold(dfc->dfc_held.dr_bp[i]);
+
        return dfc;
 }
 
 /* Release all resources that we used to capture deferred ops. */
 void
-xfs_defer_ops_release(
+xfs_defer_ops_capture_free(
        struct xfs_mount                *mp,
        struct xfs_defer_capture        *dfc)
 {
+       unsigned short                  i;
+
        xfs_defer_cancel_list(mp, &dfc->dfc_dfops);
-       if (dfc->dfc_capture_ip)
-               xfs_irele(dfc->dfc_capture_ip);
+
+       for (i = 0; i < dfc->dfc_held.dr_bufs; i++)
+               xfs_buf_relse(dfc->dfc_held.dr_bp[i]);
+
+       for (i = 0; i < dfc->dfc_held.dr_inos; i++)
+               xfs_irele(dfc->dfc_held.dr_ip[i]);
+
        kmem_free(dfc);
 }
 
 int
 xfs_defer_ops_capture_and_commit(
        struct xfs_trans                *tp,
-       struct xfs_inode                *capture_ip,
        struct list_head                *capture_list)
 {
        struct xfs_mount                *mp = tp->t_mountp;
        struct xfs_defer_capture        *dfc;
        int                             error;
 
-       ASSERT(!capture_ip || xfs_isilocked(capture_ip, XFS_ILOCK_EXCL));
-
        /* If we don't capture anything, commit transaction and exit. */
-       dfc = xfs_defer_ops_capture(tp, capture_ip);
+       dfc = xfs_defer_ops_capture(tp);
        if (!dfc)
                return xfs_trans_commit(tp);
 
        /* Commit the transaction and add the capture structure to the list. */
        error = xfs_trans_commit(tp);
        if (error) {
-               xfs_defer_ops_release(mp, dfc);
+               xfs_defer_ops_capture_free(mp, dfc);
                return error;
        }
 
 xfs_defer_ops_continue(
        struct xfs_defer_capture        *dfc,
        struct xfs_trans                *tp,
-       struct xfs_inode                **captured_ipp)
+       struct xfs_defer_resources      *dres)
 {
        ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
        ASSERT(!(tp->t_flags & XFS_TRANS_DIRTY));
 
        /* Lock and join the captured inode to the new transaction. */
-       if (dfc->dfc_capture_ip) {
-               xfs_ilock(dfc->dfc_capture_ip, XFS_ILOCK_EXCL);
-               xfs_trans_ijoin(tp, dfc->dfc_capture_ip, 0);
-       }
-       *captured_ipp = dfc->dfc_capture_ip;
+       if (dfc->dfc_held.dr_inos == 2)
+               xfs_lock_two_inodes(dfc->dfc_held.dr_ip[0], XFS_ILOCK_EXCL,
+                                   dfc->dfc_held.dr_ip[1], XFS_ILOCK_EXCL);
+       else if (dfc->dfc_held.dr_inos == 1)
+               xfs_ilock(dfc->dfc_held.dr_ip[0], XFS_ILOCK_EXCL);
+       xfs_defer_restore_resources(tp, &dfc->dfc_held);
+       memcpy(dres, &dfc->dfc_held, sizeof(struct xfs_defer_resources));
 
        /* Move captured dfops chain and state to the transaction. */
        list_splice_init(&dfc->dfc_dfops, &tp->t_dfops);
 
        kmem_free(dfc);
 }
+
+/* Release the resources captured and continued during recovery. */
+void
+xfs_defer_resources_rele(
+       struct xfs_defer_resources      *dres)
+{
+       unsigned short                  i;
+
+       for (i = 0; i < dres->dr_inos; i++) {
+               xfs_iunlock(dres->dr_ip[i], XFS_ILOCK_EXCL);
+               xfs_irele(dres->dr_ip[i]);
+               dres->dr_ip[i] = NULL;
+       }
+
+       for (i = 0; i < dres->dr_bufs; i++) {
+               xfs_buf_relse(dres->dr_bp[i]);
+               dres->dr_bp[i] = NULL;
+       }
+
+       dres->dr_inos = 0;
+       dres->dr_bufs = 0;
+       dres->dr_ordered = 0;
+}
 
        /* Log reservation saved from the transaction. */
        unsigned int            dfc_logres;
 
-       /*
-        * An inode reference that must be maintained to complete the deferred
-        * work.
-        */
-       struct xfs_inode        *dfc_capture_ip;
+       struct xfs_defer_resources dfc_held;
 };
 
 /*
  * This doesn't normally happen except log recovery.
  */
 int xfs_defer_ops_capture_and_commit(struct xfs_trans *tp,
-               struct xfs_inode *capture_ip, struct list_head *capture_list);
+               struct list_head *capture_list);
 void xfs_defer_ops_continue(struct xfs_defer_capture *d, struct xfs_trans *tp,
-               struct xfs_inode **captured_ipp);
-void xfs_defer_ops_release(struct xfs_mount *mp, struct xfs_defer_capture *d);
+               struct xfs_defer_resources *dres);
+void xfs_defer_ops_capture_free(struct xfs_mount *mp,
+               struct xfs_defer_capture *d);
+void xfs_defer_resources_rele(struct xfs_defer_resources *dres);
 
 #endif /* __XFS_DEFER_H__ */
 
 {
        struct xfs_defer_capture *dfc, *next;
        struct xfs_trans        *tp;
-       struct xfs_inode        *ip;
        int                     error = 0;
 
        list_for_each_entry_safe(dfc, next, capture_list, dfc_list) {
                struct xfs_trans_res    resv;
+               struct xfs_defer_resources dres;
 
                /*
                 * Create a new transaction reservation from the captured
                 * from recovering a single intent item.
                 */
                list_del_init(&dfc->dfc_list);
-               xfs_defer_ops_continue(dfc, tp, &ip);
-
+               xfs_defer_ops_continue(dfc, tp, &dres);
                error = xfs_trans_commit(tp);
-               if (ip) {
-                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                       xfs_irele(ip);
-               }
+               xfs_defer_resources_rele(&dres);
                if (error)
                        return error;
        }
 
        list_for_each_entry_safe(dfc, next, capture_list, dfc_list) {
                list_del_init(&dfc->dfc_list);
-               xfs_defer_ops_release(mp, dfc);
+               xfs_defer_ops_capture_free(mp, dfc);
        }
 }
 /*