diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2016-10-23 23:21:18 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-10-23 23:21:18 -0400 |
commit | b77428b12b55437b28deae738d9ce8b2e0663b55 (patch) | |
tree | 50229749ffb142f19823c848ba2598dcf036d362 /fs | |
parent | c17a8ef43d6b80ed3519b828c37d18645445949f (diff) |
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: Dave Chinner <david@fromorbit.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/libxfs/xfs_defer.c | 17 |
1 files changed, 5 insertions, 12 deletions
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 613c5cf19436..5c2929f94bd3 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c | |||
@@ -199,9 +199,9 @@ xfs_defer_intake_work( | |||
199 | struct xfs_defer_pending *dfp; | 199 | struct xfs_defer_pending *dfp; |
200 | 200 | ||
201 | list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { | 201 | list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { |
202 | trace_xfs_defer_intake_work(tp->t_mountp, dfp); | ||
203 | dfp->dfp_intent = dfp->dfp_type->create_intent(tp, | 202 | dfp->dfp_intent = dfp->dfp_type->create_intent(tp, |
204 | dfp->dfp_count); | 203 | dfp->dfp_count); |
204 | trace_xfs_defer_intake_work(tp->t_mountp, dfp); | ||
205 | list_sort(tp->t_mountp, &dfp->dfp_work, | 205 | list_sort(tp->t_mountp, &dfp->dfp_work, |
206 | dfp->dfp_type->diff_items); | 206 | dfp->dfp_type->diff_items); |
207 | list_for_each(li, &dfp->dfp_work) | 207 | list_for_each(li, &dfp->dfp_work) |
@@ -221,21 +221,14 @@ xfs_defer_trans_abort( | |||
221 | struct xfs_defer_pending *dfp; | 221 | struct xfs_defer_pending *dfp; |
222 | 222 | ||
223 | trace_xfs_defer_trans_abort(tp->t_mountp, dop); | 223 | trace_xfs_defer_trans_abort(tp->t_mountp, dop); |
224 | /* | ||
225 | * If the transaction was committed, drop the intent reference | ||
226 | * since we're bailing out of here. The other reference is | ||
227 | * dropped when the intent hits the AIL. If the transaction | ||
228 | * was not committed, the intent is freed by the intent item | ||
229 | * unlock handler on abort. | ||
230 | */ | ||
231 | if (!dop->dop_committed) | ||
232 | return; | ||
233 | 224 | ||
234 | /* Abort intent items. */ | 225 | /* Abort intent items that don't have a done item. */ |
235 | list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { | 226 | list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { |
236 | trace_xfs_defer_pending_abort(tp->t_mountp, dfp); | 227 | trace_xfs_defer_pending_abort(tp->t_mountp, dfp); |
237 | if (!dfp->dfp_done) | 228 | if (dfp->dfp_intent && !dfp->dfp_done) { |
238 | dfp->dfp_type->abort_intent(dfp->dfp_intent); | 229 | dfp->dfp_type->abort_intent(dfp->dfp_intent); |
230 | dfp->dfp_intent = NULL; | ||
231 | } | ||
239 | } | 232 | } |
240 | 233 | ||
241 | /* Shut down FS. */ | 234 | /* Shut down FS. */ |