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