From: Naohiro Aota Date: Fri, 28 Feb 2020 07:12:45 +0000 (+0900) Subject: zbd: use zone_lock to lock a zone X-Git-Tag: fio-3.20~54 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=b27aef6abfba503562d0cb55c17a1d168503403a zbd: use zone_lock to lock a zone commit 6f0c608564c3 ("zbd: Avoid async I/O multi-job workload deadlock") introduced io_u_quiesce() when it failed to lock a zone to avoid deadlock. This situation can happen on the other locking place like zbd_convert_to_open_zone(). Thus, introduce common helper "zone_lock" to lock a zone. Reviewed-by: Damien Le Moal Tested-by: Damien Le Moal Signed-off-by: Naohiro Aota Signed-off-by: Jens Axboe --- diff --git a/zbd.c b/zbd.c index 18a55ea4..b2d94249 100644 --- a/zbd.c +++ b/zbd.c @@ -927,6 +927,24 @@ static void zbd_close_zone(struct thread_data *td, const struct fio_file *f, f->zbd_info->zone_info[zone_idx].open = 0; } +static void zone_lock(struct thread_data *td, struct fio_zone_info *z) +{ + /* + * Lock the io_u target zone. The zone will be unlocked if io_u offset + * is changed or when io_u completes and zbd_put_io() executed. + * To avoid multiple jobs doing asynchronous I/Os from deadlocking each + * other waiting for zone locks when building an io_u batch, first + * only trylock the zone. If the zone is already locked by another job, + * process the currently queued I/Os so that I/O progress is made and + * zones unlocked. + */ + if (pthread_mutex_trylock(&z->mutex) != 0) { + if (!td_ioengine_flagged(td, FIO_SYNCIO)) + io_u_quiesce(td); + pthread_mutex_lock(&z->mutex); + } +} + /* * Modify the offset of an I/O unit that does not refer to an open zone such * that it refers to an open zone. Close an open zone and open a new zone if @@ -969,7 +987,7 @@ static struct fio_zone_info *zbd_convert_to_open_zone(struct thread_data *td, for (;;) { z = &f->zbd_info->zone_info[zone_idx]; - pthread_mutex_lock(&z->mutex); + zone_lock(td, z); pthread_mutex_lock(&f->zbd_info->mutex); if (td->o.max_open_zones == 0) goto examine_zone; @@ -1017,7 +1035,7 @@ examine_zone: z = &f->zbd_info->zone_info[zone_idx]; } assert(is_valid_offset(f, z->start)); - pthread_mutex_lock(&z->mutex); + zone_lock(td, z); if (z->open) continue; if (zbd_open_zone(td, io_u, zone_idx)) @@ -1035,7 +1053,7 @@ examine_zone: z = &f->zbd_info->zone_info[zone_idx]; - pthread_mutex_lock(&z->mutex); + zone_lock(td, z); if (z->wp + min_bs <= (z+1)->start) goto out; pthread_mutex_lock(&f->zbd_info->mutex); @@ -1321,20 +1339,7 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u) zbd_check_swd(f); - /* - * Lock the io_u target zone. The zone will be unlocked if io_u offset - * is changed or when io_u completes and zbd_put_io() executed. - * To avoid multiple jobs doing asynchronous I/Os from deadlocking each - * other waiting for zone locks when building an io_u batch, first - * only trylock the zone. If the zone is already locked by another job, - * process the currently queued I/Os so that I/O progress is made and - * zones unlocked. - */ - if (pthread_mutex_trylock(&zb->mutex) != 0) { - if (!td_ioengine_flagged(td, FIO_SYNCIO)) - io_u_quiesce(td); - pthread_mutex_lock(&zb->mutex); - } + zone_lock(td, zb); switch (io_u->ddir) { case DDIR_READ: