summaryrefslogtreecommitdiff
path: root/zbd.c
diff options
context:
space:
mode:
authorNiklas Cassel <niklas.cassel@wdc.com>2021-05-14 12:53:14 +0000
committerJens Axboe <axboe@kernel.dk>2021-05-14 08:57:31 -0600
commitd2f442bc0bd507510089d56cd510616093415702 (patch)
tree2ab78b1fea66d18c9a758d4b7f4820353889ff3d /zbd.c
parenteaa45783ef5079884f96813e74c6b450dc52d0f0 (diff)
downloadfio-d2f442bc0bd507510089d56cd510616093415702.tar.gz
fio-d2f442bc0bd507510089d56cd510616093415702.tar.bz2
ioengines: add get_max_open_zones zoned block device operation
Define a new IO engine operation to get the maximum number of open zones. Like the existing IO engine operations: .get_zoned_model, .report_zones, and .reset_wp, this new IO engine operation is only valid for zoned block devices. Similarly to the other zbd IO engine operations, also provide a default implementation inside oslib/linux-blkzoned.c that will be used if the ioengine does not override it. The default Linux oslib implementation is implemented similarly to blkzoned_get_zoned_model(), i.e. it will return a successful error code even when the sysfs attribute does not exist. This is because the sysfs max_open_zones attribute was introduced first in Linux v5.9. All error handling is still there, so an ioengine that provides its own implementation will still have its error code respected properly. Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'zbd.c')
-rw-r--r--zbd.c90
1 files changed, 85 insertions, 5 deletions
diff --git a/zbd.c b/zbd.c
index 46ff9aeb..68cd58e1 100644
--- a/zbd.c
+++ b/zbd.c
@@ -114,6 +114,34 @@ int zbd_reset_wp(struct thread_data *td, struct fio_file *f,
}
/**
+ * zbd_get_max_open_zones - Get the maximum number of open zones
+ * @td: FIO thread data
+ * @f: FIO file for which to get max open zones
+ * @max_open_zones: Upon success, result will be stored here.
+ *
+ * A @max_open_zones value set to zero means no limit.
+ *
+ * Returns 0 upon success and a negative error code upon failure.
+ */
+int zbd_get_max_open_zones(struct thread_data *td, struct fio_file *f,
+ unsigned int *max_open_zones)
+{
+ int ret;
+
+ if (td->io_ops && td->io_ops->get_max_open_zones)
+ ret = td->io_ops->get_max_open_zones(td, f, max_open_zones);
+ else
+ ret = blkzoned_get_max_open_zones(td, f, max_open_zones);
+ if (ret < 0) {
+ td_verror(td, errno, "get max open zones failed");
+ log_err("%s: get max open zones failed (%d).\n",
+ f->file_name, errno);
+ }
+
+ return ret;
+}
+
+/**
* zbd_zone_idx - convert an offset into a zone number
* @f: file pointer.
* @offset: offset in bytes. If this offset is in the first zone_size bytes
@@ -554,6 +582,51 @@ out:
return ret;
}
+static int zbd_set_max_open_zones(struct thread_data *td, struct fio_file *f)
+{
+ struct zoned_block_device_info *zbd = f->zbd_info;
+ unsigned int max_open_zones;
+ int ret;
+
+ if (zbd->model != ZBD_HOST_MANAGED) {
+ /* Only host-managed devices have a max open limit */
+ zbd->max_open_zones = td->o.max_open_zones;
+ goto out;
+ }
+
+ /* If host-managed, get the max open limit */
+ ret = zbd_get_max_open_zones(td, f, &max_open_zones);
+ if (ret)
+ return ret;
+
+ if (!max_open_zones) {
+ /* No device limit */
+ zbd->max_open_zones = td->o.max_open_zones;
+ } else if (!td->o.max_open_zones) {
+ /* No user limit. Set limit to device limit */
+ zbd->max_open_zones = max_open_zones;
+ } else if (td->o.max_open_zones <= max_open_zones) {
+ /* Both user limit and dev limit. User limit not too large */
+ zbd->max_open_zones = td->o.max_open_zones;
+ } else {
+ /* Both user limit and dev limit. User limit too large */
+ td_verror(td, EINVAL,
+ "Specified --max_open_zones is too large");
+ log_err("Specified --max_open_zones (%d) is larger than max (%u)\n",
+ td->o.max_open_zones, max_open_zones);
+ return -EINVAL;
+ }
+
+out:
+ /* Ensure that the limit is not larger than FIO's internal limit */
+ zbd->max_open_zones = min_not_zero(zbd->max_open_zones,
+ (uint32_t) ZBD_MAX_OPEN_ZONES);
+ dprint(FD_ZBD, "%s: using max open zones limit: %"PRIu32"\n",
+ f->file_name, zbd->max_open_zones);
+
+ return 0;
+}
+
/*
* Allocate zone information and store it into f->zbd_info if zonemode=zbd.
*
@@ -576,9 +649,13 @@ static int zbd_create_zone_info(struct thread_data *td, struct fio_file *f)
case ZBD_HOST_AWARE:
case ZBD_HOST_MANAGED:
ret = parse_zone_info(td, f);
+ if (ret)
+ return ret;
break;
case ZBD_NONE:
ret = init_zone_info(td, f);
+ if (ret)
+ return ret;
break;
default:
td_verror(td, EINVAL, "Unsupported zoned model");
@@ -586,12 +663,15 @@ static int zbd_create_zone_info(struct thread_data *td, struct fio_file *f)
return -EINVAL;
}
- if (ret == 0) {
- f->zbd_info->model = zbd_model;
- f->zbd_info->max_open_zones =
- min_not_zero(td->o.max_open_zones, ZBD_MAX_OPEN_ZONES);
+ f->zbd_info->model = zbd_model;
+
+ ret = zbd_set_max_open_zones(td, f);
+ if (ret) {
+ zbd_free_zone_info(f);
+ return ret;
}
- return ret;
+
+ return 0;
}
void zbd_free_zone_info(struct fio_file *f)