Skip to content

Commit a8f59e5

Browse files
damien-lemoalaxboe
authored andcommitted
block: use a per disk workqueue for zone write plugging
A zone write plug BIO work function blk_zone_wplug_bio_work() calls submit_bio_noacct_nocheck() to execute the next unplugged BIO. This function may block. So executing zone plugs BIO works using the block layer global kblockd workqueue can potentially lead to preformance or latency issues as the number of concurrent work for a workqueue is limited to WQ_DFL_ACTIVE (256). 1) For a system with a large number of zoned disks, issuing write requests to otherwise unused zones may be delayed wiating for a work thread to become available. 2) Requeue operations which use kblockd but are independent of zone write plugging may alsoi end up being delayed. To avoid these potential performance issues, create a workqueue per zoned device to execute zone plugs BIO work. The workqueue max active parameter is set to the maximum number of zone write plugs allocated with the zone write plug mempool. This limit is equal to the maximum number of open zones of the disk and defaults to 128 for disks that do not have a limit on the number of open zones. Fixes: dd291d7 ("block: Introduce zone write plugging") Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 8294d49 commit a8f59e5

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

block/blk-zoned.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ static void disk_zone_wplug_unplug_bio(struct gendisk *disk,
11291129
/* Schedule submission of the next plugged BIO if we have one. */
11301130
if (!bio_list_empty(&zwplug->bio_list)) {
11311131
spin_unlock_irqrestore(&zwplug->lock, flags);
1132-
kblockd_schedule_work(&zwplug->bio_work);
1132+
queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
11331133
return;
11341134
}
11351135

@@ -1332,7 +1332,7 @@ static void disk_zone_wplug_handle_error(struct gendisk *disk,
13321332
/* Restart BIO submission if we still have any BIO left. */
13331333
if (!bio_list_empty(&zwplug->bio_list)) {
13341334
WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
1335-
kblockd_schedule_work(&zwplug->bio_work);
1335+
queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
13361336
goto unlock;
13371337
}
13381338

@@ -1409,14 +1409,25 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
14091409

14101410
disk->zone_wplugs_pool = mempool_create_kmalloc_pool(pool_size,
14111411
sizeof(struct blk_zone_wplug));
1412-
if (!disk->zone_wplugs_pool) {
1413-
kfree(disk->zone_wplugs_hash);
1414-
disk->zone_wplugs_hash = NULL;
1415-
disk->zone_wplugs_hash_bits = 0;
1416-
return -ENOMEM;
1417-
}
1412+
if (!disk->zone_wplugs_pool)
1413+
goto free_hash;
1414+
1415+
disk->zone_wplugs_wq =
1416+
alloc_workqueue("%s_zwplugs", WQ_MEM_RECLAIM | WQ_HIGHPRI,
1417+
pool_size, disk->disk_name);
1418+
if (!disk->zone_wplugs_wq)
1419+
goto destroy_pool;
14181420

14191421
return 0;
1422+
1423+
destroy_pool:
1424+
mempool_destroy(disk->zone_wplugs_pool);
1425+
disk->zone_wplugs_pool = NULL;
1426+
free_hash:
1427+
kfree(disk->zone_wplugs_hash);
1428+
disk->zone_wplugs_hash = NULL;
1429+
disk->zone_wplugs_hash_bits = 0;
1430+
return -ENOMEM;
14201431
}
14211432

14221433
static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk)
@@ -1447,6 +1458,11 @@ void disk_free_zone_resources(struct gendisk *disk)
14471458
{
14481459
cancel_work_sync(&disk->zone_wplugs_work);
14491460

1461+
if (disk->zone_wplugs_wq) {
1462+
destroy_workqueue(disk->zone_wplugs_wq);
1463+
disk->zone_wplugs_wq = NULL;
1464+
}
1465+
14501466
disk_destroy_zone_wplugs_hash_table(disk);
14511467

14521468
/*

include/linux/blkdev.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ struct gendisk {
191191
struct hlist_head *zone_wplugs_hash;
192192
struct list_head zone_wplugs_err_list;
193193
struct work_struct zone_wplugs_work;
194+
struct workqueue_struct *zone_wplugs_wq;
194195
#endif /* CONFIG_BLK_DEV_ZONED */
195196

196197
#if IS_ENABLED(CONFIG_CDROM)

0 commit comments

Comments
 (0)