Merge branch 'libaio/actual_min_algo_update' of https://github.com/dpronin/fio
[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 <fcntl.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
13
14 #include "os/os.h"
15 #include "file.h"
16 #include "fio.h"
17 #include "lib/pow2.h"
18 #include "log.h"
19 #include "oslib/asprintf.h"
20 #include "smalloc.h"
21 #include "verify.h"
22 #include "pshared.h"
23 #include "zbd.h"
24
25 static bool is_valid_offset(const struct fio_file *f, uint64_t offset)
26 {
27         return (uint64_t)(offset - f->file_offset) < f->io_size;
28 }
29
30 static inline unsigned int zbd_zone_idx(const struct fio_file *f,
31                                         struct fio_zone_info *zone)
32 {
33         return zone - f->zbd_info->zone_info;
34 }
35
36 /**
37  * zbd_offset_to_zone_idx - convert an offset into a zone number
38  * @f: file pointer.
39  * @offset: offset in bytes. If this offset is in the first zone_size bytes
40  *          past the disk size then the index of the sentinel is returned.
41  */
42 static unsigned int zbd_offset_to_zone_idx(const struct fio_file *f,
43                                            uint64_t offset)
44 {
45         uint32_t zone_idx;
46
47         if (f->zbd_info->zone_size_log2 > 0)
48                 zone_idx = offset >> f->zbd_info->zone_size_log2;
49         else
50                 zone_idx = offset / f->zbd_info->zone_size;
51
52         return min(zone_idx, f->zbd_info->nr_zones);
53 }
54
55 /**
56  * zbd_zone_end - Return zone end location
57  * @z: zone info pointer.
58  */
59 static inline uint64_t zbd_zone_end(const struct fio_zone_info *z)
60 {
61         return (z+1)->start;
62 }
63
64 /**
65  * zbd_zone_capacity_end - Return zone capacity limit end location
66  * @z: zone info pointer.
67  */
68 static inline uint64_t zbd_zone_capacity_end(const struct fio_zone_info *z)
69 {
70         return z->start + z->capacity;
71 }
72
73 /**
74  * zbd_zone_remainder - Return the number of bytes that are still available for
75  *                      writing before the zone gets full
76  * @z: zone info pointer.
77  */
78 static inline uint64_t zbd_zone_remainder(struct fio_zone_info *z)
79 {
80         if (z->wp >= zbd_zone_capacity_end(z))
81                 return 0;
82
83         return zbd_zone_capacity_end(z) - z->wp;
84 }
85
86 /**
87  * zbd_zone_full - verify whether a minimum number of bytes remain in a zone
88  * @f: file pointer.
89  * @z: zone info pointer.
90  * @required: minimum number of bytes that must remain in a zone.
91  *
92  * The caller must hold z->mutex.
93  */
94 static bool zbd_zone_full(const struct fio_file *f, struct fio_zone_info *z,
95                           uint64_t required)
96 {
97         assert((required & 511) == 0);
98
99         return z->has_wp && required > zbd_zone_remainder(z);
100 }
101
102 static void zone_lock(struct thread_data *td, const struct fio_file *f,
103                       struct fio_zone_info *z)
104 {
105         struct zoned_block_device_info *zbd = f->zbd_info;
106         uint32_t nz = z - zbd->zone_info;
107
108         /* A thread should never lock zones outside its working area. */
109         assert(f->min_zone <= nz && nz < f->max_zone);
110
111         assert(z->has_wp);
112
113         /*
114          * Lock the io_u target zone. The zone will be unlocked if io_u offset
115          * is changed or when io_u completes and zbd_put_io() executed.
116          * To avoid multiple jobs doing asynchronous I/Os from deadlocking each
117          * other waiting for zone locks when building an io_u batch, first
118          * only trylock the zone. If the zone is already locked by another job,
119          * process the currently queued I/Os so that I/O progress is made and
120          * zones unlocked.
121          */
122         if (pthread_mutex_trylock(&z->mutex) != 0) {
123                 if (!td_ioengine_flagged(td, FIO_SYNCIO))
124                         io_u_quiesce(td);
125                 pthread_mutex_lock(&z->mutex);
126         }
127 }
128
129 static inline void zone_unlock(struct fio_zone_info *z)
130 {
131         int ret;
132
133         assert(z->has_wp);
134         ret = pthread_mutex_unlock(&z->mutex);
135         assert(!ret);
136 }
137
138 static inline struct fio_zone_info *zbd_get_zone(const struct fio_file *f,
139                                                  unsigned int zone_idx)
140 {
141         return &f->zbd_info->zone_info[zone_idx];
142 }
143
144 static inline struct fio_zone_info *
145 zbd_offset_to_zone(const struct fio_file *f,  uint64_t offset)
146 {
147         return zbd_get_zone(f, zbd_offset_to_zone_idx(f, offset));
148 }
149
150 static bool accounting_vdb(struct thread_data *td, const struct fio_file *f)
151 {
152         return td->o.zrt.u.f && td_write(td);
153 }
154
155 /**
156  * zbd_get_zoned_model - Get a device zoned model
157  * @td: FIO thread data
158  * @f: FIO file for which to get model information
159  */
160 static int zbd_get_zoned_model(struct thread_data *td, struct fio_file *f,
161                                enum zbd_zoned_model *model)
162 {
163         int ret;
164
165         if (f->filetype == FIO_TYPE_PIPE) {
166                 log_err("zonemode=zbd does not support pipes\n");
167                 return -EINVAL;
168         }
169
170         /* If regular file, always emulate zones inside the file. */
171         if (f->filetype == FIO_TYPE_FILE) {
172                 *model = ZBD_NONE;
173                 return 0;
174         }
175
176         if (td->io_ops && td->io_ops->get_zoned_model)
177                 ret = td->io_ops->get_zoned_model(td, f, model);
178         else
179                 ret = blkzoned_get_zoned_model(td, f, model);
180         if (ret < 0) {
181                 td_verror(td, errno, "get zoned model failed");
182                 log_err("%s: get zoned model failed (%d).\n",
183                         f->file_name, errno);
184         }
185
186         return ret;
187 }
188
189 /**
190  * zbd_report_zones - Get zone information
191  * @td: FIO thread data.
192  * @f: FIO file for which to get zone information
193  * @offset: offset from which to report zones
194  * @zones: Array of struct zbd_zone
195  * @nr_zones: Size of @zones array
196  *
197  * Get zone information into @zones starting from the zone at offset @offset
198  * for the device specified by @f.
199  *
200  * Returns the number of zones reported upon success and a negative error code
201  * upon failure. If the zone report is empty, always assume an error (device
202  * problem) and return -EIO.
203  */
204 static int zbd_report_zones(struct thread_data *td, struct fio_file *f,
205                             uint64_t offset, struct zbd_zone *zones,
206                             unsigned int nr_zones)
207 {
208         int ret;
209
210         if (td->io_ops && td->io_ops->report_zones)
211                 ret = td->io_ops->report_zones(td, f, offset, zones, nr_zones);
212         else
213                 ret = blkzoned_report_zones(td, f, offset, zones, nr_zones);
214         if (ret < 0) {
215                 td_verror(td, errno, "report zones failed");
216                 log_err("%s: report zones from sector %"PRIu64" failed (nr_zones=%d; errno=%d).\n",
217                         f->file_name, offset >> 9, nr_zones, errno);
218         } else if (ret == 0) {
219                 td_verror(td, errno, "Empty zone report");
220                 log_err("%s: report zones from sector %"PRIu64" is empty.\n",
221                         f->file_name, offset >> 9);
222                 ret = -EIO;
223         }
224
225         return ret;
226 }
227
228 /**
229  * zbd_reset_wp - reset the write pointer of a range of zones
230  * @td: FIO thread data.
231  * @f: FIO file for which to reset zones
232  * @offset: Starting offset of the first zone to reset
233  * @length: Length of the range of zones to reset
234  *
235  * Reset the write pointer of all zones in the range @offset...@offset+@length.
236  * Returns 0 upon success and a negative error code upon failure.
237  */
238 static int zbd_reset_wp(struct thread_data *td, struct fio_file *f,
239                         uint64_t offset, uint64_t length)
240 {
241         int ret;
242
243         if (td->io_ops && td->io_ops->reset_wp)
244                 ret = td->io_ops->reset_wp(td, f, offset, length);
245         else
246                 ret = blkzoned_reset_wp(td, f, offset, length);
247         if (ret < 0) {
248                 td_verror(td, errno, "resetting wp failed");
249                 log_err("%s: resetting wp for %"PRIu64" sectors at sector %"PRIu64" failed (%d).\n",
250                         f->file_name, length >> 9, offset >> 9, errno);
251         }
252
253         return ret;
254 }
255
256 /**
257  * __zbd_reset_zone - reset the write pointer of a single zone
258  * @td: FIO thread data.
259  * @f: FIO file associated with the disk for which to reset a write pointer.
260  * @z: Zone to reset.
261  *
262  * Returns 0 upon success and a negative error code upon failure.
263  *
264  * The caller must hold z->mutex.
265  */
266 static int __zbd_reset_zone(struct thread_data *td, struct fio_file *f,
267                             struct fio_zone_info *z)
268 {
269         uint64_t offset = z->start;
270         uint64_t length = (z+1)->start - offset;
271         uint64_t data_in_zone = z->wp - z->start;
272         int ret = 0;
273
274         if (!data_in_zone)
275                 return 0;
276
277         assert(is_valid_offset(f, offset + length - 1));
278
279         dprint(FD_ZBD, "%s: resetting wp of zone %u.\n",
280                f->file_name, zbd_zone_idx(f, z));
281
282         switch (f->zbd_info->model) {
283         case ZBD_HOST_AWARE:
284         case ZBD_HOST_MANAGED:
285                 ret = zbd_reset_wp(td, f, offset, length);
286                 if (ret < 0)
287                         return ret;
288                 break;
289         default:
290                 break;
291         }
292
293         if (accounting_vdb(td, f)) {
294                 pthread_mutex_lock(&f->zbd_info->mutex);
295                 f->zbd_info->wp_valid_data_bytes -= data_in_zone;
296                 pthread_mutex_unlock(&f->zbd_info->mutex);
297         }
298
299         z->wp = z->start;
300
301         td->ts.nr_zone_resets++;
302
303         return ret;
304 }
305
306 /**
307  * zbd_write_zone_put - Remove a zone from the write target zones array.
308  * @td: FIO thread data.
309  * @f: FIO file that has the write zones array to remove.
310  * @zone_idx: Index of the zone to remove.
311  *
312  * The caller must hold f->zbd_info->mutex.
313  */
314 static void zbd_write_zone_put(struct thread_data *td, const struct fio_file *f,
315                                struct fio_zone_info *z)
316 {
317         uint32_t zi;
318
319         if (!z->write)
320                 return;
321
322         for (zi = 0; zi < f->zbd_info->num_write_zones; zi++) {
323                 if (zbd_get_zone(f, f->zbd_info->write_zones[zi]) == z)
324                         break;
325         }
326         if (zi == f->zbd_info->num_write_zones)
327                 return;
328
329         dprint(FD_ZBD, "%s: removing zone %u from write zone array\n",
330                f->file_name, zbd_zone_idx(f, z));
331
332         memmove(f->zbd_info->write_zones + zi,
333                 f->zbd_info->write_zones + zi + 1,
334                 (ZBD_MAX_WRITE_ZONES - (zi + 1)) *
335                 sizeof(f->zbd_info->write_zones[0]));
336
337         f->zbd_info->num_write_zones--;
338         td->num_write_zones--;
339         z->write = 0;
340 }
341
342 /**
343  * zbd_reset_zone - reset the write pointer of a single zone and remove the zone
344  *                  from the array of write zones.
345  * @td: FIO thread data.
346  * @f: FIO file associated with the disk for which to reset a write pointer.
347  * @z: Zone to reset.
348  *
349  * Returns 0 upon success and a negative error code upon failure.
350  *
351  * The caller must hold z->mutex.
352  */
353 static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
354                           struct fio_zone_info *z)
355 {
356         int ret;
357
358         ret = __zbd_reset_zone(td, f, z);
359         if (ret)
360                 return ret;
361
362         pthread_mutex_lock(&f->zbd_info->mutex);
363         zbd_write_zone_put(td, f, z);
364         pthread_mutex_unlock(&f->zbd_info->mutex);
365         return 0;
366 }
367
368 /**
369  * zbd_finish_zone - finish the specified zone
370  * @td: FIO thread data.
371  * @f: FIO file for which to finish a zone
372  * @z: Zone to finish.
373  *
374  * Finish the zone at @offset with open or close status.
375  */
376 static int zbd_finish_zone(struct thread_data *td, struct fio_file *f,
377                            struct fio_zone_info *z)
378 {
379         uint64_t offset = z->start;
380         uint64_t length = f->zbd_info->zone_size;
381         int ret = 0;
382
383         switch (f->zbd_info->model) {
384         case ZBD_HOST_AWARE:
385         case ZBD_HOST_MANAGED:
386                 if (td->io_ops && td->io_ops->finish_zone)
387                         ret = td->io_ops->finish_zone(td, f, offset, length);
388                 else
389                         ret = blkzoned_finish_zone(td, f, offset, length);
390                 break;
391         default:
392                 break;
393         }
394
395         if (ret < 0) {
396                 td_verror(td, errno, "finish zone failed");
397                 log_err("%s: finish zone at sector %"PRIu64" failed (%d).\n",
398                         f->file_name, offset >> 9, errno);
399         } else {
400                 z->wp = (z+1)->start;
401         }
402
403         return ret;
404 }
405
406 /**
407  * zbd_reset_zones - Reset a range of zones.
408  * @td: fio thread data.
409  * @f: fio file for which to reset zones
410  * @zb: first zone to reset.
411  * @ze: first zone not to reset.
412  *
413  * Returns 0 upon success and 1 upon failure.
414  */
415 static int zbd_reset_zones(struct thread_data *td, struct fio_file *f,
416                            struct fio_zone_info *const zb,
417                            struct fio_zone_info *const ze)
418 {
419         struct fio_zone_info *z;
420         const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
421         int res = 0;
422
423         assert(min_bs);
424
425         dprint(FD_ZBD, "%s: examining zones %u .. %u\n",
426                f->file_name, zbd_zone_idx(f, zb), zbd_zone_idx(f, ze));
427
428         for (z = zb; z < ze; z++) {
429                 if (!z->has_wp)
430                         continue;
431
432                 zone_lock(td, f, z);
433
434                 if (z->wp != z->start) {
435                         dprint(FD_ZBD, "%s: resetting zone %u\n",
436                                f->file_name, zbd_zone_idx(f, z));
437                         if (zbd_reset_zone(td, f, z) < 0)
438                                 res = 1;
439                 }
440
441                 zone_unlock(z);
442         }
443
444         return res;
445 }
446
447 /**
448  * zbd_get_max_open_zones - Get the maximum number of open zones
449  * @td: FIO thread data
450  * @f: FIO file for which to get max open zones
451  * @max_open_zones: Upon success, result will be stored here.
452  *
453  * A @max_open_zones value set to zero means no limit.
454  *
455  * Returns 0 upon success and a negative error code upon failure.
456  */
457 static int zbd_get_max_open_zones(struct thread_data *td, struct fio_file *f,
458                                   unsigned int *max_open_zones)
459 {
460         int ret;
461
462         if (td->io_ops && td->io_ops->get_max_open_zones)
463                 ret = td->io_ops->get_max_open_zones(td, f, max_open_zones);
464         else
465                 ret = blkzoned_get_max_open_zones(td, f, max_open_zones);
466         if (ret < 0) {
467                 td_verror(td, errno, "get max open zones failed");
468                 log_err("%s: get max open zones failed (%d).\n",
469                         f->file_name, errno);
470         }
471
472         return ret;
473 }
474
475 /**
476  * __zbd_write_zone_get - Add a zone to the array of write zones.
477  * @td: fio thread data.
478  * @f: fio file that has the write zones array to add.
479  * @zone_idx: Index of the zone to add.
480  *
481  * Do same operation as @zbd_write_zone_get, except it adds the zone at
482  * @zone_idx to write target zones array even when it does not have remainder
483  * space to write one block.
484  */
485 static bool __zbd_write_zone_get(struct thread_data *td,
486                                  const struct fio_file *f,
487                                  struct fio_zone_info *z)
488 {
489         struct zoned_block_device_info *zbdi = f->zbd_info;
490         uint32_t zone_idx = zbd_zone_idx(f, z);
491         bool res = true;
492
493         if (z->cond == ZBD_ZONE_COND_OFFLINE)
494                 return false;
495
496         /*
497          * Skip full zones with data verification enabled because resetting a
498          * zone causes data loss and hence causes verification to fail.
499          */
500         if (td->o.verify != VERIFY_NONE && zbd_zone_remainder(z) == 0)
501                 return false;
502
503         /*
504          * zbdi->max_write_zones == 0 means that there is no limit on the
505          * maximum number of write target zones. In this case, do no track write
506          * target zones in zbdi->write_zones array.
507          */
508         if (!zbdi->max_write_zones)
509                 return true;
510
511         pthread_mutex_lock(&zbdi->mutex);
512
513         if (z->write) {
514                 /*
515                  * If the zone is going to be completely filled by writes
516                  * already in-flight, handle it as a full zone instead of a
517                  * write target zone.
518                  */
519                 if (!zbd_zone_remainder(z))
520                         res = false;
521                 goto out;
522         }
523
524         res = false;
525         /* Zero means no limit */
526         if (td->o.job_max_open_zones > 0 &&
527             td->num_write_zones >= td->o.job_max_open_zones)
528                 goto out;
529         if (zbdi->num_write_zones >= zbdi->max_write_zones)
530                 goto out;
531
532         dprint(FD_ZBD, "%s: adding zone %u to write zone array\n",
533                f->file_name, zone_idx);
534
535         zbdi->write_zones[zbdi->num_write_zones++] = zone_idx;
536         td->num_write_zones++;
537         z->write = 1;
538         res = true;
539
540 out:
541         pthread_mutex_unlock(&zbdi->mutex);
542         return res;
543 }
544
545 /**
546  * zbd_write_zone_get - Add a zone to the array of write zones.
547  * @td: fio thread data.
548  * @f: fio file that has the open zones to add.
549  * @zone_idx: Index of the zone to add.
550  *
551  * Add a ZBD zone to write target zones array, if it is not yet added. Returns
552  * true if either the zone was already added or if the zone was successfully
553  * added to the array without exceeding the maximum number of write zones.
554  * Returns false if the zone was not already added and addition of the zone
555  * would cause the zone limit to be exceeded.
556  */
557 static bool zbd_write_zone_get(struct thread_data *td, const struct fio_file *f,
558                                struct fio_zone_info *z)
559 {
560         const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
561
562         /*
563          * Skip full zones with data verification enabled because resetting a
564          * zone causes data loss and hence causes verification to fail.
565          */
566         if (td->o.verify != VERIFY_NONE && zbd_zone_full(f, z, min_bs))
567                 return false;
568
569         return __zbd_write_zone_get(td, f, z);
570 }
571
572 /* Verify whether direct I/O is used for all host-managed zoned block drives. */
573 static bool zbd_using_direct_io(void)
574 {
575         struct fio_file *f;
576         int j;
577
578         for_each_td(td) {
579                 if (td->o.odirect || !(td->o.td_ddir & TD_DDIR_WRITE))
580                         continue;
581                 for_each_file(td, f, j) {
582                         if (f->zbd_info && f->filetype == FIO_TYPE_BLOCK &&
583                             f->zbd_info->model == ZBD_HOST_MANAGED)
584                                 return false;
585                 }
586         } end_for_each();
587
588         return true;
589 }
590
591 /* Whether or not the I/O range for f includes one or more sequential zones */
592 static bool zbd_is_seq_job(const struct fio_file *f)
593 {
594         uint32_t zone_idx, zone_idx_b, zone_idx_e;
595
596         assert(f->zbd_info);
597
598         if (f->io_size == 0)
599                 return false;
600
601         zone_idx_b = zbd_offset_to_zone_idx(f, f->file_offset);
602         zone_idx_e =
603                 zbd_offset_to_zone_idx(f, f->file_offset + f->io_size - 1);
604         for (zone_idx = zone_idx_b; zone_idx <= zone_idx_e; zone_idx++)
605                 if (zbd_get_zone(f, zone_idx)->has_wp)
606                         return true;
607
608         return false;
609 }
610
611 /*
612  * Verify whether the file offset and size parameters are aligned with zone
613  * boundaries. If the file offset is not aligned, align it down to the start of
614  * the zone containing the start offset and align up the file io_size parameter.
615  */
616 static bool zbd_zone_align_file_sizes(struct thread_data *td,
617                                       struct fio_file *f)
618 {
619         const struct fio_zone_info *z;
620         uint64_t new_offset, new_end;
621
622         if (!f->zbd_info)
623                 return true;
624         if (f->file_offset >= f->real_file_size)
625                 return true;
626         if (!zbd_is_seq_job(f))
627                 return true;
628
629         if (!td->o.zone_size) {
630                 td->o.zone_size = f->zbd_info->zone_size;
631                 if (!td->o.zone_size) {
632                         log_err("%s: invalid 0 zone size\n",
633                                 f->file_name);
634                         return false;
635                 }
636         } else if (td->o.zone_size != f->zbd_info->zone_size) {
637                 log_err("%s: zonesize %llu does not match the device zone size %"PRIu64".\n",
638                         f->file_name, td->o.zone_size,
639                         f->zbd_info->zone_size);
640                 return false;
641         }
642
643         if (td->o.zone_skip % td->o.zone_size) {
644                 log_err("%s: zoneskip %llu is not a multiple of the device zone size %llu.\n",
645                         f->file_name, td->o.zone_skip,
646                         td->o.zone_size);
647                 return false;
648         }
649
650         z = zbd_offset_to_zone(f, f->file_offset);
651         if ((f->file_offset != z->start) &&
652             (td->o.td_ddir != TD_DDIR_READ)) {
653                 new_offset = zbd_zone_end(z);
654                 if (new_offset >= f->file_offset + f->io_size) {
655                         log_info("%s: io_size must be at least one zone\n",
656                                  f->file_name);
657                         return false;
658                 }
659                 log_info("%s: rounded up offset from %"PRIu64" to %"PRIu64"\n",
660                          f->file_name, f->file_offset,
661                          new_offset);
662                 f->io_size -= (new_offset - f->file_offset);
663                 f->file_offset = new_offset;
664         }
665
666         z = zbd_offset_to_zone(f, f->file_offset + f->io_size);
667         new_end = z->start;
668         if ((td->o.td_ddir != TD_DDIR_READ) &&
669             (f->file_offset + f->io_size != new_end)) {
670                 if (new_end <= f->file_offset) {
671                         log_info("%s: io_size must be at least one zone\n",
672                                  f->file_name);
673                         return false;
674                 }
675                 log_info("%s: rounded down io_size from %"PRIu64" to %"PRIu64"\n",
676                          f->file_name, f->io_size,
677                          new_end - f->file_offset);
678                 f->io_size = new_end - f->file_offset;
679         }
680
681         return true;
682 }
683
684 /*
685  * Verify whether offset and size parameters are aligned with zone boundaries.
686  */
687 static bool zbd_verify_sizes(void)
688 {
689         struct fio_file *f;
690         int j;
691
692         for_each_td(td) {
693                 for_each_file(td, f, j) {
694                         if (!zbd_zone_align_file_sizes(td, f))
695                                 return false;
696                 }
697         } end_for_each();
698
699         return true;
700 }
701
702 static bool zbd_verify_bs(void)
703 {
704         struct fio_file *f;
705         int j;
706
707         for_each_td(td) {
708                 if (td_trim(td) &&
709                     (td->o.min_bs[DDIR_TRIM] != td->o.max_bs[DDIR_TRIM] ||
710                      td->o.bssplit_nr[DDIR_TRIM])) {
711                         log_info("bsrange and bssplit are not allowed for trim with zonemode=zbd\n");
712                         return false;
713                 }
714                 for_each_file(td, f, j) {
715                         uint64_t zone_size;
716
717                         if (!f->zbd_info)
718                                 continue;
719
720                         zone_size = f->zbd_info->zone_size;
721                         if (td_trim(td) && td->o.bs[DDIR_TRIM] != zone_size) {
722                                 log_info("%s: trim block size %llu is not the zone size %"PRIu64"\n",
723                                          f->file_name, td->o.bs[DDIR_TRIM],
724                                          zone_size);
725                                 return false;
726                         }
727                 }
728         } end_for_each();
729         return true;
730 }
731
732 static int ilog2(uint64_t i)
733 {
734         int log = -1;
735
736         while (i) {
737                 i >>= 1;
738                 log++;
739         }
740         return log;
741 }
742
743 /*
744  * Initialize f->zbd_info for devices that are not zoned block devices. This
745  * allows to execute a ZBD workload against a non-ZBD device.
746  */
747 static int init_zone_info(struct thread_data *td, struct fio_file *f)
748 {
749         uint32_t nr_zones;
750         struct fio_zone_info *p;
751         uint64_t zone_size = td->o.zone_size;
752         uint64_t zone_capacity = td->o.zone_capacity;
753         struct zoned_block_device_info *zbd_info = NULL;
754         int i;
755
756         if (zone_size == 0) {
757                 log_err("%s: Specifying the zone size is mandatory for regular file/block device with --zonemode=zbd\n\n",
758                         f->file_name);
759                 return 1;
760         }
761
762         if (zone_size < 512) {
763                 log_err("%s: zone size must be at least 512 bytes for --zonemode=zbd\n\n",
764                         f->file_name);
765                 return 1;
766         }
767
768         if (zone_capacity == 0)
769                 zone_capacity = zone_size;
770
771         if (zone_capacity > zone_size) {
772                 log_err("%s: job parameter zonecapacity %llu is larger than zone size %llu\n",
773                         f->file_name, td->o.zone_capacity, td->o.zone_size);
774                 return 1;
775         }
776
777         if (f->real_file_size < zone_size) {
778                 log_err("%s: file/device size %"PRIu64" is smaller than zone size %"PRIu64"\n",
779                         f->file_name, f->real_file_size, zone_size);
780                 return -EINVAL;
781         }
782
783         nr_zones = (f->real_file_size + zone_size - 1) / zone_size;
784         zbd_info = scalloc(1, sizeof(*zbd_info) +
785                            (nr_zones + 1) * sizeof(zbd_info->zone_info[0]));
786         if (!zbd_info)
787                 return -ENOMEM;
788
789         mutex_init_pshared(&zbd_info->mutex);
790         zbd_info->refcount = 1;
791         p = &zbd_info->zone_info[0];
792         for (i = 0; i < nr_zones; i++, p++) {
793                 mutex_init_pshared_with_type(&p->mutex,
794                                              PTHREAD_MUTEX_RECURSIVE);
795                 p->start = i * zone_size;
796                 p->wp = p->start;
797                 p->type = ZBD_ZONE_TYPE_SWR;
798                 p->cond = ZBD_ZONE_COND_EMPTY;
799                 p->capacity = zone_capacity;
800                 p->has_wp = 1;
801         }
802         /* a sentinel */
803         p->start = nr_zones * zone_size;
804
805         f->zbd_info = zbd_info;
806         f->zbd_info->zone_size = zone_size;
807         f->zbd_info->zone_size_log2 = is_power_of_2(zone_size) ?
808                 ilog2(zone_size) : 0;
809         f->zbd_info->nr_zones = nr_zones;
810         return 0;
811 }
812
813 /*
814  * Maximum number of zones to report in one operation.
815  */
816 #define ZBD_REPORT_MAX_ZONES    8192U
817
818 /*
819  * Parse the device zone report and store it in f->zbd_info. Must be called
820  * only for devices that are zoned, namely those with a model != ZBD_NONE.
821  */
822 static int parse_zone_info(struct thread_data *td, struct fio_file *f)
823 {
824         int nr_zones, nrz;
825         struct zbd_zone *zones, *z;
826         struct fio_zone_info *p;
827         uint64_t zone_size, offset, capacity;
828         bool same_zone_cap = true;
829         struct zoned_block_device_info *zbd_info = NULL;
830         int i, j, ret = -ENOMEM;
831
832         zones = calloc(ZBD_REPORT_MAX_ZONES, sizeof(struct zbd_zone));
833         if (!zones)
834                 goto out;
835
836         nrz = zbd_report_zones(td, f, 0, zones, ZBD_REPORT_MAX_ZONES);
837         if (nrz < 0) {
838                 ret = nrz;
839                 log_info("fio: report zones (offset 0) failed for %s (%d).\n",
840                          f->file_name, -ret);
841                 goto out;
842         }
843
844         zone_size = zones[0].len;
845         capacity = zones[0].capacity;
846         nr_zones = (f->real_file_size + zone_size - 1) / zone_size;
847
848         if (td->o.zone_size == 0) {
849                 td->o.zone_size = zone_size;
850         } else if (td->o.zone_size != zone_size) {
851                 log_err("fio: %s job parameter zonesize %llu does not match disk zone size %"PRIu64".\n",
852                         f->file_name, td->o.zone_size, zone_size);
853                 ret = -EINVAL;
854                 goto out;
855         }
856
857         dprint(FD_ZBD, "Device %s has %d zones of size %"PRIu64" KB\n",
858                f->file_name, nr_zones, zone_size / 1024);
859
860         zbd_info = scalloc(1, sizeof(*zbd_info) +
861                            (nr_zones + 1) * sizeof(zbd_info->zone_info[0]));
862         if (!zbd_info)
863                 goto out;
864         mutex_init_pshared(&zbd_info->mutex);
865         zbd_info->refcount = 1;
866         p = &zbd_info->zone_info[0];
867         for (offset = 0, j = 0; j < nr_zones;) {
868                 z = &zones[0];
869                 for (i = 0; i < nrz; i++, j++, z++, p++) {
870                         mutex_init_pshared_with_type(&p->mutex,
871                                                      PTHREAD_MUTEX_RECURSIVE);
872                         p->start = z->start;
873                         p->capacity = z->capacity;
874                         if (capacity != z->capacity)
875                                 same_zone_cap = false;
876
877                         switch (z->cond) {
878                         case ZBD_ZONE_COND_NOT_WP:
879                         case ZBD_ZONE_COND_FULL:
880                                 p->wp = p->start + p->capacity;
881                                 break;
882                         default:
883                                 assert(z->start <= z->wp);
884                                 assert(z->wp <= z->start + zone_size);
885                                 p->wp = z->wp;
886                                 break;
887                         }
888
889                         switch (z->type) {
890                         case ZBD_ZONE_TYPE_SWR:
891                                 p->has_wp = 1;
892                                 break;
893                         default:
894                                 p->has_wp = 0;
895                         }
896                         p->type = z->type;
897                         p->cond = z->cond;
898
899                         if (j > 0 && p->start != p[-1].start + zone_size) {
900                                 log_info("%s: invalid zone data [%d:%d]: %"PRIu64" + %"PRIu64" != %"PRIu64"\n",
901                                          f->file_name, j, i,
902                                          p[-1].start, zone_size, p->start);
903                                 ret = -EINVAL;
904                                 goto out;
905                         }
906                 }
907                 z--;
908                 offset = z->start + z->len;
909                 if (j >= nr_zones)
910                         break;
911
912                 nrz = zbd_report_zones(td, f, offset, zones,
913                                        min((uint32_t)(nr_zones - j),
914                                            ZBD_REPORT_MAX_ZONES));
915                 if (nrz < 0) {
916                         ret = nrz;
917                         log_info("fio: report zones (offset %"PRIu64") failed for %s (%d).\n",
918                                  offset, f->file_name, -ret);
919                         goto out;
920                 }
921         }
922
923         /* a sentinel */
924         zbd_info->zone_info[nr_zones].start = offset;
925
926         f->zbd_info = zbd_info;
927         f->zbd_info->zone_size = zone_size;
928         f->zbd_info->zone_size_log2 = is_power_of_2(zone_size) ?
929                 ilog2(zone_size) : 0;
930         f->zbd_info->nr_zones = nr_zones;
931
932         if (same_zone_cap)
933                 dprint(FD_ZBD, "Zone capacity = %"PRIu64" KB\n",
934                        capacity / 1024);
935
936         zbd_info = NULL;
937         ret = 0;
938
939 out:
940         sfree(zbd_info);
941         free(zones);
942         return ret;
943 }
944
945 static int zbd_set_max_write_zones(struct thread_data *td, struct fio_file *f)
946 {
947         struct zoned_block_device_info *zbd = f->zbd_info;
948         unsigned int max_open_zones;
949         int ret;
950
951         if (zbd->model != ZBD_HOST_MANAGED || td->o.ignore_zone_limits) {
952                 /* Only host-managed devices have a max open limit */
953                 zbd->max_write_zones = td->o.max_open_zones;
954                 goto out;
955         }
956
957         /* If host-managed, get the max open limit */
958         ret = zbd_get_max_open_zones(td, f, &max_open_zones);
959         if (ret)
960                 return ret;
961
962         if (!max_open_zones) {
963                 /* No device limit */
964                 zbd->max_write_zones = td->o.max_open_zones;
965         } else if (!td->o.max_open_zones) {
966                 /* No user limit. Set limit to device limit */
967                 zbd->max_write_zones = max_open_zones;
968         } else if (td->o.max_open_zones <= max_open_zones) {
969                 /* Both user limit and dev limit. User limit not too large */
970                 zbd->max_write_zones = td->o.max_open_zones;
971         } else {
972                 /* Both user limit and dev limit. User limit too large */
973                 td_verror(td, EINVAL,
974                           "Specified --max_open_zones is too large");
975                 log_err("Specified --max_open_zones (%d) is larger than max (%u)\n",
976                         td->o.max_open_zones, max_open_zones);
977                 return -EINVAL;
978         }
979
980 out:
981         /* Ensure that the limit is not larger than FIO's internal limit */
982         if (zbd->max_write_zones > ZBD_MAX_WRITE_ZONES) {
983                 td_verror(td, EINVAL, "'max_open_zones' value is too large");
984                 log_err("'max_open_zones' value is larger than %u\n",
985                         ZBD_MAX_WRITE_ZONES);
986                 return -EINVAL;
987         }
988
989         dprint(FD_ZBD, "%s: using max write zones limit: %"PRIu32"\n",
990                f->file_name, zbd->max_write_zones);
991
992         return 0;
993 }
994
995 /*
996  * Allocate zone information and store it into f->zbd_info if zonemode=zbd.
997  *
998  * Returns 0 upon success and a negative error code upon failure.
999  */
1000 static int zbd_create_zone_info(struct thread_data *td, struct fio_file *f)
1001 {
1002         enum zbd_zoned_model zbd_model;
1003         int ret;
1004
1005         assert(td->o.zone_mode == ZONE_MODE_ZBD);
1006
1007         ret = zbd_get_zoned_model(td, f, &zbd_model);
1008         if (ret)
1009                 return ret;
1010
1011         switch (zbd_model) {
1012         case ZBD_HOST_AWARE:
1013         case ZBD_HOST_MANAGED:
1014                 ret = parse_zone_info(td, f);
1015                 if (ret)
1016                         return ret;
1017                 break;
1018         case ZBD_NONE:
1019                 ret = init_zone_info(td, f);
1020                 if (ret)
1021                         return ret;
1022                 break;
1023         default:
1024                 td_verror(td, EINVAL, "Unsupported zoned model");
1025                 log_err("Unsupported zoned model\n");
1026                 return -EINVAL;
1027         }
1028
1029         assert(f->zbd_info);
1030         f->zbd_info->model = zbd_model;
1031
1032         ret = zbd_set_max_write_zones(td, f);
1033         if (ret) {
1034                 zbd_free_zone_info(f);
1035                 return ret;
1036         }
1037
1038         return 0;
1039 }
1040
1041 void zbd_free_zone_info(struct fio_file *f)
1042 {
1043         uint32_t refcount;
1044
1045         assert(f->zbd_info);
1046
1047         pthread_mutex_lock(&f->zbd_info->mutex);
1048         refcount = --f->zbd_info->refcount;
1049         pthread_mutex_unlock(&f->zbd_info->mutex);
1050
1051         assert((int32_t)refcount >= 0);
1052         if (refcount == 0)
1053                 sfree(f->zbd_info);
1054         f->zbd_info = NULL;
1055 }
1056
1057 /*
1058  * Initialize f->zbd_info.
1059  *
1060  * Returns 0 upon success and a negative error code upon failure.
1061  *
1062  * Note: this function can only work correctly if it is called before the first
1063  * fio fork() call.
1064  */
1065 static int zbd_init_zone_info(struct thread_data *td, struct fio_file *file)
1066 {
1067         struct fio_file *f2;
1068         int j, ret;
1069
1070         for_each_td(td2) {
1071                 for_each_file(td2, f2, j) {
1072                         if (td2 == td && f2 == file)
1073                                 continue;
1074                         if (!f2->zbd_info ||
1075                             strcmp(f2->file_name, file->file_name) != 0)
1076                                 continue;
1077                         file->zbd_info = f2->zbd_info;
1078                         file->zbd_info->refcount++;
1079                         return 0;
1080                 }
1081         } end_for_each();
1082
1083         ret = zbd_create_zone_info(td, file);
1084         if (ret < 0)
1085                 td_verror(td, -ret, "zbd_create_zone_info() failed");
1086
1087         return ret;
1088 }
1089
1090 int zbd_init_files(struct thread_data *td)
1091 {
1092         struct fio_file *f;
1093         int i;
1094
1095         for_each_file(td, f, i) {
1096                 if (zbd_init_zone_info(td, f))
1097                         return 1;
1098         }
1099
1100         return 0;
1101 }
1102
1103 void zbd_recalc_options_with_zone_granularity(struct thread_data *td)
1104 {
1105         struct fio_file *f;
1106         int i;
1107
1108         for_each_file(td, f, i) {
1109                 struct zoned_block_device_info *zbd = f->zbd_info;
1110                 uint64_t zone_size;
1111
1112                 /* zonemode=strided doesn't get per-file zone size. */
1113                 zone_size = zbd ? zbd->zone_size : td->o.zone_size;
1114                 if (zone_size == 0)
1115                         continue;
1116
1117                 if (td->o.size_nz > 0)
1118                         td->o.size = td->o.size_nz * zone_size;
1119                 if (td->o.io_size_nz > 0)
1120                         td->o.io_size = td->o.io_size_nz * zone_size;
1121                 if (td->o.start_offset_nz > 0)
1122                         td->o.start_offset = td->o.start_offset_nz * zone_size;
1123                 if (td->o.offset_increment_nz > 0)
1124                         td->o.offset_increment =
1125                                 td->o.offset_increment_nz * zone_size;
1126                 if (td->o.zone_skip_nz > 0)
1127                         td->o.zone_skip = td->o.zone_skip_nz * zone_size;
1128         }
1129 }
1130
1131 static uint64_t zbd_verify_and_set_vdb(struct thread_data *td,
1132                                        const struct fio_file *f)
1133 {
1134         struct fio_zone_info *zb, *ze, *z;
1135         uint64_t wp_vdb = 0;
1136         struct zoned_block_device_info *zbdi = f->zbd_info;
1137
1138         assert(td->runstate < TD_RUNNING);
1139         assert(zbdi);
1140
1141         if (!accounting_vdb(td, f))
1142                 return 0;
1143
1144         /*
1145          * Ensure that the I/O range includes one or more sequential zones so
1146          * that f->min_zone and f->max_zone have different values.
1147          */
1148         if (!zbd_is_seq_job(f))
1149                 return 0;
1150
1151         if (zbdi->write_min_zone != zbdi->write_max_zone) {
1152                 if (zbdi->write_min_zone != f->min_zone ||
1153                     zbdi->write_max_zone != f->max_zone) {
1154                         td_verror(td, EINVAL,
1155                                   "multi-jobs with different write ranges are "
1156                                   "not supported with zone_reset_threshold");
1157                         log_err("multi-jobs with different write ranges are "
1158                                 "not supported with zone_reset_threshold\n");
1159                 }
1160                 return 0;
1161         }
1162
1163         zbdi->write_min_zone = f->min_zone;
1164         zbdi->write_max_zone = f->max_zone;
1165
1166         zb = zbd_get_zone(f, f->min_zone);
1167         ze = zbd_get_zone(f, f->max_zone);
1168         for (z = zb; z < ze; z++)
1169                 if (z->has_wp)
1170                         wp_vdb += z->wp - z->start;
1171
1172         zbdi->wp_valid_data_bytes = wp_vdb;
1173
1174         return wp_vdb;
1175 }
1176
1177 int zbd_setup_files(struct thread_data *td)
1178 {
1179         struct fio_file *f;
1180         int i;
1181
1182         if (!zbd_using_direct_io()) {
1183                 log_err("Using direct I/O is mandatory for writing to ZBD drives\n\n");
1184                 return 1;
1185         }
1186
1187         if (!zbd_verify_sizes())
1188                 return 1;
1189
1190         if (!zbd_verify_bs())
1191                 return 1;
1192
1193         if (td->o.experimental_verify) {
1194                 log_err("zonemode=zbd does not support experimental verify\n");
1195                 return 1;
1196         }
1197
1198         for_each_file(td, f, i) {
1199                 struct zoned_block_device_info *zbd = f->zbd_info;
1200                 struct fio_zone_info *z;
1201                 int zi;
1202                 uint64_t vdb;
1203
1204                 assert(zbd);
1205
1206                 f->min_zone = zbd_offset_to_zone_idx(f, f->file_offset);
1207                 f->max_zone =
1208                         zbd_offset_to_zone_idx(f, f->file_offset + f->io_size);
1209
1210                 vdb = zbd_verify_and_set_vdb(td, f);
1211
1212                 dprint(FD_ZBD, "%s(%s): valid data bytes = %" PRIu64 "\n",
1213                        __func__, f->file_name, vdb);
1214
1215                 /*
1216                  * When all zones in the I/O range are conventional, io_size
1217                  * can be smaller than zone size, making min_zone the same
1218                  * as max_zone. This is why the assert below needs to be made
1219                  * conditional.
1220                  */
1221                 if (zbd_is_seq_job(f))
1222                         assert(f->min_zone < f->max_zone);
1223
1224                 if (td->o.max_open_zones > 0 &&
1225                     zbd->max_write_zones != td->o.max_open_zones) {
1226                         log_err("Different 'max_open_zones' values\n");
1227                         return 1;
1228                 }
1229
1230                 /*
1231                  * The per job max open zones limit cannot be used without a
1232                  * global max open zones limit. (As the tracking of open zones
1233                  * is disabled when there is no global max open zones limit.)
1234                  */
1235                 if (td->o.job_max_open_zones && !zbd->max_write_zones) {
1236                         log_err("'job_max_open_zones' cannot be used without a global open zones limit\n");
1237                         return 1;
1238                 }
1239
1240                 /*
1241                  * zbd->max_write_zones is the global limit shared for all jobs
1242                  * that target the same zoned block device. Force sync the per
1243                  * thread global limit with the actual global limit. (The real
1244                  * per thread/job limit is stored in td->o.job_max_open_zones).
1245                  */
1246                 td->o.max_open_zones = zbd->max_write_zones;
1247
1248                 for (zi = f->min_zone; zi < f->max_zone; zi++) {
1249                         z = &zbd->zone_info[zi];
1250                         if (z->cond != ZBD_ZONE_COND_IMP_OPEN &&
1251                             z->cond != ZBD_ZONE_COND_EXP_OPEN)
1252                                 continue;
1253                         if (__zbd_write_zone_get(td, f, z))
1254                                 continue;
1255                         /*
1256                          * If the number of open zones exceeds specified limits,
1257                          * error out.
1258                          */
1259                         log_err("Number of open zones exceeds max_open_zones limit\n");
1260                         return 1;
1261                 }
1262         }
1263
1264         return 0;
1265 }
1266
1267 /*
1268  * Reset zbd_info.write_cnt, the counter that counts down towards the next
1269  * zone reset.
1270  */
1271 static void _zbd_reset_write_cnt(const struct thread_data *td,
1272                                  const struct fio_file *f)
1273 {
1274         assert(0 <= td->o.zrf.u.f && td->o.zrf.u.f <= 1);
1275
1276         f->zbd_info->write_cnt = td->o.zrf.u.f ?
1277                 min(1.0 / td->o.zrf.u.f, 0.0 + UINT_MAX) : UINT_MAX;
1278 }
1279
1280 static void zbd_reset_write_cnt(const struct thread_data *td,
1281                                 const struct fio_file *f)
1282 {
1283         pthread_mutex_lock(&f->zbd_info->mutex);
1284         _zbd_reset_write_cnt(td, f);
1285         pthread_mutex_unlock(&f->zbd_info->mutex);
1286 }
1287
1288 static bool zbd_dec_and_reset_write_cnt(const struct thread_data *td,
1289                                         const struct fio_file *f)
1290 {
1291         uint32_t write_cnt = 0;
1292
1293         pthread_mutex_lock(&f->zbd_info->mutex);
1294         assert(f->zbd_info->write_cnt);
1295         if (f->zbd_info->write_cnt)
1296                 write_cnt = --f->zbd_info->write_cnt;
1297         if (write_cnt == 0)
1298                 _zbd_reset_write_cnt(td, f);
1299         pthread_mutex_unlock(&f->zbd_info->mutex);
1300
1301         return write_cnt == 0;
1302 }
1303
1304 void zbd_file_reset(struct thread_data *td, struct fio_file *f)
1305 {
1306         struct fio_zone_info *zb, *ze;
1307         bool verify_data_left = false;
1308
1309         if (!f->zbd_info || !td_write(td))
1310                 return;
1311
1312         zb = zbd_get_zone(f, f->min_zone);
1313         ze = zbd_get_zone(f, f->max_zone);
1314
1315         /*
1316          * If data verification is enabled reset the affected zones before
1317          * writing any data to avoid that a zone reset has to be issued while
1318          * writing data, which causes data loss.
1319          */
1320         if (td->o.verify != VERIFY_NONE) {
1321                 verify_data_left = td->runstate == TD_VERIFYING ||
1322                         td->io_hist_len || td->verify_batch;
1323                 if (td->io_hist_len && td->o.verify_backlog)
1324                         verify_data_left =
1325                                 td->io_hist_len % td->o.verify_backlog;
1326                 if (!verify_data_left)
1327                         zbd_reset_zones(td, f, zb, ze);
1328         }
1329
1330         zbd_reset_write_cnt(td, f);
1331 }
1332
1333 /* Return random zone index for one of the write target zones. */
1334 static uint32_t pick_random_zone_idx(const struct fio_file *f,
1335                                      const struct io_u *io_u)
1336 {
1337         return (io_u->offset - f->file_offset) *
1338                 f->zbd_info->num_write_zones / f->io_size;
1339 }
1340
1341 static bool any_io_in_flight(void)
1342 {
1343         for_each_td(td) {
1344                 if (td->io_u_in_flight)
1345                         return true;
1346         } end_for_each();
1347
1348         return false;
1349 }
1350
1351 /*
1352  * Modify the offset of an I/O unit that does not refer to a zone such that
1353  * in write target zones array. Add a zone to or remove a zone from the lsit if
1354  * necessary. The write target zone is searched across sequential zones.
1355  * This algorithm can only work correctly if all write pointers are
1356  * a multiple of the fio block size. The caller must neither hold z->mutex
1357  * nor f->zbd_info->mutex. Returns with z->mutex held upon success.
1358  */
1359 static struct fio_zone_info *zbd_convert_to_write_zone(struct thread_data *td,
1360                                                        struct io_u *io_u)
1361 {
1362         const uint64_t min_bs = td->o.min_bs[io_u->ddir];
1363         struct fio_file *f = io_u->file;
1364         struct zoned_block_device_info *zbdi = f->zbd_info;
1365         struct fio_zone_info *z;
1366         unsigned int write_zone_idx = -1;
1367         uint32_t zone_idx, new_zone_idx;
1368         int i;
1369         bool wait_zone_write;
1370         bool in_flight;
1371         bool should_retry = true;
1372
1373         assert(is_valid_offset(f, io_u->offset));
1374
1375         if (zbdi->max_write_zones || td->o.job_max_open_zones) {
1376                 /*
1377                  * This statement accesses zbdi->write_zones[] on purpose
1378                  * without locking.
1379                  */
1380                 zone_idx = zbdi->write_zones[pick_random_zone_idx(f, io_u)];
1381         } else {
1382                 zone_idx = zbd_offset_to_zone_idx(f, io_u->offset);
1383         }
1384         if (zone_idx < f->min_zone)
1385                 zone_idx = f->min_zone;
1386         else if (zone_idx >= f->max_zone)
1387                 zone_idx = f->max_zone - 1;
1388
1389         dprint(FD_ZBD,
1390                "%s(%s): starting from zone %d (offset %lld, buflen %lld)\n",
1391                __func__, f->file_name, zone_idx, io_u->offset, io_u->buflen);
1392
1393         /*
1394          * Since z->mutex is the outer lock and zbdi->mutex the inner
1395          * lock it can happen that the state of the zone with index zone_idx
1396          * has changed after 'z' has been assigned and before zbdi->mutex
1397          * has been obtained. Hence the loop.
1398          */
1399         for (;;) {
1400                 uint32_t tmp_idx;
1401
1402                 z = zbd_get_zone(f, zone_idx);
1403                 if (z->has_wp)
1404                         zone_lock(td, f, z);
1405
1406                 pthread_mutex_lock(&zbdi->mutex);
1407
1408                 if (z->has_wp) {
1409                         if (z->cond != ZBD_ZONE_COND_OFFLINE &&
1410                             zbdi->max_write_zones == 0 &&
1411                             td->o.job_max_open_zones == 0)
1412                                 goto examine_zone;
1413                         if (zbdi->num_write_zones == 0) {
1414                                 dprint(FD_ZBD, "%s(%s): no zone is write target\n",
1415                                        __func__, f->file_name);
1416                                 goto choose_other_zone;
1417                         }
1418                 }
1419
1420                 /*
1421                  * Array of write target zones is per-device, shared across all
1422                  * threads. Start with quasi-random candidate zone. Ignore
1423                  * zones which don't belong to thread's offset/size area.
1424                  */
1425                 write_zone_idx = pick_random_zone_idx(f, io_u);
1426                 assert(!write_zone_idx ||
1427                        write_zone_idx < zbdi->num_write_zones);
1428                 tmp_idx = write_zone_idx;
1429
1430                 for (i = 0; i < zbdi->num_write_zones; i++) {
1431                         uint32_t tmpz;
1432
1433                         if (tmp_idx >= zbdi->num_write_zones)
1434                                 tmp_idx = 0;
1435                         tmpz = zbdi->write_zones[tmp_idx];
1436                         if (f->min_zone <= tmpz && tmpz < f->max_zone) {
1437                                 write_zone_idx = tmp_idx;
1438                                 goto found_candidate_zone;
1439                         }
1440
1441                         tmp_idx++;
1442                 }
1443
1444                 dprint(FD_ZBD, "%s(%s): no candidate zone\n",
1445                         __func__, f->file_name);
1446
1447                 pthread_mutex_unlock(&zbdi->mutex);
1448
1449                 if (z->has_wp)
1450                         zone_unlock(z);
1451
1452                 return NULL;
1453
1454 found_candidate_zone:
1455                 new_zone_idx = zbdi->write_zones[write_zone_idx];
1456                 if (new_zone_idx == zone_idx)
1457                         break;
1458                 zone_idx = new_zone_idx;
1459
1460                 pthread_mutex_unlock(&zbdi->mutex);
1461
1462                 if (z->has_wp)
1463                         zone_unlock(z);
1464         }
1465
1466         /* Both z->mutex and zbdi->mutex are held. */
1467
1468 examine_zone:
1469         if (zbd_zone_remainder(z) >= min_bs) {
1470                 pthread_mutex_unlock(&zbdi->mutex);
1471                 goto out;
1472         }
1473
1474 choose_other_zone:
1475         /* Check if number of write target zones reaches one of limits. */
1476         wait_zone_write =
1477                 zbdi->num_write_zones == f->max_zone - f->min_zone ||
1478                 (zbdi->max_write_zones &&
1479                  zbdi->num_write_zones == zbdi->max_write_zones) ||
1480                 (td->o.job_max_open_zones &&
1481                  td->num_write_zones == td->o.job_max_open_zones);
1482
1483         pthread_mutex_unlock(&zbdi->mutex);
1484
1485         /* Only z->mutex is held. */
1486
1487         /*
1488          * When number of write target zones reaches to one of limits, wait for
1489          * zone write completion to one of them before trying a new zone.
1490          */
1491         if (wait_zone_write) {
1492                 dprint(FD_ZBD,
1493                        "%s(%s): quiesce to remove a zone from write target zones array\n",
1494                        __func__, f->file_name);
1495                 io_u_quiesce(td);
1496         }
1497
1498 retry:
1499         /* Zone 'z' is full, so try to choose a new zone. */
1500         for (i = f->io_size / zbdi->zone_size; i > 0; i--) {
1501                 zone_idx++;
1502                 if (z->has_wp)
1503                         zone_unlock(z);
1504                 z++;
1505                 if (!is_valid_offset(f, z->start)) {
1506                         /* Wrap-around. */
1507                         zone_idx = f->min_zone;
1508                         z = zbd_get_zone(f, zone_idx);
1509                 }
1510                 assert(is_valid_offset(f, z->start));
1511                 if (!z->has_wp)
1512                         continue;
1513                 zone_lock(td, f, z);
1514                 if (z->write)
1515                         continue;
1516                 if (zbd_write_zone_get(td, f, z))
1517                         goto out;
1518         }
1519
1520         /* Only z->mutex is held. */
1521
1522         /* Check whether the write fits in any of the write target zones. */
1523         pthread_mutex_lock(&zbdi->mutex);
1524         for (i = 0; i < zbdi->num_write_zones; i++) {
1525                 zone_idx = zbdi->write_zones[i];
1526                 if (zone_idx < f->min_zone || zone_idx >= f->max_zone)
1527                         continue;
1528                 pthread_mutex_unlock(&zbdi->mutex);
1529                 zone_unlock(z);
1530
1531                 z = zbd_get_zone(f, zone_idx);
1532
1533                 zone_lock(td, f, z);
1534                 if (zbd_zone_remainder(z) >= min_bs)
1535                         goto out;
1536                 pthread_mutex_lock(&zbdi->mutex);
1537         }
1538
1539         /*
1540          * When any I/O is in-flight or when all I/Os in-flight get completed,
1541          * the I/Os might have removed zones from the write target array then
1542          * retry the steps to choose a zone. Before retry, call io_u_quiesce()
1543          * to complete in-flight writes.
1544          */
1545         in_flight = any_io_in_flight();
1546         if (in_flight || should_retry) {
1547                 dprint(FD_ZBD,
1548                        "%s(%s): wait zone write and retry write target zone selection\n",
1549                        __func__, f->file_name);
1550                 should_retry = in_flight;
1551                 pthread_mutex_unlock(&zbdi->mutex);
1552                 zone_unlock(z);
1553                 io_u_quiesce(td);
1554                 zone_lock(td, f, z);
1555                 goto retry;
1556         }
1557
1558         pthread_mutex_unlock(&zbdi->mutex);
1559
1560         zone_unlock(z);
1561
1562         dprint(FD_ZBD, "%s(%s): did not choose another write zone\n",
1563                __func__, f->file_name);
1564
1565         return NULL;
1566
1567 out:
1568         dprint(FD_ZBD, "%s(%s): returning zone %d\n",
1569                __func__, f->file_name, zone_idx);
1570
1571         io_u->offset = z->start;
1572         assert(z->has_wp);
1573         assert(z->cond != ZBD_ZONE_COND_OFFLINE);
1574
1575         return z;
1576 }
1577
1578 /*
1579  * Find another zone which has @min_bytes of readable data. Search in zones
1580  * @zb + 1 .. @zl. For random workload, also search in zones @zb - 1 .. @zf.
1581  *
1582  * Either returns NULL or returns a zone pointer. When the zone has write
1583  * pointer, hold the mutex for the zone.
1584  */
1585 static struct fio_zone_info *
1586 zbd_find_zone(struct thread_data *td, struct io_u *io_u, uint64_t min_bytes,
1587               struct fio_zone_info *zb, struct fio_zone_info *zl)
1588 {
1589         struct fio_file *f = io_u->file;
1590         struct fio_zone_info *z1, *z2;
1591         const struct fio_zone_info *const zf = zbd_get_zone(f, f->min_zone);
1592
1593         /*
1594          * Skip to the next non-empty zone in case of sequential I/O and to
1595          * the nearest non-empty zone in case of random I/O.
1596          */
1597         for (z1 = zb + 1, z2 = zb - 1; z1 < zl || z2 >= zf; z1++, z2--) {
1598                 if (z1 < zl && z1->cond != ZBD_ZONE_COND_OFFLINE) {
1599                         if (z1->has_wp)
1600                                 zone_lock(td, f, z1);
1601                         if (z1->start + min_bytes <= z1->wp)
1602                                 return z1;
1603                         if (z1->has_wp)
1604                                 zone_unlock(z1);
1605                 } else if (!td_random(td)) {
1606                         break;
1607                 }
1608
1609                 if (td_random(td) && z2 >= zf &&
1610                     z2->cond != ZBD_ZONE_COND_OFFLINE) {
1611                         if (z2->has_wp)
1612                                 zone_lock(td, f, z2);
1613                         if (z2->start + min_bytes <= z2->wp)
1614                                 return z2;
1615                         if (z2->has_wp)
1616                                 zone_unlock(z2);
1617                 }
1618         }
1619
1620         dprint(FD_ZBD,
1621                "%s: no zone has %"PRIu64" bytes of readable data\n",
1622                f->file_name, min_bytes);
1623
1624         return NULL;
1625 }
1626
1627 /**
1628  * zbd_end_zone_io - update zone status at command completion
1629  * @io_u: I/O unit
1630  * @z: zone info pointer
1631  *
1632  * If the write command made the zone full, remove it from the write target
1633  * zones array.
1634  *
1635  * The caller must hold z->mutex.
1636  */
1637 static void zbd_end_zone_io(struct thread_data *td, const struct io_u *io_u,
1638                             struct fio_zone_info *z)
1639 {
1640         const struct fio_file *f = io_u->file;
1641
1642         if (io_u->ddir == DDIR_WRITE &&
1643             io_u->offset + io_u->buflen >= zbd_zone_capacity_end(z)) {
1644                 pthread_mutex_lock(&f->zbd_info->mutex);
1645                 zbd_write_zone_put(td, f, z);
1646                 pthread_mutex_unlock(&f->zbd_info->mutex);
1647         }
1648 }
1649
1650 /**
1651  * zbd_queue_io - update the write pointer of a sequential zone
1652  * @io_u: I/O unit
1653  * @success: Whether or not the I/O unit has been queued successfully
1654  * @q: queueing status (busy, completed or queued).
1655  *
1656  * For write and trim operations, update the write pointer of the I/O unit
1657  * target zone.
1658  */
1659 static void zbd_queue_io(struct thread_data *td, struct io_u *io_u, int q,
1660                          bool success)
1661 {
1662         const struct fio_file *f = io_u->file;
1663         struct zoned_block_device_info *zbd_info = f->zbd_info;
1664         struct fio_zone_info *z;
1665         uint64_t zone_end;
1666
1667         assert(zbd_info);
1668
1669         z = zbd_offset_to_zone(f, io_u->offset);
1670         assert(z->has_wp);
1671
1672         if (!success)
1673                 goto unlock;
1674
1675         dprint(FD_ZBD,
1676                "%s: queued I/O (%lld, %llu) for zone %u\n",
1677                f->file_name, io_u->offset, io_u->buflen, zbd_zone_idx(f, z));
1678
1679         switch (io_u->ddir) {
1680         case DDIR_WRITE:
1681                 zone_end = min((uint64_t)(io_u->offset + io_u->buflen),
1682                                zbd_zone_capacity_end(z));
1683
1684                 /*
1685                  * z->wp > zone_end means that one or more I/O errors
1686                  * have occurred.
1687                  */
1688                 if (accounting_vdb(td, f) && z->wp <= zone_end) {
1689                         pthread_mutex_lock(&zbd_info->mutex);
1690                         zbd_info->wp_valid_data_bytes += zone_end - z->wp;
1691                         pthread_mutex_unlock(&zbd_info->mutex);
1692                 }
1693                 z->wp = zone_end;
1694                 break;
1695         default:
1696                 break;
1697         }
1698
1699         if (q == FIO_Q_COMPLETED && !io_u->error)
1700                 zbd_end_zone_io(td, io_u, z);
1701
1702 unlock:
1703         if (!success || q != FIO_Q_QUEUED) {
1704                 /* BUSY or COMPLETED: unlock the zone */
1705                 zone_unlock(z);
1706                 io_u->zbd_put_io = NULL;
1707         }
1708 }
1709
1710 /**
1711  * zbd_put_io - Unlock an I/O unit target zone lock
1712  * @io_u: I/O unit
1713  */
1714 static void zbd_put_io(struct thread_data *td, const struct io_u *io_u)
1715 {
1716         const struct fio_file *f = io_u->file;
1717         struct zoned_block_device_info *zbd_info = f->zbd_info;
1718         struct fio_zone_info *z;
1719
1720         assert(zbd_info);
1721
1722         z = zbd_offset_to_zone(f, io_u->offset);
1723         assert(z->has_wp);
1724
1725         dprint(FD_ZBD,
1726                "%s: terminate I/O (%lld, %llu) for zone %u\n",
1727                f->file_name, io_u->offset, io_u->buflen, zbd_zone_idx(f, z));
1728
1729         zbd_end_zone_io(td, io_u, z);
1730
1731         zone_unlock(z);
1732 }
1733
1734 /*
1735  * Windows and MacOS do not define this.
1736  */
1737 #ifndef EREMOTEIO
1738 #define EREMOTEIO       121     /* POSIX value */
1739 #endif
1740
1741 bool zbd_unaligned_write(int error_code)
1742 {
1743         switch (error_code) {
1744         case EIO:
1745         case EREMOTEIO:
1746                 return true;
1747         }
1748         return false;
1749 }
1750
1751 /**
1752  * setup_zbd_zone_mode - handle zoneskip as necessary for ZBD drives
1753  * @td: FIO thread data.
1754  * @io_u: FIO I/O unit.
1755  *
1756  * For sequential workloads, change the file offset to skip zoneskip bytes when
1757  * no more IO can be performed in the current zone.
1758  * - For read workloads, zoneskip is applied when the io has reached the end of
1759  *   the zone or the zone write position (when td->o.read_beyond_wp is false).
1760  * - For write workloads, zoneskip is applied when the zone is full.
1761  * This applies only to read and write operations.
1762  */
1763 void setup_zbd_zone_mode(struct thread_data *td, struct io_u *io_u)
1764 {
1765         struct fio_file *f = io_u->file;
1766         enum fio_ddir ddir = io_u->ddir;
1767         struct fio_zone_info *z;
1768
1769         assert(td->o.zone_mode == ZONE_MODE_ZBD);
1770         assert(td->o.zone_size);
1771         assert(f->zbd_info);
1772
1773         z = zbd_offset_to_zone(f, f->last_pos[ddir]);
1774
1775         /*
1776          * When the zone capacity is smaller than the zone size and the I/O is
1777          * sequential write, skip to zone end if the latest position is at the
1778          * zone capacity limit.
1779          */
1780         if (z->capacity < f->zbd_info->zone_size &&
1781             !td_random(td) && ddir == DDIR_WRITE &&
1782             f->last_pos[ddir] >= zbd_zone_capacity_end(z)) {
1783                 dprint(FD_ZBD,
1784                        "%s: Jump from zone capacity limit to zone end:"
1785                        " (%"PRIu64" -> %"PRIu64") for zone %u (%"PRIu64")\n",
1786                        f->file_name, f->last_pos[ddir],
1787                        zbd_zone_end(z), zbd_zone_idx(f, z), z->capacity);
1788                 td->io_skip_bytes += zbd_zone_end(z) - f->last_pos[ddir];
1789                 f->last_pos[ddir] = zbd_zone_end(z);
1790         }
1791
1792         /*
1793          * zone_skip is valid only for sequential workloads.
1794          */
1795         if (td_random(td) || !td->o.zone_skip)
1796                 return;
1797
1798         /*
1799          * It is time to switch to a new zone if:
1800          * - zone_bytes == zone_size bytes have already been accessed
1801          * - The last position reached the end of the current zone.
1802          * - For reads with td->o.read_beyond_wp == false, the last position
1803          *   reached the zone write pointer.
1804          */
1805         if (td->zone_bytes >= td->o.zone_size ||
1806             f->last_pos[ddir] >= zbd_zone_end(z) ||
1807             (ddir == DDIR_READ &&
1808              (!td->o.read_beyond_wp) && f->last_pos[ddir] >= z->wp)) {
1809                 /*
1810                  * Skip zones.
1811                  */
1812                 td->zone_bytes = 0;
1813                 f->file_offset += td->o.zone_size + td->o.zone_skip;
1814
1815                 /*
1816                  * Wrap from the beginning, if we exceed the file size
1817                  */
1818                 if (f->file_offset >= f->real_file_size)
1819                         f->file_offset = get_start_offset(td, f);
1820
1821                 f->last_pos[ddir] = f->file_offset;
1822                 td->io_skip_bytes += td->o.zone_skip;
1823         }
1824 }
1825
1826 /**
1827  * zbd_adjust_ddir - Adjust an I/O direction for zonemode=zbd.
1828  *
1829  * @td: FIO thread data.
1830  * @io_u: FIO I/O unit.
1831  * @ddir: I/O direction before adjustment.
1832  *
1833  * Return adjusted I/O direction.
1834  */
1835 enum fio_ddir zbd_adjust_ddir(struct thread_data *td, struct io_u *io_u,
1836                               enum fio_ddir ddir)
1837 {
1838         /*
1839          * In case read direction is chosen for the first random I/O, fio with
1840          * zonemode=zbd stops because no data can be read from zoned block
1841          * devices with all empty zones. Overwrite the first I/O direction as
1842          * write to make sure data to read exists.
1843          */
1844         assert(io_u->file->zbd_info);
1845         if (ddir != DDIR_READ || !td_rw(td))
1846                 return ddir;
1847
1848         if (io_u->file->last_start[DDIR_WRITE] != -1ULL || td->o.read_beyond_wp)
1849                 return DDIR_READ;
1850
1851         return DDIR_WRITE;
1852 }
1853
1854 /**
1855  * zbd_adjust_block - adjust the offset and length as necessary for ZBD drives
1856  * @td: FIO thread data.
1857  * @io_u: FIO I/O unit.
1858  *
1859  * Locking strategy: returns with z->mutex locked if and only if z refers
1860  * to a sequential zone and if io_u_accept is returned. z is the zone that
1861  * corresponds to io_u->offset at the end of this function.
1862  */
1863 enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
1864 {
1865         struct fio_file *f = io_u->file;
1866         struct zoned_block_device_info *zbdi = f->zbd_info;
1867         struct fio_zone_info *zb, *zl, *orig_zb;
1868         uint32_t orig_len = io_u->buflen;
1869         uint64_t min_bs = td->o.min_bs[io_u->ddir];
1870         uint64_t new_len;
1871         int64_t range;
1872
1873         assert(zbdi);
1874         assert(min_bs);
1875         assert(is_valid_offset(f, io_u->offset));
1876         assert(io_u->buflen);
1877
1878         zb = zbd_offset_to_zone(f, io_u->offset);
1879         orig_zb = zb;
1880
1881         if (!zb->has_wp) {
1882                 /* Accept non-write I/Os for conventional zones. */
1883                 if (io_u->ddir != DDIR_WRITE)
1884                         return io_u_accept;
1885
1886                 /*
1887                  * Make sure that writes to conventional zones
1888                  * don't cross over to any sequential zones.
1889                  */
1890                 if (!(zb + 1)->has_wp ||
1891                     io_u->offset + io_u->buflen <= (zb + 1)->start)
1892                         return io_u_accept;
1893
1894                 if (io_u->offset + min_bs > (zb + 1)->start) {
1895                         dprint(FD_IO,
1896                                "%s: off=%llu + min_bs=%"PRIu64" > next zone %"PRIu64"\n",
1897                                f->file_name, io_u->offset,
1898                                min_bs, (zb + 1)->start);
1899                         io_u->offset =
1900                                 zb->start + (zb + 1)->start - io_u->offset;
1901                         new_len = min(io_u->buflen,
1902                                       (zb + 1)->start - io_u->offset);
1903                 } else {
1904                         new_len = (zb + 1)->start - io_u->offset;
1905                 }
1906
1907                 io_u->buflen = new_len / min_bs * min_bs;
1908
1909                 return io_u_accept;
1910         }
1911
1912         /*
1913          * Accept the I/O offset for reads if reading beyond the write pointer
1914          * is enabled.
1915          */
1916         if (zb->cond != ZBD_ZONE_COND_OFFLINE &&
1917             io_u->ddir == DDIR_READ && td->o.read_beyond_wp)
1918                 return io_u_accept;
1919
1920         zone_lock(td, f, zb);
1921
1922         switch (io_u->ddir) {
1923         case DDIR_READ:
1924                 if (td->runstate == TD_VERIFYING && td_write(td))
1925                         goto accept;
1926
1927                 /*
1928                  * Check that there is enough written data in the zone to do an
1929                  * I/O of at least min_bs B. If there isn't, find a new zone for
1930                  * the I/O.
1931                  */
1932                 range = zb->cond != ZBD_ZONE_COND_OFFLINE ?
1933                         zb->wp - zb->start : 0;
1934                 if (range < min_bs ||
1935                     ((!td_random(td)) && (io_u->offset + min_bs > zb->wp))) {
1936                         zone_unlock(zb);
1937                         zl = zbd_get_zone(f, f->max_zone);
1938                         zb = zbd_find_zone(td, io_u, min_bs, zb, zl);
1939                         if (!zb) {
1940                                 dprint(FD_ZBD,
1941                                        "%s: zbd_find_zone(%lld, %llu) failed\n",
1942                                        f->file_name, io_u->offset,
1943                                        io_u->buflen);
1944                                 goto eof;
1945                         }
1946                         /*
1947                          * zbd_find_zone() returned a zone with a range of at
1948                          * least min_bs.
1949                          */
1950                         range = zb->wp - zb->start;
1951                         assert(range >= min_bs);
1952
1953                         if (!td_random(td))
1954                                 io_u->offset = zb->start;
1955                 }
1956
1957                 /*
1958                  * Make sure the I/O is within the zone valid data range while
1959                  * maximizing the I/O size and preserving randomness.
1960                  */
1961                 if (range <= io_u->buflen)
1962                         io_u->offset = zb->start;
1963                 else if (td_random(td))
1964                         io_u->offset = zb->start +
1965                                 ((io_u->offset - orig_zb->start) %
1966                                  (range - io_u->buflen)) / min_bs * min_bs;
1967
1968                 /*
1969                  * When zbd_find_zone() returns a conventional zone,
1970                  * we can simply accept the new i/o offset here.
1971                  */
1972                 if (!zb->has_wp)
1973                         return io_u_accept;
1974
1975                 /*
1976                  * Make sure the I/O does not cross over the zone wp position.
1977                  */
1978                 new_len = min((unsigned long long)io_u->buflen,
1979                               (unsigned long long)(zb->wp - io_u->offset));
1980                 new_len = new_len / min_bs * min_bs;
1981                 if (new_len < io_u->buflen) {
1982                         io_u->buflen = new_len;
1983                         dprint(FD_IO, "Changed length from %u into %llu\n",
1984                                orig_len, io_u->buflen);
1985                 }
1986
1987                 assert(zb->start <= io_u->offset);
1988                 assert(io_u->offset + io_u->buflen <= zb->wp);
1989
1990                 goto accept;
1991
1992         case DDIR_WRITE:
1993                 if (io_u->buflen > zbdi->zone_size) {
1994                         td_verror(td, EINVAL, "I/O buflen exceeds zone size");
1995                         dprint(FD_IO,
1996                                "%s: I/O buflen %llu exceeds zone size %"PRIu64"\n",
1997                                f->file_name, io_u->buflen, zbdi->zone_size);
1998                         goto eof;
1999                 }
2000
2001 retry:
2002                 if (zbd_zone_remainder(zb) > 0 &&
2003                     zbd_zone_remainder(zb) < min_bs) {
2004                         pthread_mutex_lock(&f->zbd_info->mutex);
2005                         zbd_write_zone_put(td, f, zb);
2006                         pthread_mutex_unlock(&f->zbd_info->mutex);
2007                         dprint(FD_ZBD,
2008                                "%s: finish zone %d\n",
2009                                f->file_name, zbd_zone_idx(f, zb));
2010                         io_u_quiesce(td);
2011                         zbd_finish_zone(td, f, zb);
2012                         if (zbd_zone_idx(f, zb) + 1 >= f->max_zone) {
2013                                 if (!td_random(td))
2014                                         goto eof;
2015                         }
2016                         zone_unlock(zb);
2017
2018                         /* Find the next write pointer zone */
2019                         do {
2020                                 zb++;
2021                                 if (zbd_zone_idx(f, zb) >= f->max_zone)
2022                                         zb = zbd_get_zone(f, f->min_zone);
2023                         } while (!zb->has_wp);
2024
2025                         zone_lock(td, f, zb);
2026                 }
2027
2028                 if (!zbd_write_zone_get(td, f, zb)) {
2029                         zone_unlock(zb);
2030                         zb = zbd_convert_to_write_zone(td, io_u);
2031                         if (!zb) {
2032                                 dprint(FD_IO, "%s: can't convert to write target zone",
2033                                        f->file_name);
2034                                 goto eof;
2035                         }
2036                 }
2037
2038                 if (zbd_zone_remainder(zb) > 0 &&
2039                     zbd_zone_remainder(zb) < min_bs)
2040                         goto retry;
2041
2042                 /* Check whether the zone reset threshold has been exceeded */
2043                 if (td->o.zrf.u.f) {
2044                         if (zbdi->wp_valid_data_bytes >=
2045                             f->io_size * td->o.zrt.u.f &&
2046                             zbd_dec_and_reset_write_cnt(td, f))
2047                                 zb->reset_zone = 1;
2048                 }
2049
2050                 /* Reset the zone pointer if necessary */
2051                 if (zb->reset_zone || zbd_zone_full(f, zb, min_bs)) {
2052                         if (td->o.verify != VERIFY_NONE) {
2053                                 /*
2054                                  * Unset io-u->file to tell get_next_verify()
2055                                  * that this IO is not requeue.
2056                                  */
2057                                 io_u->file = NULL;
2058                                 if (!get_next_verify(td, io_u)) {
2059                                         zone_unlock(zb);
2060                                         return io_u_accept;
2061                                 }
2062                                 io_u->file = f;
2063                         }
2064
2065                         /*
2066                          * Since previous write requests may have been submitted
2067                          * asynchronously and since we will submit the zone
2068                          * reset synchronously, wait until previously submitted
2069                          * write requests have completed before issuing a
2070                          * zone reset.
2071                          */
2072                         io_u_quiesce(td);
2073                         zb->reset_zone = 0;
2074                         if (__zbd_reset_zone(td, f, zb) < 0)
2075                                 goto eof;
2076
2077                         if (zb->capacity < min_bs) {
2078                                 td_verror(td, EINVAL, "ZCAP is less min_bs");
2079                                 log_err("zone capacity %"PRIu64" smaller than minimum block size %"PRIu64"\n",
2080                                         zb->capacity, min_bs);
2081                                 goto eof;
2082                         }
2083                 }
2084
2085                 /* Make writes occur at the write pointer */
2086                 assert(!zbd_zone_full(f, zb, min_bs));
2087                 io_u->offset = zb->wp;
2088                 if (!is_valid_offset(f, io_u->offset)) {
2089                         td_verror(td, EINVAL, "invalid WP value");
2090                         dprint(FD_ZBD, "%s: dropped request with offset %llu\n",
2091                                f->file_name, io_u->offset);
2092                         goto eof;
2093                 }
2094
2095                 /*
2096                  * Make sure that the buflen is a multiple of the minimal
2097                  * block size. Give up if shrinking would make the request too
2098                  * small.
2099                  */
2100                 new_len = min((unsigned long long)io_u->buflen,
2101                               zbd_zone_capacity_end(zb) - io_u->offset);
2102                 new_len = new_len / min_bs * min_bs;
2103                 if (new_len == io_u->buflen)
2104                         goto accept;
2105                 if (new_len >= min_bs) {
2106                         io_u->buflen = new_len;
2107                         dprint(FD_IO, "Changed length from %u into %llu\n",
2108                                orig_len, io_u->buflen);
2109                         goto accept;
2110                 }
2111
2112                 td_verror(td, EIO, "zone remainder too small");
2113                 log_err("zone remainder %lld smaller than min block size %"PRIu64"\n",
2114                         (zbd_zone_capacity_end(zb) - io_u->offset), min_bs);
2115
2116                 goto eof;
2117
2118         case DDIR_TRIM:
2119                 /* Check random trim targets a non-empty zone */
2120                 if (!td_random(td) || zb->wp > zb->start)
2121                         goto accept;
2122
2123                 /* Find out a non-empty zone to trim */
2124                 zone_unlock(zb);
2125                 zl = zbd_get_zone(f, f->max_zone);
2126                 zb = zbd_find_zone(td, io_u, 1, zb, zl);
2127                 if (zb) {
2128                         io_u->offset = zb->start;
2129                         dprint(FD_ZBD, "%s: found new zone(%lld) for trim\n",
2130                                f->file_name, io_u->offset);
2131                         goto accept;
2132                 }
2133
2134                 goto eof;
2135
2136         case DDIR_SYNC:
2137                 /* fall-through */
2138         case DDIR_DATASYNC:
2139         case DDIR_SYNC_FILE_RANGE:
2140         case DDIR_WAIT:
2141         case DDIR_LAST:
2142         case DDIR_INVAL:
2143                 goto accept;
2144         }
2145
2146         assert(false);
2147
2148 accept:
2149         assert(zb->has_wp);
2150         assert(zb->cond != ZBD_ZONE_COND_OFFLINE);
2151         assert(!io_u->zbd_queue_io);
2152         assert(!io_u->zbd_put_io);
2153
2154         io_u->zbd_queue_io = zbd_queue_io;
2155         io_u->zbd_put_io = zbd_put_io;
2156
2157         /*
2158          * Since we return with the zone lock still held,
2159          * add an annotation to let Coverity know that it
2160          * is intentional.
2161          */
2162         /* coverity[missing_unlock] */
2163
2164         return io_u_accept;
2165
2166 eof:
2167         if (zb && zb->has_wp)
2168                 zone_unlock(zb);
2169
2170         return io_u_eof;
2171 }
2172
2173 /* Return a string with ZBD statistics */
2174 char *zbd_write_status(const struct thread_stat *ts)
2175 {
2176         char *res;
2177
2178         if (asprintf(&res, "; %"PRIu64" zone resets", ts->nr_zone_resets) < 0)
2179                 return NULL;
2180         return res;
2181 }
2182
2183 /**
2184  * zbd_do_io_u_trim - If reset zone is applicable, do reset zone instead of trim
2185  *
2186  * @td: FIO thread data.
2187  * @io_u: FIO I/O unit.
2188  *
2189  * It is assumed that z->mutex is already locked.
2190  * Return io_u_completed when reset zone succeeds. Return 0 when the target zone
2191  * does not have write pointer. On error, return negative errno.
2192  */
2193 int zbd_do_io_u_trim(struct thread_data *td, struct io_u *io_u)
2194 {
2195         struct fio_file *f = io_u->file;
2196         struct fio_zone_info *z;
2197         int ret;
2198
2199         z = zbd_offset_to_zone(f, io_u->offset);
2200         if (!z->has_wp)
2201                 return 0;
2202
2203         if (io_u->offset != z->start) {
2204                 log_err("Trim offset not at zone start (%lld)\n",
2205                         io_u->offset);
2206                 return -EINVAL;
2207         }
2208
2209         ret = zbd_reset_zone((struct thread_data *)td, f, z);
2210         if (ret < 0)
2211                 return ret;
2212
2213         return io_u_completed;
2214 }