{
        const struct xfs_defer_op_type  *ops = defer_op_types[dfp->dfp_type];
 
-       dfp->dfp_intent = ops->create_intent(tp, &dfp->dfp_work,
-                       dfp->dfp_count, sort);
+       if (!dfp->dfp_intent)
+               dfp->dfp_intent = ops->create_intent(tp, &dfp->dfp_work,
+                                                    dfp->dfp_count, sort);
 }
 
 /*
                        list_add(li, &dfp->dfp_work);
                        dfp->dfp_count++;
                        dfp->dfp_done = NULL;
+                       dfp->dfp_intent = NULL;
                        xfs_defer_create_intent(tp, dfp, false);
                }
 
 
        xfs_defer_reset(stp);
 }
+
+/*
+ * Prepare a chain of fresh deferred ops work items to be completed later.  Log
+ * recovery requires the ability to put off until later the actual finishing
+ * work so that it can process unfinished items recovered from the log in
+ * correct order.
+ *
+ * Create and log intent items for all the work that we're capturing so that we
+ * can be assured that the items will get replayed if the system goes down
+ * before log recovery gets a chance to finish the work it put off.  Then we
+ * move the chain from stp to dtp.
+ */
+void
+xfs_defer_capture(
+       struct xfs_trans        *dtp,
+       struct xfs_trans        *stp)
+{
+       xfs_defer_create_intents(stp);
+       xfs_defer_move(dtp, stp);
+}
 
 extern const struct xfs_defer_op_type xfs_extent_free_defer_type;
 extern const struct xfs_defer_op_type xfs_agfl_free_defer_type;
 
+/*
+ * Functions to capture a chain of deferred operations and continue them later.
+ * This doesn't normally happen except log recovery.
+ */
+void xfs_defer_capture(struct xfs_trans *dtp, struct xfs_trans *stp);
+
 #endif /* __XFS_DEFER_H__ */
 
                xfs_bmap_unmap_extent(tp, ip, &irec);
        }
 
-       xfs_defer_move(parent_tp, tp);
+       xfs_defer_capture(parent_tp, tp);
        error = xfs_trans_commit(tp);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        xfs_irele(ip);
 
        }
 
        xfs_refcount_finish_one_cleanup(tp, rcur, error);
-       xfs_defer_move(parent_tp, tp);
+       xfs_defer_capture(parent_tp, tp);
        error = xfs_trans_commit(tp);
        return error;