[PATCH v2 3/4] zbd: finish zone when all random write target zones have small remainder

Shin'ichiro Kawasaki <[email protected]>
Newsgroups org.kernel.vger.fio
Message-ID <[email protected]>
When a random write target offset points to a zone that is not writable,
zbd_convert_to_write_zone() attempts to convert the write offset to a
different, writable zone. However, the conversion fails when all of the
following conditions are met:

1) the workload has the max_open_zones limit
2) every write target zones, up to the max_open_zones limit, has
   remainder sectors smaller than the block size
3) the next random write request targets a zone not in the write target
   zone list

In this case, zbd_convert_to_write_zone() can not open another zone
without exceeding the max_open_zones constraint. Therefore, It does not
convert the write to a different zone printing with the debug message
"did not choose another write zone". This leads to an unexpected stop of
the random write workload.

To prevent the unexpected write stop, finish one of the write target
zones with small remainder sectors. Check if all write target zones have
small remainder, and store the result in the new local boolean variable
all_write_zones_have_small_remainder. When this condition is true,
choose one of the write target zones and finish it. Then return the zone
from zbd_convert_to_write_zone() enabling the write process to continue.

Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
Reviewed-by: Damien Le Moal <[email protected]>
---
 zbd.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/zbd.c b/zbd.c
index d547bf3b..89519234 100644
--- a/zbd.c
+++ b/zbd.c
@@ -1460,6 +1460,7 @@ static struct fio_zone_info *zbd_convert_to_write_zone(struct thread_data *td,
 	bool wait_zone_write;
 	bool in_flight;
 	bool should_retry = true;
+	bool need_zone_finish;
 
 	assert(is_valid_offset(f, io_u->offset));
 
@@ -1611,6 +1612,7 @@ retry:
 
 	/* Check whether the write fits in any of the write target zones. */
 	pthread_mutex_lock(&zbdi->mutex);
+	need_zone_finish = true;
 	for (i = 0; i < zbdi->num_write_zones; i++) {
 		zone_idx = zbdi->write_zones[i];
 		if (zone_idx < f->min_zone || zone_idx >= f->max_zone)
@@ -1621,8 +1623,10 @@ retry:
 		z = zbd_get_zone(f, zone_idx);
 
 		zone_lock(td, f, z);
-		if (zbd_zone_remainder(z) >= min_bs)
+		if (zbd_zone_remainder(z) >= min_bs) {
+			need_zone_finish = false;
 			goto out;
+		}
 		pthread_mutex_lock(&zbdi->mutex);
 	}
 
@@ -1645,6 +1649,26 @@ retry:
 		goto retry;
 	}
 
+	if (td_random(td) && td->o.verify == VERIFY_NONE && need_zone_finish)
+		/*
+		 * If all open zones have remainder smaller than the block size
+		 * for random write jobs, choose one of the write target zones
+		 * and finish it. When verify is enabled, skip this zone finish
+		 * operation to avoid verify data corruption by overwrite to the
+		 * zone.
+		 */
+		if (zbd_pick_write_zone(f, io_u, &zone_idx)) {
+			pthread_mutex_unlock(&zbdi->mutex);
+			zone_unlock(z);
+			z = zbd_get_zone(f, zone_idx);
+			zone_lock(td, f, z);
+			io_u_quiesce(td);
+			dprint(FD_ZBD, "%s(%s): All write target zones have remainder smaller than block size. Choose zone %d and finish.\n",
+			       __func__, f->file_name, zone_idx);
+			zbd_finish_zone(td, f, z);
+			goto out;
+		}
+
 	pthread_mutex_unlock(&zbdi->mutex);
 
 	zone_unlock(z);
-- 
2.49.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.