diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 06:25:04 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 06:25:04 +0300 |
commit | e71c3978d6f97659f6c3ee942c3e581299e4adf2 (patch) | |
tree | 0b58c76a20a79f5f5d9ada5731aa1dbb149fbcdc /drivers/block/zram | |
parent | f797484c26300fec842fb669c69a3a60eb66e240 (diff) | |
parent | b18cc3de00ec3442cf40ac60787dbe0703b99e24 (diff) | |
download | linux-e71c3978d6f97659f6c3ee942c3e581299e4adf2.tar.xz |
Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull smp hotplug updates from Thomas Gleixner:
"This is the final round of converting the notifier mess to the state
machine. The removal of the notifiers and the related infrastructure
will happen around rc1, as there are conversions outstanding in other
trees.
The whole exercise removed about 2000 lines of code in total and in
course of the conversion several dozen bugs got fixed. The new
mechanism allows to test almost every hotplug step standalone, so
usage sites can exercise all transitions extensively.
There is more room for improvement, like integrating all the
pointlessly different architecture mechanisms of synchronizing,
setting cpus online etc into the core code"
* 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (60 commits)
tracing/rb: Init the CPU mask on allocation
soc/fsl/qbman: Convert to hotplug state machine
soc/fsl/qbman: Convert to hotplug state machine
zram: Convert to hotplug state machine
KVM/PPC/Book3S HV: Convert to hotplug state machine
arm64/cpuinfo: Convert to hotplug state machine
arm64/cpuinfo: Make hotplug notifier symmetric
mm/compaction: Convert to hotplug state machine
iommu/vt-d: Convert to hotplug state machine
mm/zswap: Convert pool to hotplug state machine
mm/zswap: Convert dst-mem to hotplug state machine
mm/zsmalloc: Convert to hotplug state machine
mm/vmstat: Convert to hotplug state machine
mm/vmstat: Avoid on each online CPU loops
mm/vmstat: Drop get_online_cpus() from init_cpu_node_state/vmstat_cpu_dead()
tracing/rb: Convert to hotplug state machine
oprofile/nmi timer: Convert to hotplug state machine
net/iucv: Use explicit clean up labels in iucv_init()
x86/pci/amd-bus: Convert to hotplug state machine
x86/oprofile/nmi: Convert to hotplug state machine
...
Diffstat (limited to 'drivers/block/zram')
-rw-r--r-- | drivers/block/zram/zcomp.c | 76 | ||||
-rw-r--r-- | drivers/block/zram/zcomp.h | 5 | ||||
-rw-r--r-- | drivers/block/zram/zram_drv.c | 9 |
3 files changed, 37 insertions, 53 deletions
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index 4b5cd3a7b2b6..12046f4f00e4 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -160,82 +160,56 @@ int zcomp_decompress(struct zcomp_strm *zstrm, dst, &dst_len); } -static int __zcomp_cpu_notifier(struct zcomp *comp, - unsigned long action, unsigned long cpu) +int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node) { + struct zcomp *comp = hlist_entry(node, struct zcomp, node); struct zcomp_strm *zstrm; - switch (action) { - case CPU_UP_PREPARE: - if (WARN_ON(*per_cpu_ptr(comp->stream, cpu))) - break; - zstrm = zcomp_strm_alloc(comp); - if (IS_ERR_OR_NULL(zstrm)) { - pr_err("Can't allocate a compression stream\n"); - return NOTIFY_BAD; - } - *per_cpu_ptr(comp->stream, cpu) = zstrm; - break; - case CPU_DEAD: - case CPU_UP_CANCELED: - zstrm = *per_cpu_ptr(comp->stream, cpu); - if (!IS_ERR_OR_NULL(zstrm)) - zcomp_strm_free(zstrm); - *per_cpu_ptr(comp->stream, cpu) = NULL; - break; - default: - break; + if (WARN_ON(*per_cpu_ptr(comp->stream, cpu))) + return 0; + + zstrm = zcomp_strm_alloc(comp); + if (IS_ERR_OR_NULL(zstrm)) { + pr_err("Can't allocate a compression stream\n"); + return -ENOMEM; } - return NOTIFY_OK; + *per_cpu_ptr(comp->stream, cpu) = zstrm; + return 0; } -static int zcomp_cpu_notifier(struct notifier_block *nb, - unsigned long action, void *pcpu) +int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node) { - unsigned long cpu = (unsigned long)pcpu; - struct zcomp *comp = container_of(nb, typeof(*comp), notifier); + struct zcomp *comp = hlist_entry(node, struct zcomp, node); + struct zcomp_strm *zstrm; - return __zcomp_cpu_notifier(comp, action, cpu); + zstrm = *per_cpu_ptr(comp->stream, cpu); + if (!IS_ERR_OR_NULL(zstrm)) + zcomp_strm_free(zstrm); + *per_cpu_ptr(comp->stream, cpu) = NULL; + return 0; } static int zcomp_init(struct zcomp *comp) { - unsigned long cpu; int ret; - comp->notifier.notifier_call = zcomp_cpu_notifier; - comp->stream = alloc_percpu(struct zcomp_strm *); if (!comp->stream) return -ENOMEM; - cpu_notifier_register_begin(); - for_each_online_cpu(cpu) { - ret = __zcomp_cpu_notifier(comp, CPU_UP_PREPARE, cpu); - if (ret == NOTIFY_BAD) - goto cleanup; - } - __register_cpu_notifier(&comp->notifier); - cpu_notifier_register_done(); + ret = cpuhp_state_add_instance(CPUHP_ZCOMP_PREPARE, &comp->node); + if (ret < 0) + goto cleanup; return 0; cleanup: - for_each_online_cpu(cpu) - __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu); - cpu_notifier_register_done(); - return -ENOMEM; + free_percpu(comp->stream); + return ret; } void zcomp_destroy(struct zcomp *comp) { - unsigned long cpu; - - cpu_notifier_register_begin(); - for_each_online_cpu(cpu) - __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu); - __unregister_cpu_notifier(&comp->notifier); - cpu_notifier_register_done(); - + cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node); free_percpu(comp->stream); kfree(comp); } diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index 478cac2ed465..41c1002a7d7d 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -19,11 +19,12 @@ struct zcomp_strm { /* dynamic per-device compression frontend */ struct zcomp { struct zcomp_strm * __percpu *stream; - struct notifier_block notifier; - const char *name; + struct hlist_node node; }; +int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node); +int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node); ssize_t zcomp_available_show(const char *comp, char *buf); bool zcomp_available_algorithm(const char *comp); diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 5497f7fc44d0..15f58ab44d0b 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -30,6 +30,7 @@ #include <linux/err.h> #include <linux/idr.h> #include <linux/sysfs.h> +#include <linux/cpuhotplug.h> #include "zram_drv.h" @@ -1443,15 +1444,22 @@ static void destroy_devices(void) idr_for_each(&zram_index_idr, &zram_remove_cb, NULL); idr_destroy(&zram_index_idr); unregister_blkdev(zram_major, "zram"); + cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE); } static int __init zram_init(void) { int ret; + ret = cpuhp_setup_state_multi(CPUHP_ZCOMP_PREPARE, "block/zram:prepare", + zcomp_cpu_up_prepare, zcomp_cpu_dead); + if (ret < 0) + return ret; + ret = class_register(&zram_control_class); if (ret) { pr_err("Unable to register zram-control class\n"); + cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE); return ret; } @@ -1459,6 +1467,7 @@ static int __init zram_init(void) if (zram_major <= 0) { pr_err("Unable to get major number\n"); class_unregister(&zram_control_class); + cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE); return -EBUSY; } |