tp->t_logcb.cb_func = (void(*)(void*, int))xfs_trans_committed;
tp->t_logcb.cb_arg = tp;
- /* We need to pass the iclog buffer which was used for the
+ /*
+ * We need to pass the iclog buffer which was used for the
* transaction commit record into this function, and attach
* the callback to it. The callback must be attached before
* the items are unlocked to avoid racing with other threads
* waiting for an item to unlock.
*/
- error = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
+ shutdown = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
- /* mark this thread as no longer being in a transaction */
- PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
+ /*
+ * Mark this thread as no longer being in a transaction
+ */
+ PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
/*
* Once all the items of the transaction have been copied
*/
xfs_trans_unlock_items(tp, commit_lsn);
+ /*
+ * If we detected a log error earlier, finish committing
+ * the transaction now (unpin log items, etc).
+ *
+ * Order is critical here, to avoid using the transaction
+ * pointer after its been freed (by xfs_trans_committed
+ * either here now, or as a callback). We cannot do this
+ * step inside xfs_log_notify as was done earlier because
+ * of this issue.
+ */
+ if (shutdown)
+ xfs_trans_committed(tp, XFS_LI_ABORTED);
+
/*
* Now that the xfs_trans_committed callback has been attached,
* and the items are released we can finally allow the iclog to
if (aborted)
lip->li_flags |= XFS_LI_ABORTED;
- if (lidp->lid_flags & XFS_LID_SYNC_UNLOCK) {
- IOP_UNLOCK(lip);
- }
-
/*
* Send in the ABORTED flag to the COMMITTED routine
* so that it knows whether the transaction was aborted