zbd: return ENOMEM if zone buffer allocation fails
[fio.git] / zbd.c
diff --git a/zbd.c b/zbd.c
index 8e94ee5371b23af562180c24d2ce5c05627e2704..46992746fc2c437e6da7a9b063e850fcecc4292b 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -338,7 +338,7 @@ static bool zbd_verify_bs(void)
                        if (!f->zbd_info)
                                continue;
                        zone_size = f->zbd_info->zone_size;
-                       for (k = 0; k < ARRAY_SIZE(td->o.bs); k++) {
+                       for (k = 0; k < FIO_ARRAY_SIZE(td->o.bs); k++) {
                                if (td->o.verify != VERIFY_NONE &&
                                    zone_size % td->o.bs[k] != 0) {
                                        log_info("%s: block size %llu is not a divisor of the zone size %d\n",
@@ -443,7 +443,7 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
        struct fio_zone_info *p;
        uint64_t zone_size, offset;
        struct zoned_block_device_info *zbd_info = NULL;
-       int i, j, ret = 0;
+       int i, j, ret = -ENOMEM;
 
        zones = calloc(ZBD_REPORT_MAX_ZONES, sizeof(struct zbd_zone));
        if (!zones)
@@ -475,7 +475,6 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
 
        zbd_info = scalloc(1, sizeof(*zbd_info) +
                           (nr_zones + 1) * sizeof(zbd_info->zone_info[0]));
-       ret = -ENOMEM;
        if (!zbd_info)
                goto out;
        mutex_init_pshared(&zbd_info->mutex);
@@ -628,6 +627,11 @@ static int zbd_init_zone_info(struct thread_data *td, struct fio_file *file)
        return ret;
 }
 
+static bool zbd_open_zone(struct thread_data *td, const struct fio_file *f,
+                         uint32_t zone_idx);
+static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
+                         struct fio_zone_info *z);
+
 int zbd_setup_files(struct thread_data *td)
 {
        struct fio_file *f;
@@ -651,6 +655,8 @@ int zbd_setup_files(struct thread_data *td)
 
        for_each_file(td, f, i) {
                struct zoned_block_device_info *zbd = f->zbd_info;
+               struct fio_zone_info *z;
+               int zi;
 
                if (!zbd)
                        continue;
@@ -666,6 +672,23 @@ int zbd_setup_files(struct thread_data *td)
                        log_err("'max_open_zones' value is limited by %u\n", ZBD_MAX_OPEN_ZONES);
                        return 1;
                }
+
+               for (zi = f->min_zone; zi < f->max_zone; zi++) {
+                       z = &zbd->zone_info[zi];
+                       if (z->cond != ZBD_ZONE_COND_IMP_OPEN &&
+                           z->cond != ZBD_ZONE_COND_EXP_OPEN)
+                               continue;
+                       if (zbd_open_zone(td, f, zi))
+                               continue;
+                       /*
+                        * If the number of open zones exceeds specified limits,
+                        * reset all extra open zones.
+                        */
+                       if (zbd_reset_zone(td, f, z) < 0) {
+                               log_err("Failed to reest zone %d\n", zi);
+                               return 1;
+                       }
+               }
        }
 
        return 0;
@@ -694,6 +717,9 @@ static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
        uint64_t length = (z+1)->start - offset;
        int ret = 0;
 
+       if (z->wp == z->start)
+               return 0;
+
        assert(is_valid_offset(f, offset + length - 1));
 
        dprint(FD_ZBD, "%s: resetting wp of zone %u.\n", f->file_name,
@@ -937,11 +963,10 @@ static bool is_zone_open(const struct thread_data *td, const struct fio_file *f,
  * was not yet open and opening a new zone would cause the zone limit to be
  * exceeded.
  */
-static bool zbd_open_zone(struct thread_data *td, const struct io_u *io_u,
+static bool zbd_open_zone(struct thread_data *td, const struct fio_file *f,
                          uint32_t zone_idx)
 {
        const uint32_t min_bs = td->o.min_bs[DDIR_WRITE];
-       const struct fio_file *f = io_u->file;
        struct fio_zone_info *z = &f->zbd_info->zone_info[zone_idx];
        bool res = true;
 
@@ -1129,7 +1154,7 @@ open_other_zone:
                zone_lock(td, f, z);
                if (z->open)
                        continue;
-               if (zbd_open_zone(td, io_u, zone_idx))
+               if (zbd_open_zone(td, f, zone_idx))
                        goto out;
        }
 
@@ -1172,7 +1197,7 @@ static struct fio_zone_info *zbd_replay_write_order(struct thread_data *td,
        const struct fio_file *f = io_u->file;
        const uint32_t min_bs = td->o.min_bs[DDIR_WRITE];
 
-       if (!zbd_open_zone(td, io_u, z - f->zbd_info->zone_info)) {
+       if (!zbd_open_zone(td, f, z - f->zbd_info->zone_info)) {
                pthread_mutex_unlock(&z->mutex);
                z = zbd_convert_to_open_zone(td, io_u);
                assert(z);
@@ -1523,6 +1548,7 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
        case DDIR_READ:
                if (td->runstate == TD_VERIFYING && td_write(td)) {
                        zb = zbd_replay_write_order(td, io_u, zb);
+                       pthread_mutex_unlock(&zb->mutex);
                        goto accept;
                }
                /*
@@ -1581,7 +1607,7 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
        case DDIR_WRITE:
                if (io_u->buflen > f->zbd_info->zone_size)
                        goto eof;
-               if (!zbd_open_zone(td, io_u, zone_idx_b)) {
+               if (!zbd_open_zone(td, f, zone_idx_b)) {
                        pthread_mutex_unlock(&zb->mutex);
                        zb = zbd_convert_to_open_zone(td, io_u);
                        if (!zb)