diff --git a/SOURCES/libvirt-qemu-Avoid-duplicate-resume-events-and-state-changes.patch b/SOURCES/libvirt-qemu-Avoid-duplicate-resume-events-and-state-changes.patch
new file mode 100644
index 0000000..473caeb
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Avoid-duplicate-resume-events-and-state-changes.patch
@@ -0,0 +1,243 @@
+From f01aeffaa7dbb4e9efe61f9826deed14c4cb3b41 Mon Sep 17 00:00:00 2001
+Message-Id: <f01aeffaa7dbb4e9efe61f9826deed14c4cb3b41@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Wed, 12 Sep 2018 14:34:33 +0200
+Subject: [PATCH] qemu: Avoid duplicate resume events and state changes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The only place where VIR_DOMAIN_EVENT_RESUMED should be generated is the
+RESUME event handler to make sure we don't generate duplicate events or
+state changes. In the worse case the duplicity can revert or cover
+changes done by other event handlers.
+
+For example, after QEMU sent RESUME, BLOCK_IO_ERROR, and STOP events
+we could happily mark the domain as running and report
+VIR_DOMAIN_EVENT_RESUMED to registered clients.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1612943
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit e6d77a75c4bf0c017d62b717b75e4bb6aa7a456b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1634758
+https://bugzilla.redhat.com/show_bug.cgi?id=1634759
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_driver.c    | 13 -----------
+ src/qemu/qemu_migration.c | 49 ++++++++++++++++-----------------------
+ src/qemu/qemu_process.c   | 10 ++++----
+ 3 files changed, 24 insertions(+), 48 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 26aa557d9f..295613ba3c 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -1863,7 +1863,6 @@ static int qemuDomainResume(virDomainPtr dom)
+     virQEMUDriverPtr driver = dom->conn->privateData;
+     virDomainObjPtr vm;
+     int ret = -1;
+-    virObjectEventPtr event = NULL;
+     int state;
+     int reason;
+     virQEMUDriverConfigPtr cfg = NULL;
+@@ -1902,9 +1901,6 @@ static int qemuDomainResume(virDomainPtr dom)
+                                "%s", _("resume operation failed"));
+             goto endjob;
+         }
+-        event = virDomainEventLifecycleNewFromObj(vm,
+-                                         VIR_DOMAIN_EVENT_RESUMED,
+-                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
+     }
+     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
+         goto endjob;
+@@ -1915,7 +1911,6 @@ static int qemuDomainResume(virDomainPtr dom)
+ 
+  cleanup:
+     virDomainObjEndAPI(&vm);
+-    virObjectEventStateQueue(driver->domainEventState, event);
+     virObjectUnref(cfg);
+     return ret;
+ }
+@@ -16031,7 +16026,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+     virDomainDefPtr config = NULL;
+     virQEMUDriverConfigPtr cfg = NULL;
+     virCapsPtr caps = NULL;
+-    bool was_running = false;
+     bool was_stopped = false;
+     qemuDomainSaveCookiePtr cookie;
+     virCPUDefPtr origCPU = NULL;
+@@ -16222,7 +16216,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+             priv = vm->privateData;
+             if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
+                 /* Transitions 5, 6 */
+-                was_running = true;
+                 if (qemuProcessStopCPUs(driver, vm,
+                                         VIR_DOMAIN_PAUSED_FROM_SNAPSHOT,
+                                         QEMU_ASYNC_JOB_START) < 0)
+@@ -16319,12 +16312,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+                 event = virDomainEventLifecycleNewFromObj(vm,
+                                                  VIR_DOMAIN_EVENT_STARTED,
+                                                  detail);
+-            } else if (!was_running) {
+-                /* Transition 8 */
+-                detail = VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT;
+-                event = virDomainEventLifecycleNewFromObj(vm,
+-                                                 VIR_DOMAIN_EVENT_RESUMED,
+-                                                 detail);
+             }
+         }
+         break;
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 825a9d399b..67940330aa 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -2982,14 +2982,10 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver,
+         virFreeError(orig_err);
+ 
+         if (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
+-            reason == VIR_DOMAIN_PAUSED_POSTCOPY) {
++            reason == VIR_DOMAIN_PAUSED_POSTCOPY)
+             qemuMigrationAnyPostcopyFailed(driver, vm);
+-        } else if (qemuMigrationSrcRestoreDomainState(driver, vm)) {
+-            event = virDomainEventLifecycleNewFromObj(vm,
+-                                                      VIR_DOMAIN_EVENT_RESUMED,
+-                                                      VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+-            virObjectEventStateQueue(driver->domainEventState, event);
+-        }
++        else
++            qemuMigrationSrcRestoreDomainState(driver, vm);
+ 
+         qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
+                                  priv->job.migParams, priv->job.apiFlags);
+@@ -4624,11 +4620,7 @@ qemuMigrationSrcPerformJob(virQEMUDriverPtr driver,
+         qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
+                                  priv->job.migParams, priv->job.apiFlags);
+ 
+-    if (qemuMigrationSrcRestoreDomainState(driver, vm)) {
+-        event = virDomainEventLifecycleNewFromObj(vm,
+-                                         VIR_DOMAIN_EVENT_RESUMED,
+-                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+-    }
++    qemuMigrationSrcRestoreDomainState(driver, vm);
+ 
+     qemuMigrationJobFinish(driver, vm);
+     if (!virDomainObjIsActive(vm) && ret == 0) {
+@@ -4672,7 +4664,6 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver,
+                              unsigned long resource)
+ {
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+-    virObjectEventPtr event = NULL;
+     int ret = -1;
+ 
+     /* If we didn't start the job in the begin phase, start it now. */
+@@ -4694,11 +4685,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver,
+                                         nmigrate_disks, migrate_disks, migParams);
+ 
+     if (ret < 0) {
+-        if (qemuMigrationSrcRestoreDomainState(driver, vm)) {
+-            event = virDomainEventLifecycleNewFromObj(vm,
+-                                                      VIR_DOMAIN_EVENT_RESUMED,
+-                                                      VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+-        }
++        qemuMigrationSrcRestoreDomainState(driver, vm);
+         goto endjob;
+     }
+ 
+@@ -4722,7 +4709,6 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver,
+ 
+  cleanup:
+     virDomainObjEndAPI(&vm);
+-    virObjectEventStateQueue(driver->domainEventState, event);
+     return ret;
+ }
+ 
+@@ -5074,13 +5060,8 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver,
+                 goto endjob;
+         }
+ 
+-        if (inPostCopy) {
++        if (inPostCopy)
+             doKill = false;
+-            event = virDomainEventLifecycleNewFromObj(vm,
+-                                        VIR_DOMAIN_EVENT_RESUMED,
+-                                        VIR_DOMAIN_EVENT_RESUMED_POSTCOPY);
+-            virObjectEventStateQueue(driver->domainEventState, event);
+-        }
+     }
+ 
+     if (mig->jobInfo) {
+@@ -5111,10 +5092,20 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver,
+ 
+     dom = virGetDomain(dconn, vm->def->name, vm->def->uuid, vm->def->id);
+ 
+-    event = virDomainEventLifecycleNewFromObj(vm,
+-                                              VIR_DOMAIN_EVENT_RESUMED,
+-                                              VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+-    virObjectEventStateQueue(driver->domainEventState, event);
++    if (inPostCopy) {
++        /* The only RESUME event during post-copy migration is triggered by
++         * QEMU when the running domain moves from the source to the
++         * destination host, but then the migration keeps running until all
++         * modified memory is transferred from the source host. This will
++         * result in VIR_DOMAIN_EVENT_RESUMED with RESUMED_POSTCOPY detail.
++         * However, our API documentation says we need to fire another RESUMED
++         * event at the very end of migration with RESUMED_MIGRATED detail.
++         */
++        event = virDomainEventLifecycleNewFromObj(vm,
++                                                  VIR_DOMAIN_EVENT_RESUMED,
++                                                  VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
++        virObjectEventStateQueue(driver->domainEventState, event);
++    }
+ 
+     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
+         virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 37568165b7..2d51c0fa25 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -436,7 +436,6 @@ qemuProcessFakeReboot(void *opaque)
+     virDomainObjPtr vm = opaque;
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+     virQEMUDriverPtr driver = priv->driver;
+-    virObjectEventPtr event = NULL;
+     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+     virDomainRunningReason reason = VIR_DOMAIN_RUNNING_BOOTED;
+     int ret = -1, rc;
+@@ -473,9 +472,6 @@ qemuProcessFakeReboot(void *opaque)
+         goto endjob;
+     }
+     priv->gotShutdown = false;
+-    event = virDomainEventLifecycleNewFromObj(vm,
+-                                     VIR_DOMAIN_EVENT_RESUMED,
+-                                     VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
+ 
+     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
+         VIR_WARN("Unable to save status on vm %s after state change",
+@@ -491,7 +487,6 @@ qemuProcessFakeReboot(void *opaque)
+     if (ret == -1)
+         ignore_value(qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE));
+     virDomainObjEndAPI(&vm);
+-    virObjectEventStateQueue(driver->domainEventState, event);
+     virObjectUnref(cfg);
+ }
+ 
+@@ -3073,7 +3068,10 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
+     if (ret < 0)
+         goto release;
+ 
+-    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
++    /* The RESUME event handler will change the domain state with the reason
++     * saved in priv->runningReason and it will also emit corresponding domain
++     * lifecycle event.
++     */
+ 
+  cleanup:
+     virObjectUnref(cfg);
+-- 
+2.19.1
+
diff --git a/SOURCES/libvirt-qemu-Don-t-ignore-resume-events.patch b/SOURCES/libvirt-qemu-Don-t-ignore-resume-events.patch
new file mode 100644
index 0000000..a44eb50
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Don-t-ignore-resume-events.patch
@@ -0,0 +1,68 @@
+From 7359db070b7a1379ea33e2754a00e56ca5e6b29f Mon Sep 17 00:00:00 2001
+Message-Id: <7359db070b7a1379ea33e2754a00e56ca5e6b29f@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Wed, 7 Nov 2018 14:34:52 +0100
+Subject: [PATCH] qemu: Don't ignore resume events
+
+Since commit v4.7.0-302-ge6d77a75c4 processing RESUME event is mandatory
+for updating domain state. But the event handler explicitly ignored this
+event in some cases. Thus the state would be wrong after a fake reboot
+or when a domain was rebooted after it crashed.
+
+BTW, the code to ignore RESUME event after SHUTDOWN didn't make sense
+even before making RESUME event mandatory. Most likely it was there as a
+result of careless copy&paste from qemuProcessHandleStop.
+
+The corresponding debug message was clarified since the original state
+does not have to be "paused" only and while we have a "resumed" event,
+the state is called "running".
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1612943
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit e47949357ba268e7e8c3adea7c262b84fa002302)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1634759
+https://bugzilla.redhat.com/show_bug.cgi?id=1634758
+https://bugzilla.redhat.com/show_bug.cgi?id=1643338
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+---
+ src/qemu/qemu_process.c | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 2d51c0fa25..9b5cb93325 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -699,15 +699,10 @@ qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+         priv->runningReason = VIR_DOMAIN_RUNNING_UNKNOWN;
+     }
+ 
+-    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
+-        if (priv->gotShutdown) {
+-            VIR_DEBUG("Ignoring RESUME event after SHUTDOWN");
+-            goto unlock;
+-        }
+-
++    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
+         eventDetail = qemuDomainRunningReasonToResumeEvent(reason);
+-        VIR_DEBUG("Transitioned guest %s out of paused into resumed state, "
+-                  "reason '%s', event detail %d",
++        VIR_DEBUG("Transitioned guest %s into running state, reason '%s', "
++                  "event detail %d",
+                   vm->def->name, virDomainRunningReasonTypeToString(reason),
+                   eventDetail);
+ 
+@@ -722,7 +717,6 @@ qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+         }
+     }
+ 
+- unlock:
+     virObjectUnlock(vm);
+     virObjectEventStateQueue(driver->domainEventState, event);
+     virObjectUnref(cfg);
+-- 
+2.19.1
+
diff --git a/SOURCES/libvirt-qemu-Map-running-reason-to-resume-event-detail.patch b/SOURCES/libvirt-qemu-Map-running-reason-to-resume-event-detail.patch
new file mode 100644
index 0000000..817b06b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Map-running-reason-to-resume-event-detail.patch
@@ -0,0 +1,121 @@
+From 919834294448ac9d1569a1f2620ea01d79a86e96 Mon Sep 17 00:00:00 2001
+Message-Id: <919834294448ac9d1569a1f2620ea01d79a86e96@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Tue, 11 Sep 2018 15:13:08 +0200
+Subject: [PATCH] qemu: Map running reason to resume event detail
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Thanks to the previous commit the RESUME event handler knows what reason
+should be used when changing the domain state to VIR_DOMAIN_RUNNING, but
+the emitted VIR_DOMAIN_EVENT_RESUMED event still uses a generic
+VIR_DOMAIN_EVENT_RESUMED_UNPAUSED detail. Luckily, the event detail can
+be easily deduced from the running reason, which saves us from having to
+pass one more value to the handler.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 8ae9b49f5a4a02f57a1dfa20d4fe04c3d40a4665)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1634758
+https://bugzilla.redhat.com/show_bug.cgi?id=1634759
+
+Conflicts:
+	src/qemu/qemu_domain.c
+	src/qemu/qemu_domain.h
+            - nodenames code is not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_domain.c  | 29 +++++++++++++++++++++++++++++
+ src/qemu/qemu_domain.h  |  3 +++
+ src/qemu/qemu_process.c | 11 +++++++----
+ 3 files changed, 39 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 17be6e5537..d80f9b393e 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -13149,3 +13149,32 @@ qemuDomainGetManagedPRSocketPath(qemuDomainObjPrivatePtr priv)
+ 
+     return ret;
+ }
++
++
++virDomainEventResumedDetailType
++qemuDomainRunningReasonToResumeEvent(virDomainRunningReason reason)
++{
++    switch (reason) {
++    case VIR_DOMAIN_RUNNING_RESTORED:
++    case VIR_DOMAIN_RUNNING_FROM_SNAPSHOT:
++        return VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT;
++
++    case VIR_DOMAIN_RUNNING_MIGRATED:
++    case VIR_DOMAIN_RUNNING_MIGRATION_CANCELED:
++        return VIR_DOMAIN_EVENT_RESUMED_MIGRATED;
++
++    case VIR_DOMAIN_RUNNING_POSTCOPY:
++        return VIR_DOMAIN_EVENT_RESUMED_POSTCOPY;
++
++    case VIR_DOMAIN_RUNNING_UNKNOWN:
++    case VIR_DOMAIN_RUNNING_SAVE_CANCELED:
++    case VIR_DOMAIN_RUNNING_BOOTED:
++    case VIR_DOMAIN_RUNNING_UNPAUSED:
++    case VIR_DOMAIN_RUNNING_WAKEUP:
++    case VIR_DOMAIN_RUNNING_CRASHED:
++    case VIR_DOMAIN_RUNNING_LAST:
++        break;
++    }
++
++    return VIR_DOMAIN_EVENT_RESUMED_UNPAUSED;
++}
+diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
+index 6a96f27a5f..cc406e3ca0 100644
+--- a/src/qemu/qemu_domain.h
++++ b/src/qemu/qemu_domain.h
+@@ -1066,4 +1066,7 @@ qemuDomainDiskCachemodeFlags(int cachemode,
+ 
+ char * qemuDomainGetManagedPRSocketPath(qemuDomainObjPrivatePtr priv);
+ 
++virDomainEventResumedDetailType
++qemuDomainRunningReasonToResumeEvent(virDomainRunningReason reason);
++
+ #endif /* __QEMU_DOMAIN_H__ */
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 7325bc4c90..37568165b7 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -694,6 +694,7 @@ qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+     qemuDomainObjPrivatePtr priv;
+     virDomainRunningReason reason = VIR_DOMAIN_RUNNING_UNPAUSED;
++    virDomainEventResumedDetailType eventDetail;
+ 
+     virObjectLock(vm);
+ 
+@@ -709,14 +710,16 @@ qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+             goto unlock;
+         }
+ 
++        eventDetail = qemuDomainRunningReasonToResumeEvent(reason);
+         VIR_DEBUG("Transitioned guest %s out of paused into resumed state, "
+-                  "reason '%s'",
+-                  vm->def->name, virDomainRunningReasonTypeToString(reason));
++                  "reason '%s', event detail %d",
++                  vm->def->name, virDomainRunningReasonTypeToString(reason),
++                  eventDetail);
+ 
+         virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
+         event = virDomainEventLifecycleNewFromObj(vm,
+-                                         VIR_DOMAIN_EVENT_RESUMED,
+-                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
++                                                  VIR_DOMAIN_EVENT_RESUMED,
++                                                  eventDetail);
+ 
+         if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
+             VIR_WARN("Unable to save status on vm %s after state change",
+-- 
+2.19.1
+
diff --git a/SOURCES/libvirt-qemu-Pass-running-reason-to-RESUME-event-handler.patch b/SOURCES/libvirt-qemu-Pass-running-reason-to-RESUME-event-handler.patch
new file mode 100644
index 0000000..6e404ce
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Pass-running-reason-to-RESUME-event-handler.patch
@@ -0,0 +1,123 @@
+From 725d1095dfd473b2a0da59594276413ea6a7fa8b Mon Sep 17 00:00:00 2001
+Message-Id: <725d1095dfd473b2a0da59594276413ea6a7fa8b@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Mon, 10 Sep 2018 19:41:53 +0200
+Subject: [PATCH] qemu: Pass running reason to RESUME event handler
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Whenever we get the RESUME event from QEMU, we change the state of the
+affected domain to VIR_DOMAIN_RUNNING with VIR_DOMAIN_RUNNING_UNPAUSED
+reason. This is fine if the domain is resumed unexpectedly, but when we
+sent "cont" to QEMU we usually have a better reason for the state
+change. The better reason is used in qemuProcessStartCPUs which also
+sets the domain state to running if qemuMonitorStartCPUs reports
+success. Thus we may end up with two state updates in a row, but the
+final reason is correct.
+
+This patch is a preparation for dropping the state change done in
+qemuMonitorStartCPUs for which we need to pass the actual running reason
+to the RESUME event handler and use it there instead of
+VIR_DOMAIN_RUNNING_UNPAUSED.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 5dab984ed0cd0332e59d719420ab2f9d009b952f)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1634758
+https://bugzilla.redhat.com/show_bug.cgi?id=1634759
+
+Conflicts:
+	src/qemu/qemu_domain.h
+            - nodenames code is not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_domain.h  |  4 ++++
+ src/qemu/qemu_process.c | 23 +++++++++++++++++------
+ 2 files changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
+index e748d78adb..6a96f27a5f 100644
+--- a/src/qemu/qemu_domain.h
++++ b/src/qemu/qemu_domain.h
+@@ -363,6 +363,10 @@ struct _qemuDomainObjPrivate {
+ 
+     /* true if qemu-pr-helper process is running for the domain */
+     bool prDaemonRunning;
++
++    /* qemuProcessStartCPUs stores the reason for starting vCPUs here for the
++     * RESUME event handler to use it */
++    virDomainRunningReason runningReason;
+ };
+ 
+ # define QEMU_DOMAIN_PRIVATE(vm) \
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 26979faa72..7325bc4c90 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -692,21 +692,28 @@ qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+     virQEMUDriverPtr driver = opaque;
+     virObjectEventPtr event = NULL;
+     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
++    qemuDomainObjPrivatePtr priv;
++    virDomainRunningReason reason = VIR_DOMAIN_RUNNING_UNPAUSED;
+ 
+     virObjectLock(vm);
+-    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
+-        qemuDomainObjPrivatePtr priv = vm->privateData;
+ 
++    priv = vm->privateData;
++    if (priv->runningReason != VIR_DOMAIN_RUNNING_UNKNOWN) {
++        reason = priv->runningReason;
++        priv->runningReason = VIR_DOMAIN_RUNNING_UNKNOWN;
++    }
++
++    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
+         if (priv->gotShutdown) {
+             VIR_DEBUG("Ignoring RESUME event after SHUTDOWN");
+             goto unlock;
+         }
+ 
+-        VIR_DEBUG("Transitioned guest %s out of paused into resumed state",
+-                  vm->def->name);
++        VIR_DEBUG("Transitioned guest %s out of paused into resumed state, "
++                  "reason '%s'",
++                  vm->def->name, virDomainRunningReasonTypeToString(reason));
+ 
+-        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+-                                 VIR_DOMAIN_RUNNING_UNPAUSED);
++        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
+         event = virDomainEventLifecycleNewFromObj(vm,
+                                          VIR_DOMAIN_EVENT_RESUMED,
+                                          VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
+@@ -3051,6 +3058,8 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
+     }
+     VIR_FREE(priv->lockState);
+ 
++    priv->runningReason = reason;
++
+     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+         goto release;
+ 
+@@ -3068,6 +3077,7 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
+     return ret;
+ 
+  release:
++    priv->runningReason = VIR_DOMAIN_RUNNING_UNKNOWN;
+     if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
+         VIR_WARN("Unable to release lease on %s", vm->def->name);
+     VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
+@@ -5928,6 +5938,7 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
+     priv->monError = false;
+     priv->monStart = 0;
+     priv->gotShutdown = false;
++    priv->runningReason = VIR_DOMAIN_RUNNING_UNKNOWN;
+ 
+     VIR_DEBUG("Updating guest CPU definition");
+     if (qemuProcessUpdateGuestCPU(vm->def, priv->qemuCaps, caps, flags) < 0)
+-- 
+2.19.1
+
diff --git a/SOURCES/libvirt-qemu-Properly-report-VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT.patch b/SOURCES/libvirt-qemu-Properly-report-VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT.patch
new file mode 100644
index 0000000..2cfbf59
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Properly-report-VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT.patch
@@ -0,0 +1,42 @@
+From fcfb306555cbae44542d3819e93a24f68b7e431a Mon Sep 17 00:00:00 2001
+Message-Id: <fcfb306555cbae44542d3819e93a24f68b7e431a@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Mon, 10 Sep 2018 15:10:54 +0200
+Subject: [PATCH] qemu: Properly report VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT was defined but not used anywhere
+in our event generation code. This fixes qemuDomainRevertToSnapshot to
+properly report why the domain was resumed.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 55af06187c48a01192764d8638b85739b0178fe0)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1634758
+https://bugzilla.redhat.com/show_bug.cgi?id=1634759
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_driver.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index c7689cc239..26aa557d9f 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -16321,7 +16321,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+                                                  detail);
+             } else if (!was_running) {
+                 /* Transition 8 */
+-                detail = VIR_DOMAIN_EVENT_RESUMED;
++                detail = VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT;
+                 event = virDomainEventLifecycleNewFromObj(vm,
+                                                  VIR_DOMAIN_EVENT_RESUMED,
+                                                  detail);
+-- 
+2.19.1
+
diff --git a/SOURCES/libvirt-qemu-Report-more-appropriate-running-reasons.patch b/SOURCES/libvirt-qemu-Report-more-appropriate-running-reasons.patch
new file mode 100644
index 0000000..1095745
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Report-more-appropriate-running-reasons.patch
@@ -0,0 +1,61 @@
+From 338a37710209d5fc35e326925318f087d572ba25 Mon Sep 17 00:00:00 2001
+Message-Id: <338a37710209d5fc35e326925318f087d572ba25@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Tue, 11 Sep 2018 19:26:07 +0200
+Subject: [PATCH] qemu: Report more appropriate running reasons
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch replaces some rather generic VIR_DOMAIN_RUNNING_UNPAUSED
+reasons when changing domain state to running with more specific ones.
+All of them are done when libvirtd reconnects to an existing domain
+after being restarted and sees an unfinished migration or save.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 54b5b0ac3945ad5417b67bec8443cf6e7b3d482b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1634758
+https://bugzilla.redhat.com/show_bug.cgi?id=1634759
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_process.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index a4b1f97df5..26979faa72 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3247,7 +3247,7 @@ qemuProcessRecoverMigrationIn(virQEMUDriverPtr driver,
+         VIR_DEBUG("Incoming migration finished, resuming domain %s",
+                   vm->def->name);
+         if (qemuProcessStartCPUs(driver, vm,
+-                                 VIR_DOMAIN_RUNNING_UNPAUSED,
++                                 VIR_DOMAIN_RUNNING_MIGRATED,
+                                  QEMU_ASYNC_JOB_NONE) < 0) {
+             VIR_WARN("Could not resume domain %s", vm->def->name);
+         }
+@@ -3354,7 +3354,7 @@ qemuProcessRecoverMigrationOut(virQEMUDriverPtr driver,
+             (reason == VIR_DOMAIN_PAUSED_MIGRATION ||
+              reason == VIR_DOMAIN_PAUSED_UNKNOWN)) {
+             if (qemuProcessStartCPUs(driver, vm,
+-                                     VIR_DOMAIN_RUNNING_UNPAUSED,
++                                     VIR_DOMAIN_RUNNING_MIGRATION_CANCELED,
+                                      QEMU_ASYNC_JOB_NONE) < 0) {
+                 VIR_WARN("Could not resume domain %s", vm->def->name);
+             }
+@@ -3412,7 +3412,7 @@ qemuProcessRecoverJob(virQEMUDriverPtr driver,
+                 reason == VIR_DOMAIN_PAUSED_MIGRATION)) ||
+               reason == VIR_DOMAIN_PAUSED_UNKNOWN)) {
+              if (qemuProcessStartCPUs(driver, vm,
+-                                      VIR_DOMAIN_RUNNING_UNPAUSED,
++                                      VIR_DOMAIN_RUNNING_SAVE_CANCELED,
+                                       QEMU_ASYNC_JOB_NONE) < 0) {
+                  VIR_WARN("Could not resume domain '%s' after migration to file",
+                           vm->def->name);
+-- 
+2.19.1
+
diff --git a/SOURCES/libvirt-virfile-Take-symlink-into-account-in-virFileIsSharedFixFUSE.patch b/SOURCES/libvirt-virfile-Take-symlink-into-account-in-virFileIsSharedFixFUSE.patch
new file mode 100644
index 0000000..5f1d252
--- /dev/null
+++ b/SOURCES/libvirt-virfile-Take-symlink-into-account-in-virFileIsSharedFixFUSE.patch
@@ -0,0 +1,186 @@
+From 703d3a465850b768e627705a587cfd8095fe0be7 Mon Sep 17 00:00:00 2001
+Message-Id: <703d3a465850b768e627705a587cfd8095fe0be7@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 23 Oct 2018 11:40:58 +0100
+Subject: [PATCH] virfile: Take symlink into account in virFileIsSharedFixFUSE
+
+RHEL-7.7: https://bugzilla.redhat.com/show_bug.cgi?id=1640465
+RHEL-7.6.z: https://bugzilla.redhat.com/show_bug.cgi?id=1641798
+
+Weirdly enough, there can be symlinks in the path we are trying
+to fix. If it is the case our clever algorithm that finds matches
+against mount table won't work. Canonicalize path at the
+beginning then.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit c0790e3a09f57da0bd25c7eac4a35ed6e7e9e858)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+---
+ cfg.mk              |  2 +-
+ src/util/virfile.c  | 15 +++++++++++++--
+ tests/virfilemock.c | 33 ++++++++++++++++++++++++++++++++-
+ tests/virfiletest.c |  1 +
+ 4 files changed, 47 insertions(+), 4 deletions(-)
+
+diff --git a/cfg.mk b/cfg.mk
+index 6bebd0ad9f..e3e94bf6f0 100644
+--- a/cfg.mk
++++ b/cfg.mk
+@@ -1216,7 +1216,7 @@ exclude_file_name_regexp--sc_prohibit_select = \
+ 	^cfg\.mk$$
+ 
+ exclude_file_name_regexp--sc_prohibit_canonicalize_file_name = \
+-  ^cfg\.mk$$
++  ^(cfg\.mk|tests/virfilemock\.c)$$
+ 
+ exclude_file_name_regexp--sc_prohibit_raw_allocation = \
+   ^(docs/hacking\.html\.in|src/util/viralloc\.[ch]|examples/.*|tests/(securityselinuxhelper|(vircgroup|nss)mock|commandhelper)\.c|tools/wireshark/src/packet-libvirt\.c)$$
+diff --git a/src/util/virfile.c b/src/util/virfile.c
+index e1dee7633a..716b55d770 100644
+--- a/src/util/virfile.c
++++ b/src/util/virfile.c
+@@ -3549,9 +3549,19 @@ virFileIsSharedFixFUSE(const char *path,
+     char mntbuf[1024];
+     char *mntDir = NULL;
+     char *mntType = NULL;
++    char *canonPath = NULL;
+     size_t maxMatching = 0;
+     int ret = -1;
+ 
++    if (!(canonPath = virFileCanonicalizePath(path))) {
++        virReportSystemError(errno,
++                             _("unable to canonicalize %s"),
++                             path);
++        return -1;
++    }
++
++    VIR_DEBUG("Path canonicalization: %s->%s", path, canonPath);
++
+     if (!(f = setmntent(PROC_MOUNTS, "r"))) {
+         virReportSystemError(errno,
+                              _("Unable to open %s"),
+@@ -3563,7 +3573,7 @@ virFileIsSharedFixFUSE(const char *path,
+         const char *p;
+         size_t len = strlen(mb.mnt_dir);
+ 
+-        if (!(p = STRSKIP(path, mb.mnt_dir)))
++        if (!(p = STRSKIP(canonPath, mb.mnt_dir)))
+             continue;
+ 
+         if (*(p - 1) != '/' && *p != '/' && *p != '\0')
+@@ -3581,12 +3591,13 @@ virFileIsSharedFixFUSE(const char *path,
+ 
+     if (STREQ_NULLABLE(mntType, "fuse.glusterfs")) {
+         VIR_DEBUG("Found gluster FUSE mountpoint=%s for path=%s. "
+-                  "Fixing shared FS type", mntDir, path);
++                  "Fixing shared FS type", mntDir, canonPath);
+         *f_type = GFS2_MAGIC;
+     }
+ 
+     ret = 0;
+  cleanup:
++    VIR_FREE(canonPath);
+     VIR_FREE(mntType);
+     VIR_FREE(mntDir);
+     endmntent(f);
+diff --git a/tests/virfilemock.c b/tests/virfilemock.c
+index 822c757380..ae5c8d025a 100644
+--- a/tests/virfilemock.c
++++ b/tests/virfilemock.c
+@@ -28,11 +28,14 @@
+ #endif
+ 
+ #include "virmock.h"
++#include "virstring.h"
++#include "viralloc.h"
+ 
+ #define VIR_FROM_THIS VIR_FROM_NONE
+ 
+ static FILE *(*real_setmntent)(const char *filename, const char *type);
+ static int (*real_statfs)(const char *path, struct statfs *buf);
++static char *(*real_canonicalize_file_name)(const char *path);
+ 
+ 
+ static void
+@@ -43,6 +46,7 @@ init_syms(void)
+ 
+     VIR_MOCK_REAL_INIT(setmntent);
+     VIR_MOCK_REAL_INIT(statfs);
++    VIR_MOCK_REAL_INIT(canonicalize_file_name);
+ }
+ 
+ 
+@@ -94,6 +98,7 @@ statfs_mock(const char *mtab,
+     FILE *f;
+     struct mntent mb;
+     char mntbuf[1024];
++    char *canonPath = NULL;
+     int ret = -1;
+ 
+     if (!(f = real_setmntent(mtab, "r"))) {
+@@ -101,10 +106,16 @@ statfs_mock(const char *mtab,
+         return -1;
+     }
+ 
++    /* We don't need to do this in callers because real statfs(2)
++     * does that for us. However, in mocked implementation we
++     * need to do this. */
++    if (!(canonPath = canonicalize_file_name(path)))
++        return -1;
++
+     while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) {
+         int ftype;
+ 
+-        if (STRNEQ(mb.mnt_dir, path))
++        if (STRNEQ(mb.mnt_dir, canonPath))
+             continue;
+ 
+         if (STREQ(mb.mnt_type, "nfs") ||
+@@ -136,6 +147,7 @@ statfs_mock(const char *mtab,
+     }
+ 
+     endmntent(f);
++    VIR_FREE(canonPath);
+     return ret;
+ }
+ 
+@@ -152,3 +164,22 @@ statfs(const char *path, struct statfs *buf)
+ 
+     return real_statfs(path, buf);
+ }
++
++
++char *
++canonicalize_file_name(const char *path)
++{
++    if (getenv("LIBVIRT_MTAB")) {
++        const char *p;
++        char *ret;
++
++        if ((p = STRSKIP(path, "/some/symlink")))
++            ignore_value(virAsprintfQuiet(&ret, "/gluster%s", p));
++        else
++            ignore_value(VIR_STRDUP_QUIET(ret, path));
++
++        return ret;
++    }
++
++    return real_canonicalize_file_name(path);
++}
+diff --git a/tests/virfiletest.c b/tests/virfiletest.c
+index be4dbf8910..a246d601ba 100644
+--- a/tests/virfiletest.c
++++ b/tests/virfiletest.c
+@@ -457,6 +457,7 @@ mymain(void)
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/nfs/blah", false);
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/file", true);
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/sshfs/file", false);
++    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/some/symlink/file", true);
+ 
+     return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
+-- 
+2.19.1
+
diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec
index a8843b7..926c37d 100644
--- a/SPECS/libvirt.spec
+++ b/SPECS/libvirt.spec
@@ -253,7 +253,7 @@
 Summary: Library providing a simple virtualization API
 Name: libvirt
 Version: 4.5.0
-Release: 10%{?dist}.2%{?extra_release}
+Release: 10%{?dist}.3%{?extra_release}
 License: LGPLv2+
 URL: https://libvirt.org/
 
@@ -374,6 +374,13 @@ Patch108: libvirt-virfiletest-Fix-test-name-prefix-for-virFileInData-test.patch
 Patch109: libvirt-virfiletst-Test-virFileIsSharedFS.patch
 Patch110: libvirt-virFileIsSharedFSType-Detect-direct-mount-points.patch
 Patch111: libvirt-virfile-Rework-virFileIsSharedFixFUSE.patch
+Patch112: libvirt-virfile-Take-symlink-into-account-in-virFileIsSharedFixFUSE.patch
+Patch113: libvirt-qemu-Properly-report-VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT.patch
+Patch114: libvirt-qemu-Report-more-appropriate-running-reasons.patch
+Patch115: libvirt-qemu-Pass-running-reason-to-RESUME-event-handler.patch
+Patch116: libvirt-qemu-Map-running-reason-to-resume-event-detail.patch
+Patch117: libvirt-qemu-Avoid-duplicate-resume-events-and-state-changes.patch
+Patch118: libvirt-qemu-Don-t-ignore-resume-events.patch
 
 Requires: libvirt-daemon = %{version}-%{release}
 Requires: libvirt-daemon-config-network = %{version}-%{release}
@@ -2273,6 +2280,15 @@ exit 0
 
 
 %changelog
+* Thu Nov  8 2018 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-10.el7_6.3
+- virfile: Take symlink into account in virFileIsSharedFixFUSE (rhbz#1641798)
+- qemu: Properly report VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT (rhbz#1634759)
+- qemu: Report more appropriate running reasons (rhbz#1634759)
+- qemu: Pass running reason to RESUME event handler (rhbz#1634759)
+- qemu: Map running reason to resume event detail (rhbz#1634759)
+- qemu: Avoid duplicate resume events and state changes (rhbz#1634759)
+- qemu: Don't ignore resume events (rhbz#1634759)
+
 * Wed Oct 10 2018 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-10.el7_6.2
 - virfile: fix cast-align error (rhbz#1635705)
 - virfiletest: Fix test name prefix for virFileInData test (rhbz#1635705)