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

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