mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 02:33:57 +00:00
xfs: only run precommits once per transaction object
Committing a transaction tx0 with a defer ops chain of (A, B, C) creates a chain of transactions that looks like this: tx0 -> txA -> txB -> txC Prior to commitcb04211748
, __xfs_trans_commit would run precommits on tx0, then call xfs_defer_finish_noroll to convert A-C to tx[A-C]. Unfortunately, after the finish_noroll loop we forgot to run precommits on txC. That was fixed by adding the second precommit call. Unfortunately, none of us remembered that xfs_defer_finish_noroll calls __xfs_trans_commit a second time to commit tx0 before finishing work A in txA and committing that. In other words, we run precommits twice on tx0: xfs_trans_commit(tx0) __xfs_trans_commit(tx0, false) xfs_trans_run_precommits(tx0) xfs_defer_finish_noroll(tx0) xfs_trans_roll(tx0) txA = xfs_trans_dup(tx0) __xfs_trans_commit(tx0, true) xfs_trans_run_precommits(tx0) This currently isn't an issue because the inode item precommit is idempotent; the iunlink item precommit deletes itself so it can't be called again; and the buffer/dquot item precommits only check the incore objects for corruption. However, it doesn't make sense to run precommits twice. Fix this situation by only running precommits after finish_noroll. Cc: <stable@vger.kernel.org> # v6.4 Fixes:cb04211748
("xfs: defered work could create precommits") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
53b001a21c
commit
44d9b07e52
@ -860,13 +860,6 @@ __xfs_trans_commit(
|
||||
|
||||
trace_xfs_trans_commit(tp, _RET_IP_);
|
||||
|
||||
error = xfs_trans_run_precommits(tp);
|
||||
if (error) {
|
||||
if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
|
||||
xfs_defer_cancel(tp);
|
||||
goto out_unreserve;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish deferred items on final commit. Only permanent transactions
|
||||
* should ever have deferred ops.
|
||||
@ -877,13 +870,12 @@ __xfs_trans_commit(
|
||||
error = xfs_defer_finish_noroll(&tp);
|
||||
if (error)
|
||||
goto out_unreserve;
|
||||
|
||||
/* Run precommits from final tx in defer chain. */
|
||||
error = xfs_trans_run_precommits(tp);
|
||||
if (error)
|
||||
goto out_unreserve;
|
||||
}
|
||||
|
||||
error = xfs_trans_run_precommits(tp);
|
||||
if (error)
|
||||
goto out_unreserve;
|
||||
|
||||
/*
|
||||
* If there is nothing to be logged by the transaction,
|
||||
* then unlock all of the items associated with the
|
||||
|
Loading…
Reference in New Issue
Block a user