Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions block/blk-zoned.c
Original file line number Diff line number Diff line change
Expand Up @@ -1923,27 +1923,33 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
if (!disk->zone_wplugs_pool)
goto free_hash;

disk->zone_wplugs_wq =
alloc_workqueue("%s_zwplugs", WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU,
pool_size, disk->disk_name);
if (!disk->zone_wplugs_wq)
goto destroy_pool;
/*
* We may already have a zone write plug workqueue as this function may
* be called after disk_free_zone_resources(), which does not destroy
* the workqueue (the zone write plugs workqueue is destroyed at
* disk_release() time).
*/
if (!disk->zone_wplugs_wq) {
disk->zone_wplugs_wq =
alloc_workqueue("%s_zwplugs",
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU,
pool_size, disk->disk_name);
if (!disk->zone_wplugs_wq)
goto destroy_pool;
}

disk->zone_wplugs_worker =
kthread_create(disk_zone_wplugs_worker, disk,
"%s_zwplugs_worker", disk->disk_name);
if (IS_ERR(disk->zone_wplugs_worker)) {
ret = PTR_ERR(disk->zone_wplugs_worker);
disk->zone_wplugs_worker = NULL;
goto destroy_wq;
goto destroy_pool;
}
wake_up_process(disk->zone_wplugs_worker);

return 0;

destroy_wq:
destroy_workqueue(disk->zone_wplugs_wq);
disk->zone_wplugs_wq = NULL;
destroy_pool:
mempool_destroy(disk->zone_wplugs_pool);
disk->zone_wplugs_pool = NULL;
Expand Down Expand Up @@ -1999,18 +2005,16 @@ static void disk_set_zones_cond_array(struct gendisk *disk, u8 *zones_cond)
kfree_rcu_mightsleep(zones_cond);
}

void disk_free_zone_resources(struct gendisk *disk)
static void disk_free_zone_resources(struct gendisk *disk)
{
if (disk->zone_wplugs_worker) {
kthread_stop(disk->zone_wplugs_worker);
disk->zone_wplugs_worker = NULL;
}
WARN_ON_ONCE(!list_empty(&disk->zone_wplugs_list));

if (disk->zone_wplugs_wq) {
destroy_workqueue(disk->zone_wplugs_wq);
disk->zone_wplugs_wq = NULL;
}
if (disk->zone_wplugs_wq)
drain_workqueue(disk->zone_wplugs_wq);

disk_destroy_zone_wplugs_hash_table(disk);

Expand All @@ -2020,6 +2024,16 @@ void disk_free_zone_resources(struct gendisk *disk)
disk->nr_zones = 0;
}

void disk_release_zone_resources(struct gendisk *disk)
{
if (disk->zone_wplugs_wq) {
destroy_workqueue(disk->zone_wplugs_wq);
disk->zone_wplugs_wq = NULL;
}

disk_free_zone_resources(disk);
}

struct blk_revalidate_zone_args {
struct gendisk *disk;
u8 *zones_cond;
Expand Down
4 changes: 2 additions & 2 deletions block/blk.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ static inline void ioc_clear_queue(struct request_queue *q)

#ifdef CONFIG_BLK_DEV_ZONED
void disk_init_zone_resources(struct gendisk *disk);
void disk_free_zone_resources(struct gendisk *disk);
void disk_release_zone_resources(struct gendisk *disk);
static inline bool bio_zone_write_plugging(struct bio *bio)
{
return bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING);
Expand Down Expand Up @@ -581,7 +581,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
static inline void disk_init_zone_resources(struct gendisk *disk)
{
}
static inline void disk_free_zone_resources(struct gendisk *disk)
static inline void disk_release_zone_resources(struct gendisk *disk)
{
}
static inline bool bio_zone_write_plugging(struct bio *bio)
Expand Down
2 changes: 1 addition & 1 deletion block/genhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@ static void disk_release(struct device *dev)

disk_release_events(disk);
kfree(disk->random);
disk_free_zone_resources(disk);
disk_release_zone_resources(disk);
xa_destroy(&disk->part_tbl);

kobject_put(&disk->queue_kobj);
Expand Down