Skip to content

Commit 5ddd658

Browse files
dgchinnerdchinner
authored andcommitted
xfs: don't commit the first deferred transaction without intents
If the first operation in a string of defer ops has no intents, then there is no reason to commit it before running the first call to xfs_defer_finish_one(). This allows the defer ops to be used effectively for non-intent based operations without requiring an unnecessary extra transaction commit when first called. This fixes a regression in per-attribute modification transaction count when delayed attributes are not being used. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Allison Henderson <allison.henderson@oracle.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
1 parent b2c2803 commit 5ddd658

1 file changed

Lines changed: 18 additions & 12 deletions

File tree

fs/xfs/libxfs/xfs_defer.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static const struct xfs_defer_op_type *defer_op_types[] = {
186186
[XFS_DEFER_OPS_TYPE_AGFL_FREE] = &xfs_agfl_free_defer_type,
187187
};
188188

189-
static void
189+
static bool
190190
xfs_defer_create_intent(
191191
struct xfs_trans *tp,
192192
struct xfs_defer_pending *dfp,
@@ -197,23 +197,26 @@ xfs_defer_create_intent(
197197
if (!dfp->dfp_intent)
198198
dfp->dfp_intent = ops->create_intent(tp, &dfp->dfp_work,
199199
dfp->dfp_count, sort);
200+
return dfp->dfp_intent != NULL;
200201
}
201202

202203
/*
203204
* For each pending item in the intake list, log its intent item and the
204205
* associated extents, then add the entire intake list to the end of
205206
* the pending list.
206207
*/
207-
STATIC void
208+
static bool
208209
xfs_defer_create_intents(
209210
struct xfs_trans *tp)
210211
{
211212
struct xfs_defer_pending *dfp;
213+
bool ret = false;
212214

213215
list_for_each_entry(dfp, &tp->t_dfops, dfp_list) {
214216
trace_xfs_defer_create_intent(tp->t_mountp, dfp);
215-
xfs_defer_create_intent(tp, dfp, true);
217+
ret |= xfs_defer_create_intent(tp, dfp, true);
216218
}
219+
return ret;
217220
}
218221

219222
/* Abort all the intents that were committed. */
@@ -487,7 +490,7 @@ int
487490
xfs_defer_finish_noroll(
488491
struct xfs_trans **tp)
489492
{
490-
struct xfs_defer_pending *dfp;
493+
struct xfs_defer_pending *dfp = NULL;
491494
int error = 0;
492495
LIST_HEAD(dop_pending);
493496

@@ -506,17 +509,20 @@ xfs_defer_finish_noroll(
506509
* of time that any one intent item can stick around in memory,
507510
* pinning the log tail.
508511
*/
509-
xfs_defer_create_intents(*tp);
512+
bool has_intents = xfs_defer_create_intents(*tp);
513+
510514
list_splice_init(&(*tp)->t_dfops, &dop_pending);
511515

512-
error = xfs_defer_trans_roll(tp);
513-
if (error)
514-
goto out_shutdown;
516+
if (has_intents || dfp) {
517+
error = xfs_defer_trans_roll(tp);
518+
if (error)
519+
goto out_shutdown;
515520

516-
/* Possibly relog intent items to keep the log moving. */
517-
error = xfs_defer_relog(tp, &dop_pending);
518-
if (error)
519-
goto out_shutdown;
521+
/* Relog intent items to keep the log moving. */
522+
error = xfs_defer_relog(tp, &dop_pending);
523+
if (error)
524+
goto out_shutdown;
525+
}
520526

521527
dfp = list_first_entry(&dop_pending, struct xfs_defer_pending,
522528
dfp_list);

0 commit comments

Comments
 (0)