]> xenbits.xensource.com Git - xen.git/commitdiff
tools/xenstore: handle dying domains in live update
authorJulien Grall <jgrall@amazon.com>
Wed, 13 Jan 2021 13:00:21 +0000 (14:00 +0100)
committerJuergen Gross <jgross@suse.com>
Thu, 21 Jan 2021 16:31:52 +0000 (17:31 +0100)
A domain could just be dying when live updating Xenstore, so the case
of not being able to map the ring page or to connect to the event
channel must be handled gracefully.

Signed-off-by: Julien Grall <jgrall@amazon.com>
Reviewed-by: Paul Durrant <paul@xen.org>
Acked-by: Wei Liu <wl@xen.org>
tools/xenstore/xenstored_control.c
tools/xenstore/xenstored_domain.c
tools/xenstore/xenstored_domain.h

index b8195eed4133ac1460a7f51539eb02c3137f2c40..3c212cc4d4baf64d94846438fda1e151b9da69e2 100644 (file)
@@ -561,6 +561,13 @@ void lu_read_state(void)
        lu_close_dump_state(&state);
 
        talloc_free(ctx);
+
+       /*
+        * We may have missed the VIRQ_DOM_EXC notification and a domain may
+        * have died while we were live-updating. So check all the domains are
+        * still alive.
+        */
+       check_domains(true);
 }
 
 static const char *lu_activate_binary(const void *ctx)
index 6934f1bc89cab5d77276405f2a92d35d4943d040..cbeb2a309c8f663fe6c4043f4752d89bbe42366d 100644 (file)
@@ -220,7 +220,7 @@ static bool get_domain_info(unsigned int domid, xc_dominfo_t *dominfo)
               dominfo->domid == domid;
 }
 
-static void domain_cleanup(void)
+void check_domains(bool restore)
 {
        xc_dominfo_t dominfo;
        struct domain *domain;
@@ -244,7 +244,14 @@ static void domain_cleanup(void)
                                domain->shutdown = true;
                                notify = 1;
                        }
-                       if (!dominfo.dying)
+                       /*
+                        * On Restore, we may have been unable to remap the
+                        * interface and the port. As we don't know whether
+                        * this was because of a dying domain, we need to
+                        * check if the interface and port are still valid.
+                        */
+                       if (!dominfo.dying && domain->port &&
+                           domain->interface)
                                continue;
                }
                if (domain->conn) {
@@ -270,7 +277,7 @@ void handle_event(void)
                barf_perror("Failed to read from event fd");
 
        if (port == virq_port)
-               domain_cleanup();
+               check_domains(false);
 
        if (xenevtchn_unmask(xce_handle, port) == -1)
                barf_perror("Failed to write to event fd");
@@ -442,14 +449,16 @@ static struct domain *introduce_domain(const void *ctx,
        if (!domain->introduced) {
                interface = is_master_domain ? xenbus_map()
                                             : map_interface(domid);
-               if (!interface)
+               if (!interface && !restore)
                        return NULL;
                if (new_domain(domain, port, restore)) {
                        rc = errno;
-                       if (is_master_domain)
-                               unmap_xenbus(interface);
-                       else
-                               unmap_interface(interface);
+                       if (interface) {
+                               if (is_master_domain)
+                                       unmap_xenbus(interface);
+                               else
+                                       unmap_interface(interface);
+                       }
                        errno = rc;
                        return NULL;
                }
index 8f3b4e0f8ba0621ff76416be672d5abed21a6976..1cc1c03ed893f99e50d7fdf93884d4b2c528a6b4 100644 (file)
@@ -21,6 +21,8 @@
 
 void handle_event(void);
 
+void check_domains(bool restore);
+
 /* domid, mfn, eventchn, path */
 int do_introduce(struct connection *conn, struct buffered_data *in);