aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_refcount_item.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-09-21 09:15:09 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2020-09-23 08:58:51 -0700
commit93293bcbde93567efaf4e6bcd58cad270e1fcbf5 (patch)
treece0c66955bfc654356af446cfbfcaa308037abd3 /fs/xfs/xfs_refcount_item.c
parentxfs: check dabtree node hash values when loading child blocks (diff)
downloadlinux-dev-93293bcbde93567efaf4e6bcd58cad270e1fcbf5.tar.xz
linux-dev-93293bcbde93567efaf4e6bcd58cad270e1fcbf5.zip
xfs: log new intent items created as part of finishing recovered intent items
During a code inspection, I found a serious bug in the log intent item recovery code when an intent item cannot complete all the work and decides to requeue itself to get that done. When this happens, the item recovery creates a new incore deferred op representing the remaining work and attaches it to the transaction that it allocated. At the end of _item_recover, it moves the entire chain of deferred ops to the dummy parent_tp that xlog_recover_process_intents passed to it, but fail to log a new intent item for the remaining work before committing the transaction for the single unit of work. xlog_finish_defer_ops logs those new intent items once recovery has finished dealing with the intent items that it recovered, but this isn't sufficient. If the log is forced to disk after a recovered log item decides to requeue itself and the system goes down before we call xlog_finish_defer_ops, the second log recovery will never see the new intent item and therefore has no idea that there was more work to do. It will finish recovery leaving the filesystem in a corrupted state. The same logic applies to /any/ deferred ops added during intent item recovery, not just the one handling the remaining work. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs/xfs/xfs_refcount_item.c')
-rw-r--r--fs/xfs/xfs_refcount_item.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index ca93b6488377..492d80a0b406 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -555,7 +555,7 @@ xfs_cui_item_recover(
}
xfs_refcount_finish_one_cleanup(tp, rcur, error);
- xfs_defer_move(parent_tp, tp);
+ xfs_defer_capture(parent_tp, tp);
error = xfs_trans_commit(tp);
return error;