/* Schedule submission of the next plugged BIO if we have one. */
if (!bio_list_empty(&zwplug->bio_list)) {
spin_unlock_irqrestore(&zwplug->lock, flags);
- kblockd_schedule_work(&zwplug->bio_work);
+ queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
return;
}
/* Restart BIO submission if we still have any BIO left. */
if (!bio_list_empty(&zwplug->bio_list)) {
WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
- kblockd_schedule_work(&zwplug->bio_work);
+ queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
goto unlock;
}
disk->zone_wplugs_pool = mempool_create_kmalloc_pool(pool_size,
sizeof(struct blk_zone_wplug));
- if (!disk->zone_wplugs_pool) {
- kfree(disk->zone_wplugs_hash);
- disk->zone_wplugs_hash = NULL;
- disk->zone_wplugs_hash_bits = 0;
- return -ENOMEM;
- }
+ if (!disk->zone_wplugs_pool)
+ goto free_hash;
+
+ disk->zone_wplugs_wq =
+ alloc_workqueue("%s_zwplugs", WQ_MEM_RECLAIM | WQ_HIGHPRI,
+ pool_size, disk->disk_name);
+ if (!disk->zone_wplugs_wq)
+ goto destroy_pool;
return 0;
+
+destroy_pool:
+ mempool_destroy(disk->zone_wplugs_pool);
+ disk->zone_wplugs_pool = NULL;
+free_hash:
+ kfree(disk->zone_wplugs_hash);
+ disk->zone_wplugs_hash = NULL;
+ disk->zone_wplugs_hash_bits = 0;
+ return -ENOMEM;
}
static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk)
{
cancel_work_sync(&disk->zone_wplugs_work);
+ if (disk->zone_wplugs_wq) {
+ destroy_workqueue(disk->zone_wplugs_wq);
+ disk->zone_wplugs_wq = NULL;
+ }
+
disk_destroy_zone_wplugs_hash_table(disk);
/*