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 <damien.lemoal@wdc.com>
Tested-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
f->zbd_info->zone_info[zone_idx].open = 0;
}
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
/*
* 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
for (;;) {
z = &f->zbd_info->zone_info[zone_idx];
for (;;) {
z = &f->zbd_info->zone_info[zone_idx];
- pthread_mutex_lock(&z->mutex);
pthread_mutex_lock(&f->zbd_info->mutex);
if (td->o.max_open_zones == 0)
goto examine_zone;
pthread_mutex_lock(&f->zbd_info->mutex);
if (td->o.max_open_zones == 0)
goto examine_zone;
z = &f->zbd_info->zone_info[zone_idx];
}
assert(is_valid_offset(f, z->start));
z = &f->zbd_info->zone_info[zone_idx];
}
assert(is_valid_offset(f, z->start));
- pthread_mutex_lock(&z->mutex);
if (z->open)
continue;
if (zbd_open_zone(td, io_u, zone_idx))
if (z->open)
continue;
if (zbd_open_zone(td, io_u, zone_idx))
z = &f->zbd_info->zone_info[zone_idx];
z = &f->zbd_info->zone_info[zone_idx];
- pthread_mutex_lock(&z->mutex);
if (z->wp + min_bs <= (z+1)->start)
goto out;
pthread_mutex_lock(&f->zbd_info->mutex);
if (z->wp + min_bs <= (z+1)->start)
goto out;
pthread_mutex_lock(&f->zbd_info->mutex);
- /*
- * 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);
- }
switch (io_u->ddir) {
case DDIR_READ:
switch (io_u->ddir) {
case DDIR_READ: