Blame SOURCES/kvm-hw-ppc-spapr.c-abort-unplug_request-if-previous-unpl.patch

4a2fec
From 351d24dd01468e63230c68aa27adfebbaf052f3e Mon Sep 17 00:00:00 2001
4a2fec
From: Serhii Popovych <spopovyc@redhat.com>
4a2fec
Date: Thu, 11 Jan 2018 10:37:46 +0100
4a2fec
Subject: [PATCH 05/12] hw/ppc/spapr.c: abort unplug_request if previous unplug
4a2fec
 isn't done
4a2fec
4a2fec
RH-Author: Serhii Popovych <spopovyc@redhat.com>
4a2fec
Message-id: <1515667066-41734-1-git-send-email-spopovyc@redhat.com>
4a2fec
Patchwork-id: 78547
4a2fec
O-Subject: [RHV7.5 qemu-kvm-rhev PATCH] hw/ppc/spapr.c: abort unplug_request if previous unplug isn't done
4a2fec
Bugzilla: 1528173
4a2fec
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
4a2fec
RH-Acked-by: David Gibson <dgibson@redhat.com>
4a2fec
RH-Acked-by: Thomas Huth <thuth@redhat.com>
4a2fec
4a2fec
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
4a2fec
4a2fec
LMB removal is completed only when the spapr_lmb_release callback
4a2fec
is called after all DRCs of the dimm are detached. During this
4a2fec
time, it is possible that a unplug request for the same dimm
4a2fec
arrives, trying to detach DRCs that were detached by the guest
4a2fec
in the first unplug_request.
4a2fec
4a2fec
BQL doesn't help in this case - the lock will prevent any concurrent
4a2fec
removal from happening until the end of spapr_memory_unplug_request
4a2fec
only. What happens is that the second unplug_request ends up calling
4a2fec
spapr_drc_detach in a DRC that were detached already, causing an
4a2fec
assert error in spapr_drc_detach (e.g
4a2fec
https://bugs.launchpad.net/qemu/+bug/1718118).
4a2fec
4a2fec
spapr_lmb_release uses a structure called sPAPRDIMMState, stored in the
4a2fec
spapr->pending_dimm_unplugs QTAIL, to track how many LMB DRCs are left
4a2fec
to be detached by the guest. When there are no more DRCs left, this
4a2fec
structure is deleted and the pc-dimm unplug handler is called to
4a2fec
finish the process.
4a2fec
4a2fec
This patch reuses the sPAPRDIMMState to allow unplug_request to know
4a2fec
if there is an ongoing unplug process for a given dimm, aborting the
4a2fec
unplug request in this case, by doing the following changes:
4a2fec
4a2fec
- in spapr_lmb_release callback, move the dimm state removal to the
4a2fec
end, after pc-dimm unplug handler. With this change we can check for
4a2fec
the existence of the dimm state to see if the unplug process is
4a2fec
done.
4a2fec
4a2fec
- use spapr_pending_dimm_unplugs_find in spapr_memory_unplug_request
4a2fec
to check if the dimm state exists. If positive, there is an unplug
4a2fec
operation already in progress for this dimm, meaning that we should
4a2fec
abort it and warn the user about it.
4a2fec
4a2fec
Fixes: https://bugs.launchpad.net/qemu/+bug/1718118
4a2fec
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
4a2fec
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
4a2fec
(cherry picked from commit 2a129767ebb13ffc29dad6a8e8e6eec06dc38b25)
4a2fec
Signed-off-by: Serhii Popovych <spopovyc@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 hw/ppc/spapr.c | 16 ++++++++++++++--
4a2fec
 1 file changed, 14 insertions(+), 2 deletions(-)
4a2fec
4a2fec
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
4a2fec
index d7fac62..e276632 100644
4a2fec
--- a/hw/ppc/spapr.c
4a2fec
+++ b/hw/ppc/spapr.c
4a2fec
@@ -3070,14 +3070,13 @@ void spapr_lmb_release(DeviceState *dev)
4a2fec
         return;
4a2fec
     }
4a2fec
 
4a2fec
-    spapr_pending_dimm_unplugs_remove(spapr, ds);
4a2fec
-
4a2fec
     /*
4a2fec
      * Now that all the LMBs have been removed by the guest, call the
4a2fec
      * pc-dimm unplug handler to cleanup up the pc-dimm device.
4a2fec
      */
4a2fec
     pc_dimm_memory_unplug(dev, &spapr->hotplug_memory, mr);
4a2fec
     object_unparent(OBJECT(dev));
4a2fec
+    spapr_pending_dimm_unplugs_remove(spapr, ds);
4a2fec
 }
4a2fec
 
4a2fec
 static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
4a2fec
@@ -3106,6 +3105,19 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
4a2fec
         goto out;
4a2fec
     }
4a2fec
 
4a2fec
+    /*
4a2fec
+     * An existing pending dimm state for this DIMM means that there is an
4a2fec
+     * unplug operation in progress, waiting for the spapr_lmb_release
4a2fec
+     * callback to complete the job (BQL can't cover that far). In this case,
4a2fec
+     * bail out to avoid detaching DRCs that were already released.
4a2fec
+     */
4a2fec
+    if (spapr_pending_dimm_unplugs_find(spapr, dimm)) {
4a2fec
+        error_setg(&local_err,
4a2fec
+                   "Memory unplug already in progress for device %s",
4a2fec
+                   dev->id);
4a2fec
+        goto out;
4a2fec
+    }
4a2fec
+
4a2fec
     spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm);
4a2fec
 
4a2fec
     addr = addr_start;
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec