block/mq: Convert to new hotplug state machine
v2 cover block/mq: Convert to new hotplug state machine
The following series converts block/mq to the new hotplug state machine. The series is against block.git/for-next and depends on
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git smp/for-block
This branch contains the necessary infrastructure for multi-instance callbacks which allows us to remove blk-mq-cpu.c completely. It can be pulled into the block tree.
Changes vs. V1:
Use the multi instance callbacks and remove the private notifier handling in the block code.
Thanks,
tglx
--- a/block/blk-mq-cpu.c | 67 ------------------------- b/include/linux/blk-mq.h | 8 --- block/Makefile | 2 block/blk-mq.c | 123 +++++++++++++++++++++-------------------------- block/blk-mq.h | 7 -- 5 files changed, 58 insertions(+), 149 deletions(-)
PATCH v2 1/2 blk/mq/cpu-notif: Convert to hotplug state machine
Replace the block-mq notifier list management with the multi instance facility in the cpu hotplug state machine.
---
block/Makefile | 2 - block/blk-mq-cpu.c | 67 ------------------------------------------------- block/blk-mq.c | 36 +++++++++----------------- block/blk-mq.h | 7 ----- include/linux/blk-mq.h | 8 ----- 5 files changed, 15 insertions(+), 105 deletions(-)
block/Makefile +1 -1
@@ -6,7 +6,7 @@ obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-flush.o blk-settings.o blk-ioc.o blk-map.o \ blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \ blk-lib.o blk-mq.o blk-mq-tag.o \ - blk-mq-sysfs.o blk-mq-cpu.o blk-mq-cpumap.o ioctl.o \ + blk-mq-sysfs.o blk-mq-cpumap.o ioctl.o \ genhd.o scsi_ioctl.o partition-generic.o ioprio.o \ badblocks.o partitions/
block/blk-mq-cpu.c deleted +0 -67
67 lines not on this page · raw message
block/blk-mq.c +13 -23
@@ -1575,11 +1575,13 @@ static struct blk_mq_tags *blk_mq_init_r* software queue to the hw queue dispatch list, and ensure that it * gets run. */ -static int blk_mq_hctx_cpu_offline (struct blk_mq_hw_ctx *hctx,int cpu) +static int blk_mq_hctx_notify_dead (unsigned int cpu,struct hlist_node *node) { +struct blk_mq_hw_ctx *hctx;struct blk_mq_ctx *ctx;LIST_HEAD (tmp); + hctx = hlist_entry_safe(node, struct blk_mq_hw_ctx, cpuhp_dead); ctx =__blk_mq_get_ctx (hctx->queue, cpu);spin_lock (&ctx->lock);
@@ -1590,30 +1592,20 @@ static int blk_mq_hctx_cpu_offline(strucspin_unlock (&ctx->lock);if (list_empty (&tmp)) -return NOTIFY_OK ; +return 0 ;spin_lock (&hctx->lock);list_splice_tail_init (&tmp, &hctx->dispatch);spin_unlock (&hctx->lock);blk_mq_run_hw_queue (hctx, true); -return NOTIFY_OK ; +return 0 ; } -static int blk_mq_hctx_notify (void *data,unsigned long action, -unsigned int cpu) +static void blk_mq_remove_cpuhp (struct blk_mq_hw_ctx *hctx) { -struct blk_mq_hw_ctx *hctx = data; - -if (action ==CPU_DEAD || action ==CPU_DEAD_FROZEN ) -return blk_mq_hctx_cpu_offline (hctx, cpu); - -/* -* In case of CPU online, tags may be reallocated -* in blk_mq_map_swqueue() after mapping is updated. -*/ - -return NOTIFY_OK ; +cpuhp_state_remove_instance_nocalls (CPUHP_BLK_MQ_DEAD , + &hctx->cpuhp_dead); }/* hctx->ctxs will be freed in queue's release handler */
@@ -1633,7 +1625,7 @@ static void blk_mq_exit_hctx(struct requif (set->ops->exit_hctx) set->ops->exit_hctx (hctx, hctx_idx); -blk_mq_unregister_cpu_notifier (&hctx->cpu_notifier); +blk_mq_remove_cpuhp (hctx);blk_free_flush_queue (hctx->fq);sbitmap_free (&hctx->ctx_map); }
@@ -1680,9 +1672,7 @@ static int blk_mq_init_hctx(struct reque hctx->queue_num = hctx_idx; hctx->flags = set->flags & ~BLK_MQ_F_TAG_SHARED ; -blk_mq_init_cpu_notifier (&hctx->cpu_notifier, - blk_mq_hctx_notify, hctx); -blk_mq_register_cpu_notifier (&hctx->cpu_notifier); +cpuhp_state_add_instance_nocalls (CPUHP_BLK_MQ_DEAD , &hctx->cpuhp_dead); hctx->tags = set->tags[hctx_idx];
@@ -1727,8 +1717,7 @@ static int blk_mq_init_hctx(struct reque free_ctxs:kfree (hctx->ctxs); unregister_cpu_notifier: -blk_mq_unregister_cpu_notifier (&hctx->cpu_notifier); - +blk_mq_remove_cpuhp (hctx);return -1 ; }
@@ -2390,7 +2379,8 @@ void blk_mq_enable_hotplug(void)static int __init blk_mq_init (void ) { -blk_mq_cpu_init (); +cpuhp_setup_state_multi (CPUHP_BLK_MQ_DEAD ,"block/mq:dead" ,NULL , + blk_mq_hctx_notify_dead);hotcpu_notifier (blk_mq_queue_reinit_notify,0 );
block/blk-mq.h +0 -7
@@ -32,13 +32,6 @@ void blk_mq_wake_waiters(struct request_/* * CPU hotplug helpers */ -struct blk_mq_cpu_notifier ; -void blk_mq_init_cpu_notifier (struct blk_mq_cpu_notifier *notifier, -int (*fn)(void *,unsigned long ,unsigned int ), -void *data); -void blk_mq_register_cpu_notifier (struct blk_mq_cpu_notifier *notifier); -void blk_mq_unregister_cpu_notifier (struct blk_mq_cpu_notifier *notifier); -void blk_mq_cpu_init (void );void blk_mq_enable_hotplug (void );void blk_mq_disable_hotplug (void );
include/linux/blk-mq.h +1 -7
@@ -7,12 +7,6 @@struct blk_mq_tags ;struct blk_flush_queue ; -struct blk_mq_cpu_notifier { -struct list_head list; -void *data; -int (*notify)(void *data,unsigned long action,unsigned int cpu); -}; - struct blk_mq_hw_ctx { struct { spinlock_t lock;
@@ -53,7 +47,7 @@ struct blk_mq_hw_ctx {struct delayed_work delay_work; -struct blk_mq_cpu_notifier cpu_notifier; +struct hlist_node cpuhp_dead;struct kobject kobj;unsigned long poll_considered;
PATCH v2 2/2 blk/mq: Convert to hotplug state machine
In reply to Thomas GleixnerFrom: Sebastian Andrzej Siewior <[email protected]>
Install the callbacks via the state machine so we can phase out the cpu hotplug notifiers mess.
---
block/blk-mq.c | 87 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 44 deletions(-)
block/blk-mq.c +43 -44
@@ -2090,50 +2090,18 @@ static void blk_mq_queue_reinit(struct rblk_mq_sysfs_register (q); } -static int blk_mq_queue_reinit_notify (struct notifier_block *nb, -unsigned long action,void *hcpu) +/* +* New online cpumask which is going to be set in this hotplug event. +* Declare this cpumasks as global as cpu-hotplug operation is invoked +* one-by-one and dynamically allocating this could result in a failure. +*/ +static struct cpumask cpuhp_online_new; + +static void blk_mq_queue_reinit_work (void ) {struct request_queue *q; -int cpu = (unsigned long )hcpu; -/* -* New online cpumask which is going to be set in this hotplug event. -* Declare this cpumasks as global as cpu-hotplug operation is invoked -* one-by-one and dynamically allocating this could result in a failure. -*/ -static struct cpumask online_new; - -/* -* Before hotadded cpu starts handling requests, new mappings must -* be established. Otherwise, these requests in hw queue might -* never be dispatched. -* -* For example, there is a single hw queue (hctx) and two CPU queues -* (ctx0 for CPU0, and ctx1 for CPU1). -* -* Now CPU1 is just onlined and a request is inserted into -* ctx1->rq_list and set bit0 in pending bitmap as ctx1->index_hw is -* still zero. -* -* And then while running hw queue, flush_busy_ctxs() finds bit0 is -* set in pending bitmap and tries to retrieve requests in -* hctx->ctxs[0]->rq_list. But htx->ctxs[0] is a pointer to ctx0, -* so the request in ctx1->rq_list is ignored. -*/ -switch (action & ~CPU_TASKS_FROZEN ) { -case CPU_DEAD : -case CPU_UP_CANCELED : -cpumask_copy (&online_new, cpu_online_mask); -break ; -case CPU_UP_PREPARE : -cpumask_copy (&online_new, cpu_online_mask); -cpumask_set_cpu (cpu, &online_new); -break ; -default : -return NOTIFY_OK ; - }mutex_lock (&all_q_mutex); -/* * We need to freeze and reinit all existing queues. Freezing * involves synchronous wait for an RCU grace period and doing it
@@ -2154,13 +2122,43 @@ static int blk_mq_queue_reinit_notify(st }list_for_each_entry (q, &all_q_list, all_q_node) -blk_mq_queue_reinit (q, &online_new); +blk_mq_queue_reinit (q, &cpuhp_online_new);list_for_each_entry (q, &all_q_list, all_q_node)blk_mq_unfreeze_queue (q);mutex_unlock (&all_q_mutex); -return NOTIFY_OK ; +} + +static int blk_mq_queue_reinit_dead (unsigned int cpu) +{ +cpumask_clear_cpu (cpu, &cpuhp_online_new); +blk_mq_queue_reinit_work (); +return 0 ; +} + +/* +* Before hotadded cpu starts handling requests, new mappings must be +* established. Otherwise, these requests in hw queue might never be +* dispatched. +* +* For example, there is a single hw queue (hctx) and two CPU queues (ctx0 +* for CPU0, and ctx1 for CPU1). +* +* Now CPU1 is just onlined and a request is inserted into ctx1->rq_list +* and set bit0 in pending bitmap as ctx1->index_hw is still zero. +* +* And then while running hw queue, flush_busy_ctxs() finds bit0 is set in +* pending bitmap and tries to retrieve requests in hctx->ctxs[0]->rq_list. +* But htx->ctxs[0] is a pointer to ctx0, so the request in ctx1->rq_list +* is ignored. +*/ +static int blk_mq_queue_reinit_prepare (unsigned int cpu) +{ +cpumask_copy (&cpuhp_online_new, cpu_online_mask); +cpumask_set_cpu (cpu, &cpuhp_online_new); +blk_mq_queue_reinit_work (); +return 0 ; }static int __blk_mq_alloc_rq_maps (struct blk_mq_tag_set *set)
@@ -2382,8 +2380,9 @@ static int __init blk_mq_init(void)cpuhp_setup_state_multi (CPUHP_BLK_MQ_DEAD ,"block/mq:dead" ,NULL , blk_mq_hctx_notify_dead); -hotcpu_notifier (blk_mq_queue_reinit_notify,0 ); - +cpuhp_setup_state_nocalls (CPUHP_BLK_MQ_PREPARE ,"block/mq:prepare" , + blk_mq_queue_reinit_prepare, + blk_mq_queue_reinit_dead);return 0 ; }subsys_initcall (blk_mq_init);
Jens Axboe
maintainerQuoted 8 lines · Thomas Gleixner
The following series converts block/mq to the new hotplug state machine. The series is against block.git/for-next and depends on
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitsmp/for-blockThis branch contains the necessary infrastructure for multi-instance callbacks which allows us to remove
blk-mq-cpu.ccompletely. It can be pulled into the block tree.
Thanks, I'll pull this in for 4.9.
Signature · 1 line
Jens Axboe
Quoted 11 lines · Jens Axboe
Quoted 8 lines · Thomas Gleixner
The following series converts block/mq to the new hotplug state machine. The series is against block.git/for-next and depends on
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitsmp/for-blockThis branch contains the necessary infrastructure for multi-instance callbacks which allows us to remove
blk-mq-cpu.ccompletely. It can be pulled into the block tree.Thanks, I'll pull this in for 4.9.
I still can't find it in your tree despite other commits today.
Jens Axboe
maintainerQuoted 7 lines · Christoph Hellwing
Quoted 6 lines · Jens Axboe
Quoted 5 lines · Thomas Gleixner
The following series converts block/mq to the new hotplug state machine. The series is against block.git/for-next and depends on
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitsmp/for-block
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
This branch contains the necessary infrastructure for multi-instance callbacks which allows us to remove
blk-mq-cpu.ccompletely. It can be pulled into the block tree.Thanks, I'll pull this in for 4.9.
I still can't find it in your tree despite other commits today.
Didn't get to it yesterday, done now.
Signature · 1 line
Jens Axboe