ANDROID: scsi/sd_zbc: Support npo2 zone sizes

Remove the restriction that the zone size must be a power of two. This
patch has been tested with the following test script:

. tests/zbd/rc
. common/null_blk
. common/scsi_debug

DESCRIPTION="test npo2 zone size support"
QUICK=1

requires() {
	_have_fio
	_have_driver f2fs
	_have_module_param scsi_debug zone_size_mb
	_have_scsi_debug
}

test() {
	echo "Running ${TEST_NAME}"

	local scsi_debug_params=(
		delay=0
		dev_size_mb=1024
		sector_size=4096
		zbc=host-managed
		zone_nr_conv=0
		zone_size_mb=3
	)
	_init_scsi_debug "${scsi_debug_params[@]}" &&
	local zdev="/dev/${SCSI_DEBUG_DEVICES[0]}" fail &&
	ls -ld "${zdev}" >>"${FULL}" &&
	local fio_args=(
		--direct=1
		--file="${zdev}"
		--gtod_reduce=1
		--iodepth=64
		--iodepth_batch=16
		--ioengine=io_uring
		--ioscheduler=none
		--name=npo2zs
		--runtime=10
		--size=1M
		--time_based=1
		--zonemode=zbd
	) &&
	_run_fio_verify_io "${fio_args[@]}" >>"${FULL}" 2>&1 ||
	fail=true

	_exit_scsi_debug

	if [ -z "$fail" ]; then
		echo "Test complete"
	else
		echo "Test failed"
		return 1
	fi
}

Bug: 269471019
Bug: 415836627
Change-Id: I70b498ab8920b4e1a13e04b753fe176a632552b2
Signed-off-by: Bart Van Assche <bvanassche@google.com>
This commit is contained in:
Bart Van Assche
2025-04-08 14:22:55 -07:00
parent 355dfccf9d
commit 497ca126dd

View File

@@ -306,7 +306,7 @@ static blk_status_t sd_zbc_cmnd_checks(struct scsi_cmnd *cmd)
if (sdkp->device->changed)
return BLK_STS_IOERR;
if (sector & (sd_zbc_zone_sectors(sdkp) - 1))
if (!bdev_is_zone_start(sdkp->disk->part0, sector))
/* Unaligned request */
return BLK_STS_IOERR;
@@ -506,13 +506,6 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf,
zone_blocks = sdkp->zone_starting_lba_gran;
}
if (!is_power_of_2(zone_blocks)) {
sd_printk(KERN_ERR, sdkp,
"Zone size %llu is not a power of two.\n",
zone_blocks);
return -EINVAL;
}
*zblocks = zone_blocks;
return 0;
@@ -520,10 +513,13 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf,
static void sd_zbc_print_zones(struct scsi_disk *sdkp)
{
u64 remainder;
if (sdkp->device->type != TYPE_ZBC || !sdkp->capacity)
return;
if (sdkp->capacity & (sdkp->zone_info.zone_blocks - 1))
div64_u64_rem(sdkp->capacity, sdkp->zone_info.zone_blocks, &remainder);
if (remainder)
sd_printk(KERN_NOTICE, sdkp,
"%u zones of %u logical blocks + 1 runt zone\n",
sdkp->zone_info.nr_zones - 1,
@@ -622,7 +618,8 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, struct queue_limits *lim,
if (ret != 0)
goto err;
nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks);
nr_zones = div64_u64(sdkp->capacity + zone_blocks - 1, zone_blocks);
sdkp->early_zone_info.nr_zones = nr_zones;
sdkp->early_zone_info.zone_blocks = zone_blocks;