Commit f0ba0e71 authored by Johannes Thumshirn's avatar Johannes Thumshirn Committed by David Sterba
Browse files

btrfs: zoned: skip ZONE FINISH of conventional zones



Don't call ZONE FINISH for conventional zones as this will result in I/O
errors. Instead check if the zone that needs finishing is a conventional
zone and if yes skip it.

Also factor out the actual handling of finishing a single zone into a
helper function, as do_zone_finish() is growing ever bigger and the
indentations levels are getting higher.

Reviewed-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 7b632596
Loading
Loading
Loading
Loading
+35 −20
Original line number Diff line number Diff line
@@ -2245,6 +2245,40 @@ static void wait_eb_writebacks(struct btrfs_block_group *block_group)
	rcu_read_unlock();
}

static int call_zone_finish(struct btrfs_block_group *block_group,
			    struct btrfs_io_stripe *stripe)
{
	struct btrfs_device *device = stripe->dev;
	const u64 physical = stripe->physical;
	struct btrfs_zoned_device_info *zinfo = device->zone_info;
	int ret;

	if (!device->bdev)
		return 0;

	if (zinfo->max_active_zones == 0)
		return 0;

	if (btrfs_dev_is_sequential(device, physical)) {
		unsigned int nofs_flags;

		nofs_flags = memalloc_nofs_save();
		ret = blkdev_zone_mgmt(device->bdev, REQ_OP_ZONE_FINISH,
				       physical >> SECTOR_SHIFT,
				       zinfo->zone_size >> SECTOR_SHIFT);
		memalloc_nofs_restore(nofs_flags);

		if (ret)
			return ret;
	}

	if (!(block_group->flags & BTRFS_BLOCK_GROUP_DATA))
		zinfo->reserved_active_zones++;
	btrfs_dev_clear_active_zone(device, physical);

	return 0;
}

static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_written)
{
	struct btrfs_fs_info *fs_info = block_group->fs_info;
@@ -2329,31 +2363,12 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
	down_read(&dev_replace->rwsem);
	map = block_group->physical_map;
	for (i = 0; i < map->num_stripes; i++) {
		struct btrfs_device *device = map->stripes[i].dev;
		const u64 physical = map->stripes[i].physical;
		struct btrfs_zoned_device_info *zinfo = device->zone_info;
		unsigned int nofs_flags;

		if (!device->bdev)
			continue;

		if (zinfo->max_active_zones == 0)
			continue;

		nofs_flags = memalloc_nofs_save();
		ret = blkdev_zone_mgmt(device->bdev, REQ_OP_ZONE_FINISH,
				       physical >> SECTOR_SHIFT,
				       zinfo->zone_size >> SECTOR_SHIFT);
		memalloc_nofs_restore(nofs_flags);

		ret = call_zone_finish(block_group, &map->stripes[i]);
		if (ret) {
			up_read(&dev_replace->rwsem);
			return ret;
		}

		if (!(block_group->flags & BTRFS_BLOCK_GROUP_DATA))
			zinfo->reserved_active_zones++;
		btrfs_dev_clear_active_zone(device, physical);
	}
	up_read(&dev_replace->rwsem);