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 9ef162d..df8c99c 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 b0345aa..1297117 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 bea0adf..a95bac0 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 b150b07..fb25ba7 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;
 }