btrfs: add extra warning if delayed iput is added when it's not allowed
authorQu Wenruo <wqu@suse.com>
Mon, 10 Mar 2025 05:14:56 +0000 (15:44 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 18 Mar 2025 19:35:52 +0000 (20:35 +0100)
Since I have triggered the ASSERT() on the delayed iput too many times,
now is the time to add some extra debug warnings for delayed iput.

All delayed iputs should be queued after all ordered extents finish
their IO and all involved workqueues are flushed.

Thus after the btrfs_run_delayed_iputs() inside close_ctree(), there
should be no more delayed puts added.

So introduce a new BTRFS_FS_STATE_NO_DELAYED_IPUT, set after the above
mentioned timing.  And all btrfs_add_delayed_iput() will check that flag
and give a WARN_ON_ONCE().

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/fs.h
fs/btrfs/inode.c

index 03d349edb61b97c5acc22288cf82ec6fd6ab7119..1fae31f781d880587b20d9b949603a3739c17aff 100644 (file)
@@ -4397,6 +4397,8 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        /* Ordered extents for free space inodes. */
        btrfs_flush_workqueue(fs_info->endio_freespace_worker);
        btrfs_run_delayed_iputs(fs_info);
+       /* There should be no more workload to generate new delayed iputs. */
+       set_bit(BTRFS_FS_STATE_NO_DELAYED_IPUT, &fs_info->fs_state);
 
        cancel_work_sync(&fs_info->async_reclaim_work);
        cancel_work_sync(&fs_info->async_data_reclaim_work);
index c76d432168447c2b95f85f8eb0c5f3271470f756..bcca43046064b8898e86422c54baaa0e7dcf5fa0 100644 (file)
@@ -117,6 +117,9 @@ enum {
        /* Indicates there was an error cleaning up a log tree. */
        BTRFS_FS_STATE_LOG_CLEANUP_ERROR,
 
+       /* No more delayed iput can be queued. */
+       BTRFS_FS_STATE_NO_DELAYED_IPUT,
+
        BTRFS_FS_STATE_COUNT
 };
 
index a9d20ccea74f7104d58ffc91a0439386a5b81c13..c6790ce15dcaf80f2d1fc4166ed5a6d46c7dd168 100644 (file)
@@ -3427,6 +3427,7 @@ void btrfs_add_delayed_iput(struct btrfs_inode *inode)
        if (atomic_add_unless(&inode->vfs_inode.i_count, -1, 1))
                return;
 
+       WARN_ON_ONCE(test_bit(BTRFS_FS_STATE_NO_DELAYED_IPUT, &fs_info->fs_state));
        atomic_inc(&fs_info->nr_delayed_iputs);
        /*
         * Need to be irq safe here because we can be called from either an irq