Commit b77428b1 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner

xfs: defer should abort intent items if the trans roll fails

If the deferred ops transaction roll fails, we need to abort the intent
items if we haven't already logged a done item for it, regardless of
whether or not the deferred ops has had a transaction committed.  Dave
found this while running generic/388.

Move the tracepoint to make it easier to track object lifetimes.
Reported-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent c17a8ef4
...@@ -199,9 +199,9 @@ xfs_defer_intake_work( ...@@ -199,9 +199,9 @@ xfs_defer_intake_work(
struct xfs_defer_pending *dfp; struct xfs_defer_pending *dfp;
list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { list_for_each_entry(dfp, &dop->dop_intake, dfp_list) {
trace_xfs_defer_intake_work(tp->t_mountp, dfp);
dfp->dfp_intent = dfp->dfp_type->create_intent(tp, dfp->dfp_intent = dfp->dfp_type->create_intent(tp,
dfp->dfp_count); dfp->dfp_count);
trace_xfs_defer_intake_work(tp->t_mountp, dfp);
list_sort(tp->t_mountp, &dfp->dfp_work, list_sort(tp->t_mountp, &dfp->dfp_work,
dfp->dfp_type->diff_items); dfp->dfp_type->diff_items);
list_for_each(li, &dfp->dfp_work) list_for_each(li, &dfp->dfp_work)
...@@ -221,21 +221,14 @@ xfs_defer_trans_abort( ...@@ -221,21 +221,14 @@ xfs_defer_trans_abort(
struct xfs_defer_pending *dfp; struct xfs_defer_pending *dfp;
trace_xfs_defer_trans_abort(tp->t_mountp, dop); trace_xfs_defer_trans_abort(tp->t_mountp, dop);
/*
* If the transaction was committed, drop the intent reference
* since we're bailing out of here. The other reference is
* dropped when the intent hits the AIL. If the transaction
* was not committed, the intent is freed by the intent item
* unlock handler on abort.
*/
if (!dop->dop_committed)
return;
/* Abort intent items. */ /* Abort intent items that don't have a done item. */
list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { list_for_each_entry(dfp, &dop->dop_pending, dfp_list) {
trace_xfs_defer_pending_abort(tp->t_mountp, dfp); trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
if (!dfp->dfp_done) if (dfp->dfp_intent && !dfp->dfp_done) {
dfp->dfp_type->abort_intent(dfp->dfp_intent); dfp->dfp_type->abort_intent(dfp->dfp_intent);
dfp->dfp_intent = NULL;
}
} }
/* Shut down FS. */ /* Shut down FS. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment