77 lines
3.1 KiB
Diff
77 lines
3.1 KiB
Diff
From 361b73ca6606d8bace6fe78b63d508d747c6689a Mon Sep 17 00:00:00 2001
|
|
From: Filipe Manana <fdmanana@suse.com>
|
|
Date: Wed, 5 Mar 2025 16:52:26 +0000
|
|
Subject: btrfs: fix non-empty delayed iputs list on unmount due to compressed
|
|
write workers
|
|
|
|
At close_ctree() after we have ran delayed iputs either through explicitly
|
|
calling btrfs_run_delayed_iputs() or later during the call to
|
|
btrfs_commit_super() or btrfs_error_commit_super(), we assert that the
|
|
delayed iputs list is empty.
|
|
|
|
When we have compressed writes this assertion may fail because delayed
|
|
iputs may have been added to the list after we last ran delayed iputs.
|
|
This happens like this:
|
|
|
|
1) We have a compressed write bio executing;
|
|
|
|
2) We enter close_ctree() and flush the fs_info->endio_write_workers
|
|
queue which is the queue used for running ordered extent completion;
|
|
|
|
3) The compressed write bio finishes and enters
|
|
btrfs_finish_compressed_write_work(), where it calls
|
|
btrfs_finish_ordered_extent() which in turn calls
|
|
btrfs_queue_ordered_fn(), which queues a work item in the
|
|
fs_info->endio_write_workers queue that we have flushed before;
|
|
|
|
4) At close_ctree() we proceed, run all existing delayed iputs and
|
|
call btrfs_commit_super() (which also runs delayed iputs), but before
|
|
we run the following assertion below:
|
|
|
|
ASSERT(list_empty(&fs_info->delayed_iputs))
|
|
|
|
A delayed iput is added by the step below...
|
|
|
|
5) The ordered extent completion job queued in step 3 runs and results in
|
|
creating a delayed iput when dropping the last reference of the ordered
|
|
extent (a call to btrfs_put_ordered_extent() made from
|
|
btrfs_finish_one_ordered());
|
|
|
|
6) At this point the delayed iputs list is not empty, so the assertion at
|
|
close_ctree() fails.
|
|
|
|
Fix this by flushing the fs_info->compressed_write_workers queue at
|
|
close_ctree() before flushing the fs_info->endio_write_workers queue,
|
|
respecting the queue dependency as the later is responsible for the
|
|
execution of ordered extent completion.
|
|
|
|
CC: stable@vger.kernel.org # 5.15+
|
|
Reviewed-by: Qu Wenruo <wqu@suse.com>
|
|
Signed-off-by: Filipe Manana <fdmanana@suse.com>
|
|
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
---
|
|
fs/btrfs/disk-io.c | 12 ++++++++++++
|
|
1 file changed, 12 insertions(+)
|
|
|
|
--- a/fs/btrfs/disk-io.c
|
|
+++ b/fs/btrfs/disk-io.c
|
|
@@ -4346,6 +4346,18 @@ void __cold close_ctree(struct btrfs_fs_
|
|
btrfs_flush_workqueue(fs_info->delalloc_workers);
|
|
|
|
/*
|
|
+ * When finishing a compressed write bio we schedule a work queue item
|
|
+ * to finish an ordered extent - btrfs_finish_compressed_write_work()
|
|
+ * calls btrfs_finish_ordered_extent() which in turns does a call to
|
|
+ * btrfs_queue_ordered_fn(), and that queues the ordered extent
|
|
+ * completion either in the endio_write_workers work queue or in the
|
|
+ * fs_info->endio_freespace_worker work queue. We flush those queues
|
|
+ * below, so before we flush them we must flush this queue for the
|
|
+ * workers of compressed writes.
|
|
+ */
|
|
+ flush_workqueue(fs_info->compressed_write_workers);
|
|
+
|
|
+ /*
|
|
* After we parked the cleaner kthread, ordered extents may have
|
|
* completed and created new delayed iputs. If one of the async reclaim
|
|
* tasks is running and in the RUN_DELAYED_IPUTS flush state, then we
|