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