zbd: use zone_lock() in zbd_process_swd()
authorDmitry Fomichev <dmitry.fomichev@wdc.com>
Wed, 27 Jan 2021 04:19:22 +0000 (13:19 +0900)
committerJens Axboe <axboe@kernel.dk>
Fri, 29 Jan 2021 15:14:00 +0000 (08:14 -0700)
Most of ZBD code in fio uses zone_lock() to lock write pointer zones.
This wrapper, besides doing the obvious pthread mutex lock, quiesce
the outstanding i/o when running via asynchronous ioengines. This is
necessary to avoid deadlocks. The function zbd_process_swd(), however,
still uses the naked pthread mutex to lock zones and this leads to a
deadlock when running ZBD test #48 against regular nullb devices.

The fix added in the same patch series that introduced test #48 was to
NOT initialize SWD at all, but this solution is found to create
problems with verify. As the proper fix, modify zbd_process_swd()
to use zone_lock(). This makes the test #48 pass even when SWD counter
is initialized.

Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Reviewed-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
zbd.c

diff --git a/zbd.c b/zbd.c
index 84165ddc50b9d08933db2d45a3fb1ea0eb180ad6..cebde1b696b61793ae7c67e306b8ff1950c73653 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -166,7 +166,8 @@ static bool zbd_zone_full(const struct fio_file *f, struct fio_zone_info *z,
                z->wp + required > zbd_zone_capacity_end(z);
 }
 
-static void zone_lock(struct thread_data *td, struct fio_file *f, struct fio_zone_info *z)
+static void zone_lock(struct thread_data *td, const struct fio_file *f,
+                     struct fio_zone_info *z)
 {
        struct zoned_block_device_info *zbd = f->zbd_info;
        uint32_t nz = z - zbd->zone_info;
@@ -893,7 +894,8 @@ enum swd_action {
 };
 
 /* Calculate the number of sectors with data (swd) and perform action 'a' */
-static uint64_t zbd_process_swd(const struct fio_file *f, enum swd_action a)
+static uint64_t zbd_process_swd(struct thread_data *td,
+                               const struct fio_file *f, enum swd_action a)
 {
        struct fio_zone_info *zb, *ze, *z;
        uint64_t swd = 0;
@@ -903,7 +905,7 @@ static uint64_t zbd_process_swd(const struct fio_file *f, enum swd_action a)
        ze = get_zone(f, f->max_zone);
        for (z = zb; z < ze; z++) {
                if (z->has_wp) {
-                       pthread_mutex_lock(&z->mutex);
+                       zone_lock(td, f, z);
                        wp_swd += z->wp - z->start;
                }
                swd += z->wp - z->start;
@@ -934,33 +936,27 @@ static uint64_t zbd_process_swd(const struct fio_file *f, enum swd_action a)
 static const bool enable_check_swd = false;
 
 /* Check whether the values of zbd_info.*sectors_with_data are correct. */
-static void zbd_check_swd(const struct fio_file *f)
+static void zbd_check_swd(struct thread_data *td, const struct fio_file *f)
 {
        if (!enable_check_swd)
                return;
 
-       zbd_process_swd(f, CHECK_SWD);
-}
-
-static void zbd_init_swd(struct fio_file *f)
-{
-       uint64_t swd;
-
-       swd = zbd_process_swd(f, SET_SWD);
-       dprint(FD_ZBD, "%s(%s): swd = %" PRIu64 "\n", __func__, f->file_name,
-              swd);
+       zbd_process_swd(td, f, CHECK_SWD);
 }
 
 void zbd_file_reset(struct thread_data *td, struct fio_file *f)
 {
        struct fio_zone_info *zb, *ze;
+       uint64_t swd;
 
        if (!f->zbd_info || !td_write(td))
                return;
 
        zb = get_zone(f, f->min_zone);
        ze = get_zone(f, f->max_zone);
-       zbd_init_swd(f);
+       swd = zbd_process_swd(td, f, SET_SWD);
+       dprint(FD_ZBD, "%s(%s): swd = %" PRIu64 "\n", __func__, f->file_name,
+              swd);
        /*
         * If data verification is enabled reset the affected zones before
         * writing any data to avoid that a zone reset has to be issued while
@@ -1413,7 +1409,7 @@ static void zbd_put_io(struct thread_data *td, const struct io_u *io_u)
        zbd_end_zone_io(td, io_u, z);
 
        zone_unlock(z);
-       zbd_check_swd(f);
+       zbd_check_swd(td, f);
 }
 
 /*
@@ -1579,7 +1575,7 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
            io_u->ddir == DDIR_READ && td->o.read_beyond_wp)
                return io_u_accept;
 
-       zbd_check_swd(f);
+       zbd_check_swd(td, f);
 
        zone_lock(td, f, zb);