]> git.ipfire.org Git - people/ms/linux.git/commitdiff
btrfs: zoned: fix API misuse of zone finish waiting
authorNaohiro Aota <naohiro.aota@wdc.com>
Wed, 31 Aug 2022 04:55:48 +0000 (13:55 +0900)
committerDavid Sterba <dsterba@suse.com>
Mon, 5 Sep 2022 13:32:21 +0000 (15:32 +0200)
The commit 2ce543f47843 ("btrfs: zoned: wait until zone is finished when
allocation didn't progress") implemented a zone finish waiting mechanism
to the write path of zoned mode. However, using
wait_var_event()/wake_up_all() on fs_info->zone_finish_wait is wrong and
wait_var_event() just hangs because no one ever wakes it up once it goes
into sleep.

Instead, we can simply use wait_on_bit_io() and clear_and_wake_up_bit()
on fs_info->flags with a proper barrier installed.

Fixes: 2ce543f47843 ("btrfs: zoned: wait until zone is finished when allocation didn't progress")
CC: stable@vger.kernel.org # 5.16+
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/zoned.c

index 9ef162dbd4bc11fd84c649d6b7c8b453313a8571..df8c99c99df9278f874c053f0ed7f34987fa1385 100644 (file)
@@ -1088,8 +1088,6 @@ struct btrfs_fs_info {
 
        spinlock_t zone_active_bgs_lock;
        struct list_head zone_active_bgs;
-       /* Waiters when BTRFS_FS_NEED_ZONE_FINISH is set */
-       wait_queue_head_t zone_finish_wait;
 
        /* Updates are not protected by any lock */
        struct btrfs_commit_stats commit_stats;
index b0345aa16c017f989362159c590f589742897122..129711773ae51b2ec4e8907b08b6c831b9208ad4 100644 (file)
@@ -3070,7 +3070,6 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
        init_waitqueue_head(&fs_info->transaction_blocked_wait);
        init_waitqueue_head(&fs_info->async_submit_wait);
        init_waitqueue_head(&fs_info->delayed_iputs_wait);
-       init_waitqueue_head(&fs_info->zone_finish_wait);
 
        /* Usable values until the real ones are cached from the superblock */
        fs_info->nodesize = 4096;
index bea0adf2873515f5383bdecde45eeb2a1349f6d2..a95bac0c3e20e95d496bce2f057611b7f6a13d9f 100644 (file)
@@ -1644,10 +1644,9 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
                        done_offset = end;
 
                if (done_offset == start) {
-                       struct btrfs_fs_info *info = inode->root->fs_info;
-
-                       wait_var_event(&info->zone_finish_wait,
-                                      !test_bit(BTRFS_FS_NEED_ZONE_FINISH, &info->flags));
+                       wait_on_bit_io(&inode->root->fs_info->flags,
+                                      BTRFS_FS_NEED_ZONE_FINISH,
+                                      TASK_UNINTERRUPTIBLE);
                        continue;
                }
 
index b150b07ba1a7663c9b04c85307324d6819bd1b73..fb25ba7fcb2a29c8da9c63e99c6a053c854e4d7e 100644 (file)
@@ -2007,8 +2007,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
        /* For active_bg_list */
        btrfs_put_block_group(block_group);
 
-       clear_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
-       wake_up_all(&fs_info->zone_finish_wait);
+       clear_and_wake_up_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
 
        return 0;
 }