zbd: set thread errors in zbd_adjust_block()
[fio.git] / zbd.c
diff --git a/zbd.c b/zbd.c
index 2cebc5e6d0126bcbe5755dcc4bbf77352cda5b80..8e9fc7d4a4ea8e583087dbd764eea4a393609f78 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -786,11 +786,8 @@ static void zbd_close_zone(struct thread_data *td, const struct fio_file *f,
                if (f->zbd_info->open_zones[open_zone_idx] == zone_idx)
                        break;
        }
-       if (open_zone_idx == f->zbd_info->num_open_zones) {
-               dprint(FD_ZBD, "%s: zone %d is not open\n",
-                      f->file_name, zone_idx);
+       if (open_zone_idx == f->zbd_info->num_open_zones)
                return;
-       }
 
        dprint(FD_ZBD, "%s: closing zone %d\n", f->file_name, zone_idx);
        memmove(f->zbd_info->open_zones + open_zone_idx,
@@ -1090,16 +1087,18 @@ static struct fio_zone_info *zbd_convert_to_open_zone(struct thread_data *td,
                uint32_t tmp_idx;
 
                z = get_zone(f, zone_idx);
-
-               zone_lock(td, f, z);
+               if (z->has_wp)
+                       zone_lock(td, f, z);
                pthread_mutex_lock(&f->zbd_info->mutex);
-               if (z->cond != ZBD_ZONE_COND_OFFLINE &&
-                   td->o.max_open_zones == 0 && td->o.job_max_open_zones == 0)
-                       goto examine_zone;
-               if (f->zbd_info->num_open_zones == 0) {
-                       dprint(FD_ZBD, "%s(%s): no zones are open\n",
-                              __func__, f->file_name);
-                       goto open_other_zone;
+               if (z->has_wp) {
+                       if (z->cond != ZBD_ZONE_COND_OFFLINE &&
+                           td->o.max_open_zones == 0 && td->o.job_max_open_zones == 0)
+                               goto examine_zone;
+                       if (f->zbd_info->num_open_zones == 0) {
+                               dprint(FD_ZBD, "%s(%s): no zones are open\n",
+                                      __func__, f->file_name);
+                               goto open_other_zone;
+                       }
                }
 
                /*
@@ -1108,7 +1107,8 @@ static struct fio_zone_info *zbd_convert_to_open_zone(struct thread_data *td,
                 * Ignore zones which don't belong to thread's offset/size area.
                 */
                open_zone_idx = pick_random_zone_idx(f, io_u);
-               assert(open_zone_idx < f->zbd_info->num_open_zones);
+               assert(!open_zone_idx ||
+                      open_zone_idx < f->zbd_info->num_open_zones);
                tmp_idx = open_zone_idx;
                for (i = 0; i < f->zbd_info->num_open_zones; i++) {
                        uint32_t tmpz;
@@ -1127,7 +1127,8 @@ static struct fio_zone_info *zbd_convert_to_open_zone(struct thread_data *td,
                dprint(FD_ZBD, "%s(%s): no candidate zone\n",
                        __func__, f->file_name);
                pthread_mutex_unlock(&f->zbd_info->mutex);
-               zone_unlock(z);
+               if (z->has_wp)
+                       zone_unlock(z);
                return NULL;
 
 found_candidate_zone:
@@ -1136,7 +1137,8 @@ found_candidate_zone:
                        break;
                zone_idx = new_zone_idx;
                pthread_mutex_unlock(&f->zbd_info->mutex);
-               zone_unlock(z);
+               if (z->has_wp)
+                       zone_unlock(z);
        }
 
        /* Both z->mutex and f->zbd_info->mutex are held. */
@@ -1238,10 +1240,23 @@ static struct fio_zone_info *zbd_replay_write_order(struct thread_data *td,
                assert(z);
        }
 
-       if (z->verify_block * min_bs >= z->capacity)
+       if (z->verify_block * min_bs >= z->capacity) {
                log_err("%s: %d * %d >= %llu\n", f->file_name, z->verify_block,
                        min_bs, (unsigned long long)z->capacity);
-       io_u->offset = z->start + z->verify_block++ * min_bs;
+               /*
+                * If the assertion below fails during a test run, adding
+                * "--experimental_verify=1" to the command line may help.
+                */
+               assert(false);
+       }
+       io_u->offset = z->start + z->verify_block * min_bs;
+       if (io_u->offset + io_u->buflen >= zbd_zone_capacity_end(z)) {
+               log_err("%s: %llu + %llu >= %lu\n", f->file_name, io_u->offset,
+                       io_u->buflen, zbd_zone_capacity_end(z));
+               assert(false);
+       }
+       z->verify_block += io_u->buflen / min_bs;
+
        return z;
 }
 
@@ -1673,13 +1688,22 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
                assert(io_u->offset + io_u->buflen <= zb->wp);
                goto accept;
        case DDIR_WRITE:
-               if (io_u->buflen > f->zbd_info->zone_size)
+               if (io_u->buflen > f->zbd_info->zone_size) {
+                       td_verror(td, EINVAL, "I/O buflen exceeds zone size");
+                       dprint(FD_IO,
+                              "%s: I/O buflen %llu exceeds zone size %lu\n",
+                              f->file_name, io_u->buflen,
+                              f->zbd_info->zone_size);
                        goto eof;
+               }
                if (!zbd_open_zone(td, f, zone_idx_b)) {
                        zone_unlock(zb);
                        zb = zbd_convert_to_open_zone(td, io_u);
-                       if (!zb)
+                       if (!zb) {
+                               dprint(FD_IO, "%s: can't convert to open zone",
+                                      f->file_name);
                                goto eof;
+                       }
                        zone_idx_b = zbd_zone_nr(f, zb);
                }
                /* Check whether the zone reset threshold has been exceeded */
@@ -1706,6 +1730,7 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
                                goto eof;
 
                        if (zb->capacity < min_bs) {
+                               td_verror(td, EINVAL, "ZCAP is less min_bs");
                                log_err("zone capacity %llu smaller than minimum block size %d\n",
                                        (unsigned long long)zb->capacity,
                                        min_bs);
@@ -1716,8 +1741,9 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
                assert(!zbd_zone_full(f, zb, min_bs));
                io_u->offset = zb->wp;
                if (!is_valid_offset(f, io_u->offset)) {
-                       dprint(FD_ZBD, "Dropped request with offset %llu\n",
-                              io_u->offset);
+                       td_verror(td, EINVAL, "invalid WP value");
+                       dprint(FD_ZBD, "%s: dropped request with offset %llu\n",
+                              f->file_name, io_u->offset);
                        goto eof;
                }
                /*
@@ -1736,9 +1762,9 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
                               orig_len, io_u->buflen);
                        goto accept;
                }
-               log_err("Zone remainder %lld smaller than minimum block size %d\n",
-                       (zbd_zone_capacity_end(zb) - io_u->offset),
-                       min_bs);
+               td_verror(td, EIO, "zone remainder too small");
+               log_err("zone remainder %lld smaller than min block size %d\n",
+                       (zbd_zone_capacity_end(zb) - io_u->offset), min_bs);
                goto eof;
        case DDIR_TRIM:
                /* fall-through */