From d6204f1e8db28cd72613f6c1b199f6457c0bbb2b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 10 Jan 2023 13:29:34 -0800 Subject: [PATCH] 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: 197782466 Bug: 269471019 Change-Id: I70b498ab8920b4e1a13e04b753fe176a632552b2 Signed-off-by: Bart Van Assche --- drivers/scsi/sd_zbc.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 068a3832b5f5..aec5757f307c 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -346,7 +346,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; @@ -756,13 +756,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; @@ -770,10 +763,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 (!sd_is_zoned(sdkp) || !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, @@ -967,7 +963,7 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE]) else blk_queue_max_open_zones(q, sdkp->zones_max_open); blk_queue_max_active_zones(q, 0); - nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks); + nr_zones = div64_u64(sdkp->capacity + zone_blocks - 1, zone_blocks); /* * Per ZBC and ZAC specifications, writes in sequential write required