|
@@ -6330,22 +6330,20 @@ static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void raid5_free_percpu(struct r5conf *conf)
|
|
|
+static int raid456_cpu_dead(unsigned int cpu, struct hlist_node *node)
|
|
|
{
|
|
|
- unsigned long cpu;
|
|
|
+ struct r5conf *conf = hlist_entry_safe(node, struct r5conf, node);
|
|
|
+
|
|
|
+ free_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
+static void raid5_free_percpu(struct r5conf *conf)
|
|
|
+{
|
|
|
if (!conf->percpu)
|
|
|
return;
|
|
|
|
|
|
-#ifdef CONFIG_HOTPLUG_CPU
|
|
|
- unregister_cpu_notifier(&conf->cpu_notify);
|
|
|
-#endif
|
|
|
-
|
|
|
- get_online_cpus();
|
|
|
- for_each_possible_cpu(cpu)
|
|
|
- free_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
|
|
|
- put_online_cpus();
|
|
|
-
|
|
|
+ cpuhp_state_remove_instance(CPUHP_MD_RAID5_PREPARE, &conf->node);
|
|
|
free_percpu(conf->percpu);
|
|
|
}
|
|
|
|
|
@@ -6364,64 +6362,28 @@ static void free_conf(struct r5conf *conf)
|
|
|
kfree(conf);
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_HOTPLUG_CPU
|
|
|
-static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
|
|
|
- void *hcpu)
|
|
|
+static int raid456_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
|
|
|
{
|
|
|
- struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
|
|
|
- long cpu = (long)hcpu;
|
|
|
+ struct r5conf *conf = hlist_entry_safe(node, struct r5conf, node);
|
|
|
struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
|
|
|
|
|
|
- switch (action) {
|
|
|
- case CPU_UP_PREPARE:
|
|
|
- case CPU_UP_PREPARE_FROZEN:
|
|
|
- if (alloc_scratch_buffer(conf, percpu)) {
|
|
|
- pr_err("%s: failed memory allocation for cpu%ld\n",
|
|
|
- __func__, cpu);
|
|
|
- return notifier_from_errno(-ENOMEM);
|
|
|
- }
|
|
|
- break;
|
|
|
- case CPU_DEAD:
|
|
|
- case CPU_DEAD_FROZEN:
|
|
|
- case CPU_UP_CANCELED:
|
|
|
- case CPU_UP_CANCELED_FROZEN:
|
|
|
- free_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
+ if (alloc_scratch_buffer(conf, percpu)) {
|
|
|
+ pr_err("%s: failed memory allocation for cpu%u\n",
|
|
|
+ __func__, cpu);
|
|
|
+ return -ENOMEM;
|
|
|
}
|
|
|
- return NOTIFY_OK;
|
|
|
+ return 0;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
static int raid5_alloc_percpu(struct r5conf *conf)
|
|
|
{
|
|
|
- unsigned long cpu;
|
|
|
int err = 0;
|
|
|
|
|
|
conf->percpu = alloc_percpu(struct raid5_percpu);
|
|
|
if (!conf->percpu)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
-#ifdef CONFIG_HOTPLUG_CPU
|
|
|
- conf->cpu_notify.notifier_call = raid456_cpu_notify;
|
|
|
- conf->cpu_notify.priority = 0;
|
|
|
- err = register_cpu_notifier(&conf->cpu_notify);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-#endif
|
|
|
-
|
|
|
- get_online_cpus();
|
|
|
- for_each_present_cpu(cpu) {
|
|
|
- err = alloc_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
|
|
|
- if (err) {
|
|
|
- pr_err("%s: failed memory allocation for cpu%ld\n",
|
|
|
- __func__, cpu);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- put_online_cpus();
|
|
|
-
|
|
|
+ err = cpuhp_state_add_instance(CPUHP_MD_RAID5_PREPARE, &conf->node);
|
|
|
if (!err) {
|
|
|
conf->scribble_disks = max(conf->raid_disks,
|
|
|
conf->previous_raid_disks);
|
|
@@ -7953,10 +7915,21 @@ static struct md_personality raid4_personality =
|
|
|
|
|
|
static int __init raid5_init(void)
|
|
|
{
|
|
|
+ int ret;
|
|
|
+
|
|
|
raid5_wq = alloc_workqueue("raid5wq",
|
|
|
WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE|WQ_SYSFS, 0);
|
|
|
if (!raid5_wq)
|
|
|
return -ENOMEM;
|
|
|
+
|
|
|
+ ret = cpuhp_setup_state_multi(CPUHP_MD_RAID5_PREPARE,
|
|
|
+ "md/raid5:prepare",
|
|
|
+ raid456_cpu_up_prepare,
|
|
|
+ raid456_cpu_dead);
|
|
|
+ if (ret) {
|
|
|
+ destroy_workqueue(raid5_wq);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
register_md_personality(&raid6_personality);
|
|
|
register_md_personality(&raid5_personality);
|
|
|
register_md_personality(&raid4_personality);
|
|
@@ -7968,6 +7941,7 @@ static void raid5_exit(void)
|
|
|
unregister_md_personality(&raid6_personality);
|
|
|
unregister_md_personality(&raid5_personality);
|
|
|
unregister_md_personality(&raid4_personality);
|
|
|
+ cpuhp_remove_multi_state(CPUHP_MD_RAID5_PREPARE);
|
|
|
destroy_workqueue(raid5_wq);
|
|
|
}
|
|
|
|