diff options
author | Greg Kurz <groug@kaod.org> | 2017-07-03 16:54:36 +0200 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2017-07-11 11:04:02 +1000 |
commit | 160bb67885c22f98e3045d9223e2fc915d61c274 (patch) | |
tree | 92647a3105e22a1217c4f4c040a96ec391d071d6 /hw/ppc | |
parent | 95cb0657766a495ca54caa15ab9feb5681c20f15 (diff) |
spapr: fix memory hotplug error path
QEMU shouldn't abort if spapr_add_lmbs()->spapr_drc_attach() fails.
Let's propagate the error instead, like it is done everywhere else
where spapr_drc_attach() is called.
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Daniel Barboza <danielhb@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/spapr.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 70b3fd374e..ba8f57a5a0 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2601,6 +2601,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, int i, fdt_offset, fdt_size; void *fdt; uint64_t addr = addr_start; + Error *local_err = NULL; for (i = 0; i < nr_lmbs; i++) { drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, @@ -2611,7 +2612,18 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, fdt_offset = spapr_populate_memory_node(fdt, node, addr, SPAPR_MEMORY_BLOCK_SIZE); - spapr_drc_attach(drc, dev, fdt, fdt_offset, errp); + spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err); + if (local_err) { + while (addr > addr_start) { + addr -= SPAPR_MEMORY_BLOCK_SIZE; + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, + addr / SPAPR_MEMORY_BLOCK_SIZE); + spapr_drc_detach(drc, dev, NULL); + } + g_free(fdt); + error_propagate(errp, local_err); + return; + } addr += SPAPR_MEMORY_BLOCK_SIZE; } /* send hotplug notification to the @@ -2651,14 +2663,20 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, addr = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); if (local_err) { - pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); - goto out; + goto out_unplug; } spapr_add_lmbs(dev, addr, size, node, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), - &error_abort); + &local_err); + if (local_err) { + goto out_unplug; + } + + return; +out_unplug: + pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); out: error_propagate(errp, local_err); } |