diff options
author | Nathan Lynch <nathanl@linux.ibm.com> | 2019-05-28 18:28:01 -0500 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2019-06-19 20:05:08 +1000 |
commit | 348ea30f51fc63ce3c7fd7dba6043e8e3ee0ef34 (patch) | |
tree | ad391ce2c50619edb86e197d51b62c5234e3b50f /arch/powerpc/platforms/pseries/dlpar.c | |
parent | f474c28fbcbe42faca4eb415172c07d76adcb819 (diff) | |
download | lwn-348ea30f51fc63ce3c7fd7dba6043e8e3ee0ef34.tar.gz lwn-348ea30f51fc63ce3c7fd7dba6043e8e3ee0ef34.zip |
powerpc/pseries: avoid blocking in irq when queuing hotplug events
A couple of bugs in queue_hotplug_event():
1. Unchecked kmalloc result which could lead to an oops.
2. Use of GFP_KERNEL allocations in interrupt context (this code's
only caller is ras_hotplug_interrupt()).
Use kmemdup to avoid open-coding the allocation+copy and check for
failure; use GFP_ATOMIC for both allocations.
Ultimately it probably would be better to avoid or reduce allocations
in this path if possible.
Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/platforms/pseries/dlpar.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/dlpar.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index c852024044bb..4989c5762398 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -390,11 +390,11 @@ void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog) struct pseries_hp_work *work; struct pseries_hp_errorlog *hp_errlog_copy; - hp_errlog_copy = kmalloc(sizeof(struct pseries_hp_errorlog), - GFP_KERNEL); - memcpy(hp_errlog_copy, hp_errlog, sizeof(struct pseries_hp_errorlog)); + hp_errlog_copy = kmemdup(hp_errlog, sizeof(*hp_errlog), GFP_ATOMIC); + if (!hp_errlog_copy) + return; - work = kmalloc(sizeof(struct pseries_hp_work), GFP_KERNEL); + work = kmalloc(sizeof(struct pseries_hp_work), GFP_ATOMIC); if (work) { INIT_WORK((struct work_struct *)work, pseries_hp_work_fn); work->errlog = hp_errlog_copy; |