fb81b532bc37b7f9d3406442d80f24f7d8e056d9
[fio.git] / zbd.c
1 /*
2  * Copyright (C) 2018 Western Digital Corporation or its affiliates.
3  *
4  * This file is released under the GPL.
5  */
6
7 #include <errno.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <dirent.h>
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include <linux/blkzoned.h>
16 #include "file.h"
17 #include "fio.h"
18 #include "lib/pow2.h"
19 #include "log.h"
20 #include "smalloc.h"
21 #include "verify.h"
22 #include "zbd.h"
23
24 /**
25  * zbd_zone_idx - convert an offset into a zone number
26  * @f: file pointer.
27  * @offset: offset in bytes. If this offset is in the first zone_size bytes
28  *          past the disk size then the index of the sentinel is returned.
29  */
30 static uint32_t zbd_zone_idx(const struct fio_file *f, uint64_t offset)
31 {
32         uint32_t zone_idx;
33
34         if (f->zbd_info->zone_size_log2 > 0)
35                 zone_idx = offset >> f->zbd_info->zone_size_log2;
36         else
37                 zone_idx = offset / f->zbd_info->zone_size;
38
39         return min(zone_idx, f->zbd_info->nr_zones);
40 }
41
42 /**
43  * zbd_zone_full - verify whether a minimum number of bytes remain in a zone
44  * @f: file pointer.
45  * @z: zone info pointer.
46  * @required: minimum number of bytes that must remain in a zone.
47  *
48  * The caller must hold z->mutex.
49  */
50 static bool zbd_zone_full(const struct fio_file *f, struct fio_zone_info *z,
51                           uint64_t required)
52 {
53         assert((required & 511) == 0);
54
55         return z->type == BLK_ZONE_TYPE_SEQWRITE_REQ &&
56                 z->wp + required > z->start + f->zbd_info->zone_size;
57 }
58
59 static bool is_valid_offset(const struct fio_file *f, uint64_t offset)
60 {
61         return (uint64_t)(offset - f->file_offset) < f->io_size;
62 }
63
64 /* Verify whether direct I/O is used for all host-managed zoned drives. */
65 static bool zbd_using_direct_io(void)
66 {
67         struct thread_data *td;
68         struct fio_file *f;
69         int i, j;
70
71         for_each_td(td, i) {
72                 if (td->o.odirect || !(td->o.td_ddir & TD_DDIR_WRITE))
73                         continue;
74                 for_each_file(td, f, j) {
75                         if (f->zbd_info &&
76                             f->zbd_info->model == ZBD_DM_HOST_MANAGED)
77                                 return false;
78                 }
79         }
80
81         return true;
82 }
83
84 /* Whether or not the I/O range for f includes one or more sequential zones */
85 static bool zbd_is_seq_job(struct fio_file *f)
86 {
87         uint32_t zone_idx, zone_idx_b, zone_idx_e;
88
89         assert(f->zbd_info);
90         if (f->io_size == 0)
91                 return false;
92         zone_idx_b = zbd_zone_idx(f, f->file_offset);
93         zone_idx_e = zbd_zone_idx(f, f->file_offset + f->io_size - 1);
94         for (zone_idx = zone_idx_b; zone_idx <= zone_idx_e; zone_idx++)
95                 if (f->zbd_info->zone_info[zone_idx].type ==
96                     BLK_ZONE_TYPE_SEQWRITE_REQ)
97                         return true;
98
99         return false;
100 }
101
102 /*
103  * Verify whether offset and size parameters are aligned with zone boundaries.
104  */
105 static bool zbd_verify_sizes(void)
106 {
107         const struct fio_zone_info *z;
108         struct thread_data *td;
109         struct fio_file *f;
110         uint64_t new_offset, new_end;
111         uint32_t zone_idx;
112         int i, j;
113
114         for_each_td(td, i) {
115                 for_each_file(td, f, j) {
116                         if (!f->zbd_info)
117                                 continue;
118                         if (f->file_offset >= f->real_file_size)
119                                 continue;
120                         if (!zbd_is_seq_job(f))
121                                 continue;
122
123                         if (td->o.zone_skip &&
124                             (td->o.zone_skip < td->o.zone_size ||
125                              td->o.zone_skip % td->o.zone_size)) {
126                                 log_err("%s: zoneskip %llu is not a multiple of the device zone size %llu.\n",
127                                         f->file_name, (unsigned long long) td->o.zone_skip,
128                                         (unsigned long long) td->o.zone_size);
129                                 return false;
130                         }
131
132                         zone_idx = zbd_zone_idx(f, f->file_offset);
133                         z = &f->zbd_info->zone_info[zone_idx];
134                         if (f->file_offset != z->start) {
135                                 new_offset = (z+1)->start;
136                                 if (new_offset >= f->file_offset + f->io_size) {
137                                         log_info("%s: io_size must be at least one zone\n",
138                                                  f->file_name);
139                                         return false;
140                                 }
141                                 log_info("%s: rounded up offset from %llu to %llu\n",
142                                          f->file_name, (unsigned long long) f->file_offset,
143                                          (unsigned long long) new_offset);
144                                 f->io_size -= (new_offset - f->file_offset);
145                                 f->file_offset = new_offset;
146                         }
147                         zone_idx = zbd_zone_idx(f, f->file_offset + f->io_size);
148                         z = &f->zbd_info->zone_info[zone_idx];
149                         new_end = z->start;
150                         if (f->file_offset + f->io_size != new_end) {
151                                 if (new_end <= f->file_offset) {
152                                         log_info("%s: io_size must be at least one zone\n",
153                                                  f->file_name);
154                                         return false;
155                                 }
156                                 log_info("%s: rounded down io_size from %llu to %llu\n",
157                                          f->file_name, (unsigned long long) f->io_size,
158                                          (unsigned long long) new_end - f->file_offset);
159                                 f->io_size = new_end - f->file_offset;
160                         }
161                 }
162         }
163
164         return true;
165 }
166
167 static bool zbd_verify_bs(void)
168 {
169         struct thread_data *td;
170         struct fio_file *f;
171         uint32_t zone_size;
172         int i, j, k;
173
174         for_each_td(td, i) {
175                 for_each_file(td, f, j) {
176                         if (!f->zbd_info)
177                                 continue;
178                         zone_size = f->zbd_info->zone_size;
179                         for (k = 0; k < ARRAY_SIZE(td->o.bs); k++) {
180                                 if (td->o.verify != VERIFY_NONE &&
181                                     zone_size % td->o.bs[k] != 0) {
182                                         log_info("%s: block size %llu is not a divisor of the zone size %d\n",
183                                                  f->file_name, td->o.bs[k],
184                                                  zone_size);
185                                         return false;
186                                 }
187                         }
188                 }
189         }
190         return true;
191 }
192
193 /*
194  * Read zone information into @buf starting from sector @start_sector.
195  * @fd is a file descriptor that refers to a block device and @bufsz is the
196  * size of @buf.
197  *
198  * Returns 0 upon success and a negative error code upon failure.
199  * If the zone report is empty, always assume an error (device problem) and
200  * return -EIO.
201  */
202 static int read_zone_info(int fd, uint64_t start_sector,
203                           void *buf, unsigned int bufsz)
204 {
205         struct blk_zone_report *hdr = buf;
206         int ret;
207
208         if (bufsz < sizeof(*hdr))
209                 return -EINVAL;
210
211         memset(hdr, 0, sizeof(*hdr));
212
213         hdr->nr_zones = (bufsz - sizeof(*hdr)) / sizeof(struct blk_zone);
214         hdr->sector = start_sector;
215         ret = ioctl(fd, BLKREPORTZONE, hdr);
216         if (ret)
217                 return -errno;
218         if (!hdr->nr_zones)
219                 return -EIO;
220         return 0;
221 }
222
223 /*
224  * Read up to 255 characters from the first line of a file. Strip the trailing
225  * newline.
226  */
227 static char *read_file(const char *path)
228 {
229         char line[256], *p = line;
230         FILE *f;
231
232         f = fopen(path, "rb");
233         if (!f)
234                 return NULL;
235         if (!fgets(line, sizeof(line), f))
236                 line[0] = '\0';
237         strsep(&p, "\n");
238         fclose(f);
239
240         return strdup(line);
241 }
242
243 static enum blk_zoned_model get_zbd_model(const char *file_name)
244 {
245         enum blk_zoned_model model = ZBD_DM_NONE;
246         char *zoned_attr_path = NULL;
247         char *model_str = NULL;
248         struct stat statbuf;
249         char *sys_devno_path = NULL;
250         char *part_attr_path = NULL;
251         char *part_str = NULL;
252         char sys_path[PATH_MAX];
253         ssize_t sz;
254         char *delim = NULL;
255
256         if (stat(file_name, &statbuf) < 0)
257                 goto out;
258
259         if (asprintf(&sys_devno_path, "/sys/dev/block/%d:%d",
260                      major(statbuf.st_rdev), minor(statbuf.st_rdev)) < 0)
261                 goto out;
262
263         sz = readlink(sys_devno_path, sys_path, sizeof(sys_path) - 1);
264         if (sz < 0)
265                 goto out;
266         sys_path[sz] = '\0';
267
268         /*
269          * If the device is a partition device, cut the device name in the
270          * canonical sysfs path to obtain the sysfs path of the holder device.
271          *   e.g.:  /sys/devices/.../sda/sda1 -> /sys/devices/.../sda
272          */
273         if (asprintf(&part_attr_path, "/sys/dev/block/%s/partition",
274                      sys_path) < 0)
275                 goto out;
276         part_str = read_file(part_attr_path);
277         if (part_str && *part_str == '1') {
278                 delim = strrchr(sys_path, '/');
279                 if (!delim)
280                         goto out;
281                 *delim = '\0';
282         }
283
284         if (asprintf(&zoned_attr_path,
285                      "/sys/dev/block/%s/queue/zoned", sys_path) < 0)
286                 goto out;
287
288         model_str = read_file(zoned_attr_path);
289         if (!model_str)
290                 goto out;
291         dprint(FD_ZBD, "%s: zbd model string: %s\n", file_name, model_str);
292         if (strcmp(model_str, "host-aware") == 0)
293                 model = ZBD_DM_HOST_AWARE;
294         else if (strcmp(model_str, "host-managed") == 0)
295                 model = ZBD_DM_HOST_MANAGED;
296
297 out:
298         free(model_str);
299         free(zoned_attr_path);
300         free(part_str);
301         free(part_attr_path);
302         free(sys_devno_path);
303         return model;
304 }
305
306 static int ilog2(uint64_t i)
307 {
308         int log = -1;
309
310         while (i) {
311                 i >>= 1;
312                 log++;
313         }
314         return log;
315 }
316
317 /*
318  * Initialize f->zbd_info for devices that are not zoned block devices. This
319  * allows to execute a ZBD workload against a non-ZBD device.
320  */
321 static int init_zone_info(struct thread_data *td, struct fio_file *f)
322 {
323         uint32_t nr_zones;
324         struct fio_zone_info *p;
325         uint64_t zone_size = td->o.zone_size;
326         struct zoned_block_device_info *zbd_info = NULL;
327         pthread_mutexattr_t attr;
328         int i;
329
330         if (zone_size == 0) {
331                 log_err("%s: Specifying the zone size is mandatory for regular block devices with --zonemode=zbd\n\n",
332                         f->file_name);
333                 return 1;
334         }
335
336         if (zone_size < 512) {
337                 log_err("%s: zone size must be at least 512 bytes for --zonemode=zbd\n\n",
338                         f->file_name);
339                 return 1;
340         }
341
342         nr_zones = (f->real_file_size + zone_size - 1) / zone_size;
343         zbd_info = scalloc(1, sizeof(*zbd_info) +
344                            (nr_zones + 1) * sizeof(zbd_info->zone_info[0]));
345         if (!zbd_info)
346                 return -ENOMEM;
347
348         pthread_mutexattr_init(&attr);
349         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
350         pthread_mutexattr_setpshared(&attr, true);
351         pthread_mutex_init(&zbd_info->mutex, &attr);
352         zbd_info->refcount = 1;
353         p = &zbd_info->zone_info[0];
354         for (i = 0; i < nr_zones; i++, p++) {
355                 pthread_mutex_init(&p->mutex, &attr);
356                 p->start = i * zone_size;
357                 p->wp = p->start + zone_size;
358                 p->type = BLK_ZONE_TYPE_SEQWRITE_REQ;
359                 p->cond = BLK_ZONE_COND_EMPTY;
360         }
361         /* a sentinel */
362         p->start = nr_zones * zone_size;
363
364         f->zbd_info = zbd_info;
365         f->zbd_info->zone_size = zone_size;
366         f->zbd_info->zone_size_log2 = is_power_of_2(zone_size) ?
367                 ilog2(zone_size) : -1;
368         f->zbd_info->nr_zones = nr_zones;
369         pthread_mutexattr_destroy(&attr);
370         return 0;
371 }
372
373 /*
374  * Parse the BLKREPORTZONE output and store it in f->zbd_info. Must be called
375  * only for devices that support this ioctl, namely zoned block devices.
376  */
377 static int parse_zone_info(struct thread_data *td, struct fio_file *f)
378 {
379         const unsigned int bufsz = sizeof(struct blk_zone_report) +
380                 4096 * sizeof(struct blk_zone);
381         uint32_t nr_zones;
382         struct blk_zone_report *hdr;
383         const struct blk_zone *z;
384         struct fio_zone_info *p;
385         uint64_t zone_size, start_sector;
386         struct zoned_block_device_info *zbd_info = NULL;
387         pthread_mutexattr_t attr;
388         void *buf;
389         int fd, i, j, ret = 0;
390
391         pthread_mutexattr_init(&attr);
392         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
393         pthread_mutexattr_setpshared(&attr, true);
394
395         buf = malloc(bufsz);
396         if (!buf)
397                 goto out;
398
399         fd = open(f->file_name, O_RDONLY | O_LARGEFILE);
400         if (fd < 0) {
401                 ret = -errno;
402                 goto free;
403         }
404
405         ret = read_zone_info(fd, 0, buf, bufsz);
406         if (ret < 0) {
407                 log_info("fio: BLKREPORTZONE(%lu) failed for %s (%d).\n",
408                          0UL, f->file_name, -ret);
409                 goto close;
410         }
411         hdr = buf;
412         if (hdr->nr_zones < 1) {
413                 log_info("fio: %s has invalid zone information.\n",
414                          f->file_name);
415                 goto close;
416         }
417         z = (void *)(hdr + 1);
418         zone_size = z->len << 9;
419         nr_zones = (f->real_file_size + zone_size - 1) / zone_size;
420
421         if (td->o.zone_size == 0) {
422                 td->o.zone_size = zone_size;
423         } else if (td->o.zone_size != zone_size) {
424                 log_err("fio: %s job parameter zonesize %llu does not match disk zone size %llu.\n",
425                         f->file_name, (unsigned long long) td->o.zone_size,
426                         (unsigned long long) zone_size);
427                 ret = -EINVAL;
428                 goto close;
429         }
430
431         dprint(FD_ZBD, "Device %s has %d zones of size %llu KB\n", f->file_name,
432                nr_zones, (unsigned long long) zone_size / 1024);
433
434         zbd_info = scalloc(1, sizeof(*zbd_info) +
435                            (nr_zones + 1) * sizeof(zbd_info->zone_info[0]));
436         ret = -ENOMEM;
437         if (!zbd_info)
438                 goto close;
439         pthread_mutex_init(&zbd_info->mutex, &attr);
440         zbd_info->refcount = 1;
441         p = &zbd_info->zone_info[0];
442         for (start_sector = 0, j = 0; j < nr_zones;) {
443                 z = (void *)(hdr + 1);
444                 for (i = 0; i < hdr->nr_zones; i++, j++, z++, p++) {
445                         pthread_mutex_init(&p->mutex, &attr);
446                         p->start = z->start << 9;
447                         switch (z->cond) {
448                         case BLK_ZONE_COND_NOT_WP:
449                         case BLK_ZONE_COND_FULL:
450                                 p->wp = p->start + zone_size;
451                                 break;
452                         default:
453                                 assert(z->start <= z->wp);
454                                 assert(z->wp <= z->start + (zone_size >> 9));
455                                 p->wp = z->wp << 9;
456                                 break;
457                         }
458                         p->type = z->type;
459                         p->cond = z->cond;
460                         if (j > 0 && p->start != p[-1].start + zone_size) {
461                                 log_info("%s: invalid zone data\n",
462                                          f->file_name);
463                                 ret = -EINVAL;
464                                 goto close;
465                         }
466                 }
467                 z--;
468                 start_sector = z->start + z->len;
469                 if (j >= nr_zones)
470                         break;
471                 ret = read_zone_info(fd, start_sector, buf, bufsz);
472                 if (ret < 0) {
473                         log_info("fio: BLKREPORTZONE(%llu) failed for %s (%d).\n",
474                                  (unsigned long long) start_sector, f->file_name, -ret);
475                         goto close;
476                 }
477         }
478         /* a sentinel */
479         zbd_info->zone_info[nr_zones].start = start_sector << 9;
480
481         f->zbd_info = zbd_info;
482         f->zbd_info->zone_size = zone_size;
483         f->zbd_info->zone_size_log2 = is_power_of_2(zone_size) ?
484                 ilog2(zone_size) : -1;
485         f->zbd_info->nr_zones = nr_zones;
486         zbd_info = NULL;
487         ret = 0;
488
489 close:
490         sfree(zbd_info);
491         close(fd);
492 free:
493         free(buf);
494 out:
495         pthread_mutexattr_destroy(&attr);
496         return ret;
497 }
498
499 /*
500  * Allocate zone information and store it into f->zbd_info if zonemode=zbd.
501  *
502  * Returns 0 upon success and a negative error code upon failure.
503  */
504 static int zbd_create_zone_info(struct thread_data *td, struct fio_file *f)
505 {
506         enum blk_zoned_model zbd_model;
507         int ret = 0;
508
509         assert(td->o.zone_mode == ZONE_MODE_ZBD);
510
511         zbd_model = get_zbd_model(f->file_name);
512         switch (zbd_model) {
513         case ZBD_DM_HOST_AWARE:
514         case ZBD_DM_HOST_MANAGED:
515                 ret = parse_zone_info(td, f);
516                 break;
517         case ZBD_DM_NONE:
518                 ret = init_zone_info(td, f);
519                 break;
520         }
521         if (ret == 0)
522                 f->zbd_info->model = zbd_model;
523         return ret;
524 }
525
526 void zbd_free_zone_info(struct fio_file *f)
527 {
528         uint32_t refcount;
529
530         if (!f->zbd_info)
531                 return;
532
533         pthread_mutex_lock(&f->zbd_info->mutex);
534         refcount = --f->zbd_info->refcount;
535         pthread_mutex_unlock(&f->zbd_info->mutex);
536
537         assert((int32_t)refcount >= 0);
538         if (refcount == 0)
539                 sfree(f->zbd_info);
540         f->zbd_info = NULL;
541 }
542
543 /*
544  * Initialize f->zbd_info.
545  *
546  * Returns 0 upon success and a negative error code upon failure.
547  *
548  * Note: this function can only work correctly if it is called before the first
549  * fio fork() call.
550  */
551 static int zbd_init_zone_info(struct thread_data *td, struct fio_file *file)
552 {
553         struct thread_data *td2;
554         struct fio_file *f2;
555         int i, j, ret;
556
557         for_each_td(td2, i) {
558                 for_each_file(td2, f2, j) {
559                         if (td2 == td && f2 == file)
560                                 continue;
561                         if (!f2->zbd_info ||
562                             strcmp(f2->file_name, file->file_name) != 0)
563                                 continue;
564                         file->zbd_info = f2->zbd_info;
565                         file->zbd_info->refcount++;
566                         return 0;
567                 }
568         }
569
570         ret = zbd_create_zone_info(td, file);
571         if (ret < 0)
572                 td_verror(td, -ret, "zbd_create_zone_info() failed");
573         return ret;
574 }
575
576 int zbd_init(struct thread_data *td)
577 {
578         struct fio_file *f;
579         int i;
580
581         for_each_file(td, f, i) {
582                 if (f->filetype != FIO_TYPE_BLOCK)
583                         continue;
584                 if (zbd_init_zone_info(td, f))
585                         return 1;
586         }
587
588         if (!zbd_using_direct_io()) {
589                 log_err("Using direct I/O is mandatory for writing to ZBD drives\n\n");
590                 return 1;
591         }
592
593         if (!zbd_verify_sizes())
594                 return 1;
595
596         if (!zbd_verify_bs())
597                 return 1;
598
599         return 0;
600 }
601
602 /**
603  * zbd_reset_range - reset zones for a range of sectors
604  * @td: FIO thread data.
605  * @f: Fio file for which to reset zones
606  * @sector: Starting sector in units of 512 bytes
607  * @nr_sectors: Number of sectors in units of 512 bytes
608  *
609  * Returns 0 upon success and a negative error code upon failure.
610  */
611 static int zbd_reset_range(struct thread_data *td, const struct fio_file *f,
612                            uint64_t offset, uint64_t length)
613 {
614         struct blk_zone_range zr = {
615                 .sector         = offset >> 9,
616                 .nr_sectors     = length >> 9,
617         };
618         uint32_t zone_idx_b, zone_idx_e;
619         struct fio_zone_info *zb, *ze, *z;
620         int ret = 0;
621
622         assert(f->fd != -1);
623         assert(is_valid_offset(f, offset + length - 1));
624         switch (f->zbd_info->model) {
625         case ZBD_DM_HOST_AWARE:
626         case ZBD_DM_HOST_MANAGED:
627                 ret = ioctl(f->fd, BLKRESETZONE, &zr);
628                 if (ret < 0) {
629                         td_verror(td, errno, "resetting wp failed");
630                         log_err("%s: resetting wp for %llu sectors at sector %llu failed (%d).\n",
631                                 f->file_name, zr.nr_sectors, zr.sector, errno);
632                         return ret;
633                 }
634                 break;
635         case ZBD_DM_NONE:
636                 break;
637         }
638
639         zone_idx_b = zbd_zone_idx(f, offset);
640         zb = &f->zbd_info->zone_info[zone_idx_b];
641         zone_idx_e = zbd_zone_idx(f, offset + length);
642         ze = &f->zbd_info->zone_info[zone_idx_e];
643         for (z = zb; z < ze; z++) {
644                 pthread_mutex_lock(&z->mutex);
645                 pthread_mutex_lock(&f->zbd_info->mutex);
646                 f->zbd_info->sectors_with_data -= z->wp - z->start;
647                 pthread_mutex_unlock(&f->zbd_info->mutex);
648                 z->wp = z->start;
649                 z->verify_block = 0;
650                 pthread_mutex_unlock(&z->mutex);
651         }
652
653         td->ts.nr_zone_resets += ze - zb;
654
655         return ret;
656 }
657
658 static unsigned int zbd_zone_nr(struct zoned_block_device_info *zbd_info,
659                                 struct fio_zone_info *zone)
660 {
661         return zone - zbd_info->zone_info;
662 }
663
664 /**
665  * zbd_reset_zone - reset the write pointer of a single zone
666  * @td: FIO thread data.
667  * @f: FIO file associated with the disk for which to reset a write pointer.
668  * @z: Zone to reset.
669  *
670  * Returns 0 upon success and a negative error code upon failure.
671  */
672 static int zbd_reset_zone(struct thread_data *td, const struct fio_file *f,
673                           struct fio_zone_info *z)
674 {
675         dprint(FD_ZBD, "%s: resetting wp of zone %u.\n", f->file_name,
676                 zbd_zone_nr(f->zbd_info, z));
677
678         return zbd_reset_range(td, f, z->start, (z+1)->start - z->start);
679 }
680
681 /*
682  * Reset a range of zones. Returns 0 upon success and 1 upon failure.
683  * @td: fio thread data.
684  * @f: fio file for which to reset zones
685  * @zb: first zone to reset.
686  * @ze: first zone not to reset.
687  * @all_zones: whether to reset all zones or only those zones for which the
688  *      write pointer is not a multiple of td->o.min_bs[DDIR_WRITE].
689  */
690 static int zbd_reset_zones(struct thread_data *td, struct fio_file *f,
691                            struct fio_zone_info *const zb,
692                            struct fio_zone_info *const ze, bool all_zones)
693 {
694         struct fio_zone_info *z, *start_z = ze;
695         const uint32_t min_bs = td->o.min_bs[DDIR_WRITE];
696         bool reset_wp;
697         int res = 0;
698
699         dprint(FD_ZBD, "%s: examining zones %u .. %u\n", f->file_name,
700                 zbd_zone_nr(f->zbd_info, zb), zbd_zone_nr(f->zbd_info, ze));
701         assert(f->fd != -1);
702         for (z = zb; z < ze; z++) {
703                 pthread_mutex_lock(&z->mutex);
704                 switch (z->type) {
705                 case BLK_ZONE_TYPE_SEQWRITE_REQ:
706                         reset_wp = all_zones ? z->wp != z->start :
707                                         (td->o.td_ddir & TD_DDIR_WRITE) &&
708                                         z->wp % min_bs != 0;
709                         if (start_z == ze && reset_wp) {
710                                 start_z = z;
711                         } else if (start_z < ze && !reset_wp) {
712                                 dprint(FD_ZBD,
713                                        "%s: resetting zones %u .. %u\n",
714                                        f->file_name,
715                                         zbd_zone_nr(f->zbd_info, start_z),
716                                         zbd_zone_nr(f->zbd_info, z));
717                                 if (zbd_reset_range(td, f, start_z->start,
718                                                 z->start - start_z->start) < 0)
719                                         res = 1;
720                                 start_z = ze;
721                         }
722                         break;
723                 default:
724                         if (start_z == ze)
725                                 break;
726                         dprint(FD_ZBD, "%s: resetting zones %u .. %u\n",
727                                f->file_name, zbd_zone_nr(f->zbd_info, start_z),
728                                zbd_zone_nr(f->zbd_info, z));
729                         if (zbd_reset_range(td, f, start_z->start,
730                                             z->start - start_z->start) < 0)
731                                 res = 1;
732                         start_z = ze;
733                         break;
734                 }
735         }
736         if (start_z < ze) {
737                 dprint(FD_ZBD, "%s: resetting zones %u .. %u\n", f->file_name,
738                         zbd_zone_nr(f->zbd_info, start_z),
739                         zbd_zone_nr(f->zbd_info, z));
740                 if (zbd_reset_range(td, f, start_z->start,
741                                     z->start - start_z->start) < 0)
742                         res = 1;
743         }
744         for (z = zb; z < ze; z++)
745                 pthread_mutex_unlock(&z->mutex);
746
747         return res;
748 }
749
750 /*
751  * Reset zbd_info.write_cnt, the counter that counts down towards the next
752  * zone reset.
753  */
754 static void zbd_reset_write_cnt(const struct thread_data *td,
755                                 const struct fio_file *f)
756 {
757         assert(0 <= td->o.zrf.u.f && td->o.zrf.u.f <= 1);
758
759         pthread_mutex_lock(&f->zbd_info->mutex);
760         f->zbd_info->write_cnt = td->o.zrf.u.f ?
761                 min(1.0 / td->o.zrf.u.f, 0.0 + UINT_MAX) : UINT_MAX;
762         pthread_mutex_unlock(&f->zbd_info->mutex);
763 }
764
765 static bool zbd_dec_and_reset_write_cnt(const struct thread_data *td,
766                                         const struct fio_file *f)
767 {
768         uint32_t write_cnt = 0;
769
770         pthread_mutex_lock(&f->zbd_info->mutex);
771         assert(f->zbd_info->write_cnt);
772         if (f->zbd_info->write_cnt)
773                 write_cnt = --f->zbd_info->write_cnt;
774         if (write_cnt == 0)
775                 zbd_reset_write_cnt(td, f);
776         pthread_mutex_unlock(&f->zbd_info->mutex);
777
778         return write_cnt == 0;
779 }
780
781 enum swd_action {
782         CHECK_SWD,
783         SET_SWD,
784 };
785
786 /* Calculate the number of sectors with data (swd) and perform action 'a' */
787 static uint64_t zbd_process_swd(const struct fio_file *f, enum swd_action a)
788 {
789         struct fio_zone_info *zb, *ze, *z;
790         uint64_t swd = 0;
791
792         zb = &f->zbd_info->zone_info[zbd_zone_idx(f, f->file_offset)];
793         ze = &f->zbd_info->zone_info[zbd_zone_idx(f, f->file_offset +
794                                                   f->io_size)];
795         for (z = zb; z < ze; z++) {
796                 pthread_mutex_lock(&z->mutex);
797                 swd += z->wp - z->start;
798         }
799         pthread_mutex_lock(&f->zbd_info->mutex);
800         switch (a) {
801         case CHECK_SWD:
802                 assert(f->zbd_info->sectors_with_data == swd);
803                 break;
804         case SET_SWD:
805                 f->zbd_info->sectors_with_data = swd;
806                 break;
807         }
808         pthread_mutex_unlock(&f->zbd_info->mutex);
809         for (z = zb; z < ze; z++)
810                 pthread_mutex_unlock(&z->mutex);
811
812         return swd;
813 }
814
815 /*
816  * The swd check is useful for debugging but takes too much time to leave
817  * it enabled all the time. Hence it is disabled by default.
818  */
819 static const bool enable_check_swd = false;
820
821 /* Check whether the value of zbd_info.sectors_with_data is correct. */
822 static void zbd_check_swd(const struct fio_file *f)
823 {
824         if (!enable_check_swd)
825                 return;
826
827         zbd_process_swd(f, CHECK_SWD);
828 }
829
830 static void zbd_init_swd(struct fio_file *f)
831 {
832         uint64_t swd;
833
834         swd = zbd_process_swd(f, SET_SWD);
835         dprint(FD_ZBD, "%s(%s): swd = %" PRIu64 "\n", __func__, f->file_name,
836                swd);
837 }
838
839 void zbd_file_reset(struct thread_data *td, struct fio_file *f)
840 {
841         struct fio_zone_info *zb, *ze;
842         uint32_t zone_idx_e;
843
844         if (!f->zbd_info)
845                 return;
846
847         zb = &f->zbd_info->zone_info[zbd_zone_idx(f, f->file_offset)];
848         zone_idx_e = zbd_zone_idx(f, f->file_offset + f->io_size);
849         ze = &f->zbd_info->zone_info[zone_idx_e];
850         zbd_init_swd(f);
851         /*
852          * If data verification is enabled reset the affected zones before
853          * writing any data to avoid that a zone reset has to be issued while
854          * writing data, which causes data loss.
855          */
856         zbd_reset_zones(td, f, zb, ze, td->o.verify != VERIFY_NONE &&
857                         (td->o.td_ddir & TD_DDIR_WRITE) &&
858                         td->runstate != TD_VERIFYING);
859         zbd_reset_write_cnt(td, f);
860 }
861
862 /* The caller must hold f->zbd_info->mutex. */
863 static bool is_zone_open(const struct thread_data *td, const struct fio_file *f,
864                          unsigned int zone_idx)
865 {
866         struct zoned_block_device_info *zbdi = f->zbd_info;
867         int i;
868
869         assert(td->o.max_open_zones <= ARRAY_SIZE(zbdi->open_zones));
870         assert(zbdi->num_open_zones <= td->o.max_open_zones);
871
872         for (i = 0; i < zbdi->num_open_zones; i++)
873                 if (zbdi->open_zones[i] == zone_idx)
874                         return true;
875
876         return false;
877 }
878
879 /*
880  * Open a ZBD zone if it was not yet open. Returns true if either the zone was
881  * already open or if opening a new zone is allowed. Returns false if the zone
882  * was not yet open and opening a new zone would cause the zone limit to be
883  * exceeded.
884  */
885 static bool zbd_open_zone(struct thread_data *td, const struct io_u *io_u,
886                           uint32_t zone_idx)
887 {
888         const uint32_t min_bs = td->o.min_bs[DDIR_WRITE];
889         const struct fio_file *f = io_u->file;
890         struct fio_zone_info *z = &f->zbd_info->zone_info[zone_idx];
891         bool res = true;
892
893         if (z->cond == BLK_ZONE_COND_OFFLINE)
894                 return false;
895
896         /*
897          * Skip full zones with data verification enabled because resetting a
898          * zone causes data loss and hence causes verification to fail.
899          */
900         if (td->o.verify != VERIFY_NONE && zbd_zone_full(f, z, min_bs))
901                 return false;
902
903         /* Zero means no limit */
904         if (!td->o.max_open_zones)
905                 return true;
906
907         pthread_mutex_lock(&f->zbd_info->mutex);
908         if (is_zone_open(td, f, zone_idx))
909                 goto out;
910         res = false;
911         if (f->zbd_info->num_open_zones >= td->o.max_open_zones)
912                 goto out;
913         dprint(FD_ZBD, "%s: opening zone %d\n", f->file_name, zone_idx);
914         f->zbd_info->open_zones[f->zbd_info->num_open_zones++] = zone_idx;
915         z->open = 1;
916         res = true;
917
918 out:
919         pthread_mutex_unlock(&f->zbd_info->mutex);
920         return res;
921 }
922
923 /* The caller must hold f->zbd_info->mutex */
924 static void zbd_close_zone(struct thread_data *td, const struct fio_file *f,
925                            unsigned int open_zone_idx)
926 {
927         uint32_t zone_idx;
928
929         assert(open_zone_idx < f->zbd_info->num_open_zones);
930         zone_idx = f->zbd_info->open_zones[open_zone_idx];
931         memmove(f->zbd_info->open_zones + open_zone_idx,
932                 f->zbd_info->open_zones + open_zone_idx + 1,
933                 (FIO_MAX_OPEN_ZBD_ZONES - (open_zone_idx + 1)) *
934                 sizeof(f->zbd_info->open_zones[0]));
935         f->zbd_info->num_open_zones--;
936         f->zbd_info->zone_info[zone_idx].open = 0;
937 }
938
939 /*
940  * Modify the offset of an I/O unit that does not refer to an open zone such
941  * that it refers to an open zone. Close an open zone and open a new zone if
942  * necessary. This algorithm can only work correctly if all write pointers are
943  * a multiple of the fio block size. The caller must neither hold z->mutex
944  * nor f->zbd_info->mutex. Returns with z->mutex held upon success.
945  */
946 static struct fio_zone_info *zbd_convert_to_open_zone(struct thread_data *td,
947                                                       struct io_u *io_u)
948 {
949         const uint32_t min_bs = td->o.min_bs[io_u->ddir];
950         const struct fio_file *f = io_u->file;
951         struct fio_zone_info *z;
952         unsigned int open_zone_idx = -1;
953         uint32_t zone_idx, new_zone_idx;
954         int i;
955
956         assert(is_valid_offset(f, io_u->offset));
957
958         if (td->o.max_open_zones) {
959                 /*
960                  * This statement accesses f->zbd_info->open_zones[] on purpose
961                  * without locking.
962                  */
963                 zone_idx = f->zbd_info->open_zones[(io_u->offset -
964                                                     f->file_offset) *
965                                 f->zbd_info->num_open_zones / f->io_size];
966         } else {
967                 zone_idx = zbd_zone_idx(f, io_u->offset);
968         }
969         dprint(FD_ZBD, "%s(%s): starting from zone %d (offset %lld, buflen %lld)\n",
970                __func__, f->file_name, zone_idx, io_u->offset, io_u->buflen);
971
972         /*
973          * Since z->mutex is the outer lock and f->zbd_info->mutex the inner
974          * lock it can happen that the state of the zone with index zone_idx
975          * has changed after 'z' has been assigned and before f->zbd_info->mutex
976          * has been obtained. Hence the loop.
977          */
978         for (;;) {
979                 z = &f->zbd_info->zone_info[zone_idx];
980
981                 pthread_mutex_lock(&z->mutex);
982                 pthread_mutex_lock(&f->zbd_info->mutex);
983                 if (td->o.max_open_zones == 0)
984                         goto examine_zone;
985                 if (f->zbd_info->num_open_zones == 0) {
986                         pthread_mutex_unlock(&f->zbd_info->mutex);
987                         pthread_mutex_unlock(&z->mutex);
988                         dprint(FD_ZBD, "%s(%s): no zones are open\n",
989                                __func__, f->file_name);
990                         return NULL;
991                 }
992                 open_zone_idx = (io_u->offset - f->file_offset) *
993                         f->zbd_info->num_open_zones / f->io_size;
994                 assert(open_zone_idx < f->zbd_info->num_open_zones);
995                 new_zone_idx = f->zbd_info->open_zones[open_zone_idx];
996                 if (new_zone_idx == zone_idx)
997                         break;
998                 zone_idx = new_zone_idx;
999                 pthread_mutex_unlock(&f->zbd_info->mutex);
1000                 pthread_mutex_unlock(&z->mutex);
1001         }
1002
1003         /* Both z->mutex and f->zbd_info->mutex are held. */
1004
1005 examine_zone:
1006         if (z->wp + min_bs <= (z+1)->start) {
1007                 pthread_mutex_unlock(&f->zbd_info->mutex);
1008                 goto out;
1009         }
1010         dprint(FD_ZBD, "%s(%s): closing zone %d\n", __func__, f->file_name,
1011                zone_idx);
1012         if (td->o.max_open_zones)
1013                 zbd_close_zone(td, f, open_zone_idx);
1014         pthread_mutex_unlock(&f->zbd_info->mutex);
1015
1016         /* Only z->mutex is held. */
1017
1018         /* Zone 'z' is full, so try to open a new zone. */
1019         for (i = f->io_size / f->zbd_info->zone_size; i > 0; i--) {
1020                 zone_idx++;
1021                 pthread_mutex_unlock(&z->mutex);
1022                 z++;
1023                 if (!is_valid_offset(f, z->start)) {
1024                         /* Wrap-around. */
1025                         zone_idx = zbd_zone_idx(f, f->file_offset);
1026                         z = &f->zbd_info->zone_info[zone_idx];
1027                 }
1028                 assert(is_valid_offset(f, z->start));
1029                 pthread_mutex_lock(&z->mutex);
1030                 if (z->open)
1031                         continue;
1032                 if (zbd_open_zone(td, io_u, zone_idx))
1033                         goto out;
1034         }
1035
1036         /* Only z->mutex is held. */
1037
1038         /* Check whether the write fits in any of the already opened zones. */
1039         pthread_mutex_lock(&f->zbd_info->mutex);
1040         for (i = 0; i < f->zbd_info->num_open_zones; i++) {
1041                 zone_idx = f->zbd_info->open_zones[i];
1042                 pthread_mutex_unlock(&f->zbd_info->mutex);
1043                 pthread_mutex_unlock(&z->mutex);
1044
1045                 z = &f->zbd_info->zone_info[zone_idx];
1046
1047                 pthread_mutex_lock(&z->mutex);
1048                 if (z->wp + min_bs <= (z+1)->start)
1049                         goto out;
1050                 pthread_mutex_lock(&f->zbd_info->mutex);
1051         }
1052         pthread_mutex_unlock(&f->zbd_info->mutex);
1053         pthread_mutex_unlock(&z->mutex);
1054         dprint(FD_ZBD, "%s(%s): did not open another zone\n", __func__,
1055                f->file_name);
1056         return NULL;
1057
1058 out:
1059         dprint(FD_ZBD, "%s(%s): returning zone %d\n", __func__, f->file_name,
1060                zone_idx);
1061         io_u->offset = z->start;
1062         return z;
1063 }
1064
1065 /* The caller must hold z->mutex. */
1066 static struct fio_zone_info *zbd_replay_write_order(struct thread_data *td,
1067                                                     struct io_u *io_u,
1068                                                     struct fio_zone_info *z)
1069 {
1070         const struct fio_file *f = io_u->file;
1071         const uint32_t min_bs = td->o.min_bs[DDIR_WRITE];
1072
1073         if (!zbd_open_zone(td, io_u, z - f->zbd_info->zone_info)) {
1074                 pthread_mutex_unlock(&z->mutex);
1075                 z = zbd_convert_to_open_zone(td, io_u);
1076                 assert(z);
1077         }
1078
1079         if (z->verify_block * min_bs >= f->zbd_info->zone_size)
1080                 log_err("%s: %d * %d >= %llu\n", f->file_name, z->verify_block,
1081                         min_bs, (unsigned long long) f->zbd_info->zone_size);
1082         io_u->offset = z->start + z->verify_block++ * min_bs;
1083         return z;
1084 }
1085
1086 /*
1087  * Find another zone for which @io_u fits below the write pointer. Start
1088  * searching in zones @zb + 1 .. @zl and continue searching in zones
1089  * @zf .. @zb - 1.
1090  *
1091  * Either returns NULL or returns a zone pointer and holds the mutex for that
1092  * zone.
1093  */
1094 static struct fio_zone_info *
1095 zbd_find_zone(struct thread_data *td, struct io_u *io_u,
1096               struct fio_zone_info *zb, struct fio_zone_info *zl)
1097 {
1098         const uint32_t min_bs = td->o.min_bs[io_u->ddir];
1099         const struct fio_file *f = io_u->file;
1100         struct fio_zone_info *z1, *z2;
1101         const struct fio_zone_info *const zf =
1102                 &f->zbd_info->zone_info[zbd_zone_idx(f, f->file_offset)];
1103
1104         /*
1105          * Skip to the next non-empty zone in case of sequential I/O and to
1106          * the nearest non-empty zone in case of random I/O.
1107          */
1108         for (z1 = zb + 1, z2 = zb - 1; z1 < zl || z2 >= zf; z1++, z2--) {
1109                 if (z1 < zl && z1->cond != BLK_ZONE_COND_OFFLINE) {
1110                         pthread_mutex_lock(&z1->mutex);
1111                         if (z1->start + min_bs <= z1->wp)
1112                                 return z1;
1113                         pthread_mutex_unlock(&z1->mutex);
1114                 } else if (!td_random(td)) {
1115                         break;
1116                 }
1117                 if (td_random(td) && z2 >= zf &&
1118                     z2->cond != BLK_ZONE_COND_OFFLINE) {
1119                         pthread_mutex_lock(&z2->mutex);
1120                         if (z2->start + min_bs <= z2->wp)
1121                                 return z2;
1122                         pthread_mutex_unlock(&z2->mutex);
1123                 }
1124         }
1125         dprint(FD_ZBD, "%s: adjusting random read offset failed\n",
1126                f->file_name);
1127         return NULL;
1128 }
1129
1130 /**
1131  * zbd_queue_io - update the write pointer of a sequential zone
1132  * @io_u: I/O unit
1133  * @success: Whether or not the I/O unit has been queued successfully
1134  * @q: queueing status (busy, completed or queued).
1135  *
1136  * For write and trim operations, update the write pointer of the I/O unit
1137  * target zone.
1138  */
1139 static void zbd_queue_io(struct io_u *io_u, int q, bool success)
1140 {
1141         const struct fio_file *f = io_u->file;
1142         struct zoned_block_device_info *zbd_info = f->zbd_info;
1143         struct fio_zone_info *z;
1144         uint32_t zone_idx;
1145         uint64_t zone_end;
1146
1147         if (!zbd_info)
1148                 return;
1149
1150         zone_idx = zbd_zone_idx(f, io_u->offset);
1151         assert(zone_idx < zbd_info->nr_zones);
1152         z = &zbd_info->zone_info[zone_idx];
1153
1154         if (z->type != BLK_ZONE_TYPE_SEQWRITE_REQ)
1155                 return;
1156
1157         if (!success)
1158                 goto unlock;
1159
1160         dprint(FD_ZBD,
1161                "%s: queued I/O (%lld, %llu) for zone %u\n",
1162                f->file_name, io_u->offset, io_u->buflen, zone_idx);
1163
1164         switch (io_u->ddir) {
1165         case DDIR_WRITE:
1166                 zone_end = min((uint64_t)(io_u->offset + io_u->buflen),
1167                                (z + 1)->start);
1168                 pthread_mutex_lock(&zbd_info->mutex);
1169                 /*
1170                  * z->wp > zone_end means that one or more I/O errors
1171                  * have occurred.
1172                  */
1173                 if (z->wp <= zone_end)
1174                         zbd_info->sectors_with_data += zone_end - z->wp;
1175                 pthread_mutex_unlock(&zbd_info->mutex);
1176                 z->wp = zone_end;
1177                 break;
1178         case DDIR_TRIM:
1179                 assert(z->wp == z->start);
1180                 break;
1181         default:
1182                 break;
1183         }
1184
1185 unlock:
1186         if (!success || q != FIO_Q_QUEUED) {
1187                 /* BUSY or COMPLETED: unlock the zone */
1188                 pthread_mutex_unlock(&z->mutex);
1189                 io_u->zbd_put_io = NULL;
1190         }
1191 }
1192
1193 /**
1194  * zbd_put_io - Unlock an I/O unit target zone lock
1195  * @io_u: I/O unit
1196  */
1197 static void zbd_put_io(const struct io_u *io_u)
1198 {
1199         const struct fio_file *f = io_u->file;
1200         struct zoned_block_device_info *zbd_info = f->zbd_info;
1201         struct fio_zone_info *z;
1202         uint32_t zone_idx;
1203
1204         if (!zbd_info)
1205                 return;
1206
1207         zone_idx = zbd_zone_idx(f, io_u->offset);
1208         assert(zone_idx < zbd_info->nr_zones);
1209         z = &zbd_info->zone_info[zone_idx];
1210
1211         if (z->type != BLK_ZONE_TYPE_SEQWRITE_REQ)
1212                 return;
1213
1214         dprint(FD_ZBD,
1215                "%s: terminate I/O (%lld, %llu) for zone %u\n",
1216                f->file_name, io_u->offset, io_u->buflen, zone_idx);
1217
1218         assert(pthread_mutex_unlock(&z->mutex) == 0);
1219         zbd_check_swd(f);
1220 }
1221
1222 bool zbd_unaligned_write(int error_code)
1223 {
1224         switch (error_code) {
1225         case EIO:
1226         case EREMOTEIO:
1227                 return true;
1228         }
1229         return false;
1230 }
1231
1232 /**
1233  * setup_zbd_zone_mode - handle zoneskip as necessary for ZBD drives
1234  * @td: FIO thread data.
1235  * @io_u: FIO I/O unit.
1236  *
1237  * For sequential workloads, change the file offset to skip zoneskip bytes when
1238  * no more IO can be performed in the current zone.
1239  * - For read workloads, zoneskip is applied when the io has reached the end of
1240  *   the zone or the zone write position (when td->o.read_beyond_wp is false).
1241  * - For write workloads, zoneskip is applied when the zone is full.
1242  * This applies only to read and write operations.
1243  */
1244 void setup_zbd_zone_mode(struct thread_data *td, struct io_u *io_u)
1245 {
1246         struct fio_file *f = io_u->file;
1247         enum fio_ddir ddir = io_u->ddir;
1248         struct fio_zone_info *z;
1249         uint32_t zone_idx;
1250
1251         assert(td->o.zone_mode == ZONE_MODE_ZBD);
1252         assert(td->o.zone_size);
1253
1254         /*
1255          * zone_skip is valid only for sequential workloads.
1256          */
1257         if (td_random(td) || !td->o.zone_skip)
1258                 return;
1259
1260         /*
1261          * It is time to switch to a new zone if:
1262          * - zone_bytes == zone_size bytes have already been accessed
1263          * - The last position reached the end of the current zone.
1264          * - For reads with td->o.read_beyond_wp == false, the last position
1265          *   reached the zone write pointer.
1266          */
1267         zone_idx = zbd_zone_idx(f, f->last_pos[ddir]);
1268         z = &f->zbd_info->zone_info[zone_idx];
1269
1270         if (td->zone_bytes >= td->o.zone_size ||
1271             f->last_pos[ddir] >= (z+1)->start ||
1272             (ddir == DDIR_READ &&
1273              (!td->o.read_beyond_wp) && f->last_pos[ddir] >= z->wp)) {
1274                 /*
1275                  * Skip zones.
1276                  */
1277                 td->zone_bytes = 0;
1278                 f->file_offset += td->o.zone_size + td->o.zone_skip;
1279
1280                 /*
1281                  * Wrap from the beginning, if we exceed the file size
1282                  */
1283                 if (f->file_offset >= f->real_file_size)
1284                         f->file_offset = get_start_offset(td, f);
1285
1286                 f->last_pos[ddir] = f->file_offset;
1287                 td->io_skip_bytes += td->o.zone_skip;
1288         }
1289 }
1290
1291 /**
1292  * zbd_adjust_block - adjust the offset and length as necessary for ZBD drives
1293  * @td: FIO thread data.
1294  * @io_u: FIO I/O unit.
1295  *
1296  * Locking strategy: returns with z->mutex locked if and only if z refers
1297  * to a sequential zone and if io_u_accept is returned. z is the zone that
1298  * corresponds to io_u->offset at the end of this function.
1299  */
1300 enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
1301 {
1302         const struct fio_file *f = io_u->file;
1303         uint32_t zone_idx_b;
1304         struct fio_zone_info *zb, *zl, *orig_zb;
1305         uint32_t orig_len = io_u->buflen;
1306         uint32_t min_bs = td->o.min_bs[io_u->ddir];
1307         uint64_t new_len;
1308         int64_t range;
1309
1310         if (!f->zbd_info)
1311                 return io_u_accept;
1312
1313         assert(is_valid_offset(f, io_u->offset));
1314         assert(io_u->buflen);
1315         zone_idx_b = zbd_zone_idx(f, io_u->offset);
1316         zb = &f->zbd_info->zone_info[zone_idx_b];
1317         orig_zb = zb;
1318
1319         /* Accept the I/O offset for conventional zones. */
1320         if (zb->type == BLK_ZONE_TYPE_CONVENTIONAL)
1321                 return io_u_accept;
1322
1323         /*
1324          * Accept the I/O offset for reads if reading beyond the write pointer
1325          * is enabled.
1326          */
1327         if (zb->cond != BLK_ZONE_COND_OFFLINE &&
1328             io_u->ddir == DDIR_READ && td->o.read_beyond_wp)
1329                 return io_u_accept;
1330
1331         zbd_check_swd(f);
1332
1333         /*
1334          * Lock the io_u target zone. The zone will be unlocked if io_u offset
1335          * is changed or when io_u completes and zbd_put_io() executed.
1336          * To avoid multiple jobs doing asynchronous I/Os from deadlocking each
1337          * other waiting for zone locks when building an io_u batch, first
1338          * only trylock the zone. If the zone is already locked by another job,
1339          * process the currently queued I/Os so that I/O progress is made and
1340          * zones unlocked.
1341          */
1342         if (pthread_mutex_trylock(&zb->mutex) != 0) {
1343                 if (!td_ioengine_flagged(td, FIO_SYNCIO))
1344                         io_u_quiesce(td);
1345                 pthread_mutex_lock(&zb->mutex);
1346         }
1347
1348         switch (io_u->ddir) {
1349         case DDIR_READ:
1350                 if (td->runstate == TD_VERIFYING) {
1351                         zb = zbd_replay_write_order(td, io_u, zb);
1352                         goto accept;
1353                 }
1354                 /*
1355                  * Check that there is enough written data in the zone to do an
1356                  * I/O of at least min_bs B. If there isn't, find a new zone for
1357                  * the I/O.
1358                  */
1359                 range = zb->cond != BLK_ZONE_COND_OFFLINE ?
1360                         zb->wp - zb->start : 0;
1361                 if (range < min_bs ||
1362                     ((!td_random(td)) && (io_u->offset + min_bs > zb->wp))) {
1363                         pthread_mutex_unlock(&zb->mutex);
1364                         zl = &f->zbd_info->zone_info[zbd_zone_idx(f,
1365                                                 f->file_offset + f->io_size)];
1366                         zb = zbd_find_zone(td, io_u, zb, zl);
1367                         if (!zb) {
1368                                 dprint(FD_ZBD,
1369                                        "%s: zbd_find_zone(%lld, %llu) failed\n",
1370                                        f->file_name, io_u->offset,
1371                                        io_u->buflen);
1372                                 goto eof;
1373                         }
1374                         /*
1375                          * zbd_find_zone() returned a zone with a range of at
1376                          * least min_bs.
1377                          */
1378                         range = zb->wp - zb->start;
1379                         assert(range >= min_bs);
1380
1381                         if (!td_random(td))
1382                                 io_u->offset = zb->start;
1383                 }
1384                 /*
1385                  * Make sure the I/O is within the zone valid data range while
1386                  * maximizing the I/O size and preserving randomness.
1387                  */
1388                 if (range <= io_u->buflen)
1389                         io_u->offset = zb->start;
1390                 else if (td_random(td))
1391                         io_u->offset = zb->start +
1392                                 ((io_u->offset - orig_zb->start) %
1393                                  (range - io_u->buflen)) / min_bs * min_bs;
1394                 /*
1395                  * Make sure the I/O does not cross over the zone wp position.
1396                  */
1397                 new_len = min((unsigned long long)io_u->buflen,
1398                               (unsigned long long)(zb->wp - io_u->offset));
1399                 new_len = new_len / min_bs * min_bs;
1400                 if (new_len < io_u->buflen) {
1401                         io_u->buflen = new_len;
1402                         dprint(FD_IO, "Changed length from %u into %llu\n",
1403                                orig_len, io_u->buflen);
1404                 }
1405                 assert(zb->start <= io_u->offset);
1406                 assert(io_u->offset + io_u->buflen <= zb->wp);
1407                 goto accept;
1408         case DDIR_WRITE:
1409                 if (io_u->buflen > f->zbd_info->zone_size)
1410                         goto eof;
1411                 if (!zbd_open_zone(td, io_u, zone_idx_b)) {
1412                         pthread_mutex_unlock(&zb->mutex);
1413                         zb = zbd_convert_to_open_zone(td, io_u);
1414                         if (!zb)
1415                                 goto eof;
1416                         zone_idx_b = zb - f->zbd_info->zone_info;
1417                 }
1418                 /* Check whether the zone reset threshold has been exceeded */
1419                 if (td->o.zrf.u.f) {
1420                         if (f->zbd_info->sectors_with_data >=
1421                             f->io_size * td->o.zrt.u.f &&
1422                             zbd_dec_and_reset_write_cnt(td, f)) {
1423                                 zb->reset_zone = 1;
1424                         }
1425                 }
1426                 /* Reset the zone pointer if necessary */
1427                 if (zb->reset_zone || zbd_zone_full(f, zb, min_bs)) {
1428                         assert(td->o.verify == VERIFY_NONE);
1429                         /*
1430                          * Since previous write requests may have been submitted
1431                          * asynchronously and since we will submit the zone
1432                          * reset synchronously, wait until previously submitted
1433                          * write requests have completed before issuing a
1434                          * zone reset.
1435                          */
1436                         io_u_quiesce(td);
1437                         zb->reset_zone = 0;
1438                         if (zbd_reset_zone(td, f, zb) < 0)
1439                                 goto eof;
1440                 }
1441                 /* Make writes occur at the write pointer */
1442                 assert(!zbd_zone_full(f, zb, min_bs));
1443                 io_u->offset = zb->wp;
1444                 if (!is_valid_offset(f, io_u->offset)) {
1445                         dprint(FD_ZBD, "Dropped request with offset %llu\n",
1446                                io_u->offset);
1447                         goto eof;
1448                 }
1449                 /*
1450                  * Make sure that the buflen is a multiple of the minimal
1451                  * block size. Give up if shrinking would make the request too
1452                  * small.
1453                  */
1454                 new_len = min((unsigned long long)io_u->buflen,
1455                               (zb + 1)->start - io_u->offset);
1456                 new_len = new_len / min_bs * min_bs;
1457                 if (new_len == io_u->buflen)
1458                         goto accept;
1459                 if (new_len >= min_bs) {
1460                         io_u->buflen = new_len;
1461                         dprint(FD_IO, "Changed length from %u into %llu\n",
1462                                orig_len, io_u->buflen);
1463                         goto accept;
1464                 }
1465                 log_err("Zone remainder %lld smaller than minimum block size %d\n",
1466                         ((zb + 1)->start - io_u->offset),
1467                         min_bs);
1468                 goto eof;
1469         case DDIR_TRIM:
1470                 /* fall-through */
1471         case DDIR_SYNC:
1472         case DDIR_DATASYNC:
1473         case DDIR_SYNC_FILE_RANGE:
1474         case DDIR_WAIT:
1475         case DDIR_LAST:
1476         case DDIR_INVAL:
1477                 goto accept;
1478         }
1479
1480         assert(false);
1481
1482 accept:
1483         assert(zb);
1484         assert(zb->cond != BLK_ZONE_COND_OFFLINE);
1485         assert(!io_u->zbd_queue_io);
1486         assert(!io_u->zbd_put_io);
1487         io_u->zbd_queue_io = zbd_queue_io;
1488         io_u->zbd_put_io = zbd_put_io;
1489         return io_u_accept;
1490
1491 eof:
1492         if (zb)
1493                 pthread_mutex_unlock(&zb->mutex);
1494         return io_u_eof;
1495 }
1496
1497 /* Return a string with ZBD statistics */
1498 char *zbd_write_status(const struct thread_stat *ts)
1499 {
1500         char *res;
1501
1502         if (asprintf(&res, "; %llu zone resets", (unsigned long long) ts->nr_zone_resets) < 0)
1503                 return NULL;
1504         return res;
1505 }