X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=zbd.c;h=ee8bcb30416a0fdc12af8a9ce79d5e9d1e341427;hb=df8781b62a9d0dffae40d86916feff3659a5fb7e;hp=09ddcca42e7c011f1a7f2d30211a4b0beb227d56;hpb=a4b7f12b99e4bf011341cecafbef2caeec436d53;p=fio.git diff --git a/zbd.c b/zbd.c index 09ddcca4..ee8bcb30 100644 --- a/zbd.c +++ b/zbd.c @@ -13,10 +13,12 @@ #include #include #include + #include "file.h" #include "fio.h" #include "lib/pow2.h" #include "log.h" +#include "oslib/asprintf.h" #include "smalloc.h" #include "verify.h" #include "zbd.h" @@ -119,6 +121,30 @@ static bool zbd_verify_sizes(void) continue; if (!zbd_is_seq_job(f)) continue; + + if (!td->o.zone_size) { + td->o.zone_size = f->zbd_info->zone_size; + if (!td->o.zone_size) { + log_err("%s: invalid 0 zone size\n", + f->file_name); + return false; + } + } else if (td->o.zone_size != f->zbd_info->zone_size) { + log_err("%s: job parameter zonesize %llu does not match disk zone size %llu.\n", + f->file_name, (unsigned long long) td->o.zone_size, + (unsigned long long) f->zbd_info->zone_size); + return false; + } + + if (td->o.zone_skip && + (td->o.zone_skip < td->o.zone_size || + td->o.zone_skip % td->o.zone_size)) { + log_err("%s: zoneskip %llu is not a multiple of the device zone size %llu.\n", + f->file_name, (unsigned long long) td->o.zone_skip, + (unsigned long long) td->o.zone_size); + return false; + } + zone_idx = zbd_zone_idx(f, f->file_offset); z = &f->zbd_info->zone_info[zone_idx]; if (f->file_offset != z->start) { @@ -411,8 +437,8 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f) if (td->o.zone_size == 0) { td->o.zone_size = zone_size; } else if (td->o.zone_size != zone_size) { - log_info("fio: %s job parameter zonesize %llu does not match disk zone size %llu.\n", - f->file_name, (unsigned long long) td->o.zone_size, + log_err("fio: %s job parameter zonesize %llu does not match disk zone size %llu.\n", + f->file_name, (unsigned long long) td->o.zone_size, (unsigned long long) zone_size); ret = -EINVAL; goto close; @@ -559,7 +585,7 @@ static int zbd_init_zone_info(struct thread_data *td, struct fio_file *file) ret = zbd_create_zone_info(td, file); if (ret < 0) - td_verror(td, -ret, "BLKREPORTZONE failed"); + td_verror(td, -ret, "zbd_create_zone_info() failed"); return ret; } @@ -1219,6 +1245,65 @@ bool zbd_unaligned_write(int error_code) return false; } +/** + * setup_zbd_zone_mode - handle zoneskip as necessary for ZBD drives + * @td: FIO thread data. + * @io_u: FIO I/O unit. + * + * For sequential workloads, change the file offset to skip zoneskip bytes when + * no more IO can be performed in the current zone. + * - For read workloads, zoneskip is applied when the io has reached the end of + * the zone or the zone write position (when td->o.read_beyond_wp is false). + * - For write workloads, zoneskip is applied when the zone is full. + * This applies only to read and write operations. + */ +void setup_zbd_zone_mode(struct thread_data *td, struct io_u *io_u) +{ + struct fio_file *f = io_u->file; + enum fio_ddir ddir = io_u->ddir; + struct fio_zone_info *z; + uint32_t zone_idx; + + assert(td->o.zone_mode == ZONE_MODE_ZBD); + assert(td->o.zone_size); + + /* + * zone_skip is valid only for sequential workloads. + */ + if (td_random(td) || !td->o.zone_skip) + return; + + /* + * It is time to switch to a new zone if: + * - zone_bytes == zone_size bytes have already been accessed + * - The last position reached the end of the current zone. + * - For reads with td->o.read_beyond_wp == false, the last position + * reached the zone write pointer. + */ + zone_idx = zbd_zone_idx(f, f->last_pos[ddir]); + z = &f->zbd_info->zone_info[zone_idx]; + + if (td->zone_bytes >= td->o.zone_size || + f->last_pos[ddir] >= (z+1)->start || + (ddir == DDIR_READ && + (!td->o.read_beyond_wp) && f->last_pos[ddir] >= z->wp)) { + /* + * Skip zones. + */ + td->zone_bytes = 0; + f->file_offset += td->o.zone_size + td->o.zone_skip; + + /* + * Wrap from the beginning, if we exceed the file size + */ + if (f->file_offset >= f->real_file_size) + f->file_offset = get_start_offset(td, f); + + f->last_pos[ddir] = f->file_offset; + td->io_skip_bytes += td->o.zone_skip; + } +} + /** * zbd_adjust_block - adjust the offset and length as necessary for ZBD drives * @td: FIO thread data.