diff options
Diffstat (limited to 'fs/xfs/xfs_log_cil.c')
-rw-r--r-- | fs/xfs/xfs_log_cil.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 31e4ea2d19ac..ef8e7d9f445d 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -377,9 +377,23 @@ xfs_log_commit_cil( | |||
377 | xfs_log_done(mp, tp->t_ticket, NULL, log_flags); | 377 | xfs_log_done(mp, tp->t_ticket, NULL, log_flags); |
378 | xfs_trans_unreserve_and_mod_sb(tp); | 378 | xfs_trans_unreserve_and_mod_sb(tp); |
379 | 379 | ||
380 | /* | ||
381 | * Once all the items of the transaction have been copied to the CIL, | ||
382 | * the items can be unlocked and freed. | ||
383 | * | ||
384 | * This needs to be done before we drop the CIL context lock because we | ||
385 | * have to update state in the log items and unlock them before they go | ||
386 | * to disk. If we don't, then the CIL checkpoint can race with us and | ||
387 | * we can run checkpoint completion before we've updated and unlocked | ||
388 | * the log items. This affects (at least) processing of stale buffers, | ||
389 | * inodes and EFIs. | ||
390 | */ | ||
391 | xfs_trans_free_items(tp, *commit_lsn, 0); | ||
392 | |||
380 | /* check for background commit before unlock */ | 393 | /* check for background commit before unlock */ |
381 | if (log->l_cilp->xc_ctx->space_used > XLOG_CIL_SPACE_LIMIT(log)) | 394 | if (log->l_cilp->xc_ctx->space_used > XLOG_CIL_SPACE_LIMIT(log)) |
382 | push = 1; | 395 | push = 1; |
396 | |||
383 | up_read(&log->l_cilp->xc_ctx_lock); | 397 | up_read(&log->l_cilp->xc_ctx_lock); |
384 | 398 | ||
385 | /* | 399 | /* |