diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index cbee0a86c978..a5f7dc18a62f 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -341,7 +341,7 @@ xfs_defer_reset( * If an inode is provided, relog it to the new transaction. */ int -xfs_defer_finish( +xfs_defer_finish_noroll( struct xfs_trans **tp) { struct xfs_defer_ops *dop = (*tp)->t_dfops; @@ -430,25 +430,37 @@ xfs_defer_finish( cleanup_fn(*tp, state, error); } - /* - * Roll the transaction once more to avoid returning to the caller - * with a dirty transaction. - */ - if ((*tp)->t_flags & XFS_TRANS_DIRTY) { - error = xfs_defer_trans_roll(tp); - dop = (*tp)->t_dfops; - } out: - if (error) { + if (error) trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); - } else { + else trace_xfs_defer_finish_done((*tp)->t_mountp, dop, _RET_IP_); - xfs_defer_reset(dop); - } return error; } +int +xfs_defer_finish( + struct xfs_trans **tp) +{ + int error; + + /* + * Finish and roll the transaction once more to avoid returning to the + * caller with a dirty transaction. + */ + error = xfs_defer_finish_noroll(tp); + if (error) + return error; + if ((*tp)->t_flags & XFS_TRANS_DIRTY) { + error = xfs_defer_trans_roll(tp); + if (error) + return error; + } + xfs_defer_reset((*tp)->t_dfops); + return 0; +} + /* * Free up any items left in the list. */ diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 56f927803940..85c41fe4dbae 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -48,6 +48,7 @@ enum xfs_defer_ops_type { void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); +int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish(struct xfs_trans **tp); void __xfs_defer_cancel(struct xfs_defer_ops *dop); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index cd553aa9ecb0..7bf5c1202719 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -933,7 +933,7 @@ __xfs_trans_commit( /* finish deferred items on final commit */ if (!regrant && tp->t_dfops) { - error = xfs_defer_finish(&tp); + error = xfs_defer_finish_noroll(&tp); if (error) { xfs_defer_cancel(tp); goto out_unreserve;