Skip to content

Commit

Permalink
btrfs: zoned: wait until zone is finished when allocation didn't prog…
Browse files Browse the repository at this point in the history
…ress

When the allocated position doesn't progress, we cannot submit IOs to
finish a block group, but there should be ongoing IOs that will finish a
block group. So, in that case, we wait for a zone to be finished and retry
the allocation after that.

Introduce a new flag BTRFS_FS_NEED_ZONE_FINISH for fs_info->flags to
indicate we need a zone finish to have proceeded. The flag is set when the
allocator detected it cannot activate a new block group. And, it is cleared
once a zone is finished.

CC: stable@vger.kernel.org # 5.16+
Fixes: afba2bc ("btrfs: zoned: implement active zone tracking")
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Naohiro Aota authored and David Sterba committed Jul 25, 2022
1 parent 898793d commit 2ce543f
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 2 deletions.
5 changes: 5 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,9 @@ enum {
/* Indicate we have half completed snapshot deletions pending. */
BTRFS_FS_UNFINISHED_DROPS,

/* Indicate we have to finish a zone to do next allocation. */
BTRFS_FS_NEED_ZONE_FINISH,

#if BITS_PER_LONG == 32
/* Indicate if we have error/warn message printed on 32bit systems */
BTRFS_FS_32BIT_ERROR,
Expand Down Expand Up @@ -1086,6 +1089,8 @@ 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;
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -3152,6 +3152,7 @@ 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;
Expand Down
9 changes: 7 additions & 2 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1643,8 +1643,13 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
if (ret == 0)
done_offset = end;

if (done_offset == start)
return -ENOSPC;
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));
continue;
}

if (!locked_page_done) {
__set_page_dirty_nobuffers(locked_page);
Expand Down
6 changes: 6 additions & 0 deletions fs/btrfs/zoned.c
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,9 @@ 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);

return 0;
}

Expand Down Expand Up @@ -2043,6 +2046,9 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
}
mutex_unlock(&fs_info->chunk_mutex);

if (!ret)
set_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);

return ret;
}

Expand Down

0 comments on commit 2ce543f

Please sign in to comment.