aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDong Jia Shi <bjsdjshi@linux.vnet.ibm.com>2017-02-16 06:27:33 +0100
committerMichael Roth <mdroth@linux.vnet.ibm.com>2017-03-20 14:26:46 -0500
commit34e9c09d03185256d699803d5cb6bfb22872b510 (patch)
tree27c88080e8c49d6a01ce30efe4c680167a139385
parent9e9483dea908cab6f07d1324eff2756d0970bae1 (diff)
s390x/css: reassign subchannel if schid is changed after migration
The subchannel is a means to access a device. While the device number is assigned by the administrator, the subchannel number is assigned by the channel subsystem in an ascending order on cold and hot plug. When doing unplug and replug operations, the same device may end up on a different subchannel; for example - We start with a device fe.1.2222, which ends up at subchannel fe.1.0000. - Now we detach the device, attach a device fe.1.3333 (which would get the now-free subchannel fe.1.0000), re-attach fe.1.2222 (which ends up at subchannel fe.1.0001) and detach fe.1.3333. - We now have the same device (fe.1.2222) available to the guest; it just shows up on a different subchannel. In such a case, the subchannel numbers are different from what a QEMU would create during cold plug when parsing the command line. As this would cause a guest visible change on migration, we do restore the source system's value of the subchannel number on load. So we are now fine from the guest perspective. From the host perspective this will cause an inconsistent state in our internal data structures, though. For example, the subchannel 0 might not be at array position 0. This will lead to problems when we continue doing hot (un/re) plug operations. Let's fix this by cleaning up our internal data structures. Reported-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> Cc: qemu-stable@nongnu.org Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> (cherry picked from commit 3c788ebc6f6eef5ac6e9cb4a28c578abcf08247d) Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
-rw-r--r--hw/s390x/css.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 0f2580d644..91a9fa4f69 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1672,12 +1672,27 @@ void subch_device_save(SubchDev *s, QEMUFile *f)
int subch_device_load(SubchDev *s, QEMUFile *f)
{
+ SubchDev *old_s;
+ uint16_t old_schid = s->schid;
int i;
s->cssid = qemu_get_byte(f);
s->ssid = qemu_get_byte(f);
s->schid = qemu_get_be16(f);
s->devno = qemu_get_be16(f);
+ /* Re-assign subch. */
+ if (old_schid != s->schid) {
+ old_s = channel_subsys.css[s->cssid]->sch_set[s->ssid]->sch[old_schid];
+ /*
+ * (old_s != s) means that some other device has its correct
+ * subchannel already assigned (in load).
+ */
+ if (old_s == s) {
+ css_subch_assign(s->cssid, s->ssid, old_schid, s->devno, NULL);
+ }
+ /* It's OK to re-assign without a prior de-assign. */
+ css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s);
+ }
s->thinint_active = qemu_get_byte(f);
/* SCHIB */
/* PMCW */