]> xenbits.xensource.com Git - people/liuw/xen.git/commitdiff
libxl_dm: Pre-open QMP socket for QEMU
authorAnthony PERARD <anthony.perard@citrix.com>
Thu, 31 May 2018 13:43:20 +0000 (14:43 +0100)
committerWei Liu <wei.liu2@citrix.com>
Fri, 11 Jan 2019 14:57:52 +0000 (14:57 +0000)
This patch moves the creation of the QMP unix socket from QEMU to libxl.
But libxl doesn't rely on this yet.

When starting QEMU with dm_restrict=1, pre-open the QMP socket before
exec QEMU. That socket will be useful to find out if QEMU is ready, and
pre-opening it means that libxl can connect to it without waiting for
QEMU to create it.

The pre-opening is conditional, based on the use of dm_restrict
because it is using a new command line option of QEMU, and dm_restrict
support in QEMU is newer.

-chardev socket,fd=X is available with QEMU 2.12, since commit:
> char: allow passing pre-opened socket file descriptor at startup
0935700f8544033ebbd41e1f13cd528f8a58d24d

dm_restrict is available in QEMU 3.0.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
tools/libxl/libxl_create.c
tools/libxl/libxl_dm.c
tools/libxl/libxl_internal.h

index 4ca25f56a6da135fbf0fd52a6384d4da46aad90b..89f4766a27752507b335670a0e5de52954955454 100644 (file)
@@ -763,12 +763,17 @@ static int store_libxl_entry(libxl__gc *gc, uint32_t domid,
 
 void libxl__domain_build_state_init(libxl__domain_build_state *state)
 {
+    state->dm_monitor_fd = -1;
 }
 
 void libxl__domain_build_state_dispose(libxl__domain_build_state *state)
 {
     libxl__file_reference_unmap(&state->pv_kernel);
     libxl__file_reference_unmap(&state->pv_ramdisk);
+    if (state->dm_monitor_fd >= 0) {
+        close(state->dm_monitor_fd);
+        state->dm_monitor_fd = -1;
+    }
 }
 
 /*----- main domain creation -----*/
index 200310083fb1948b8212e9f5cf5bfb6331b98b9e..b9921eb885a45592cab990127f33be4ab464e08e 100644 (file)
@@ -670,6 +670,8 @@ static int libxl__build_device_model_args_old(libxl__gc *gc,
     dm_args = flexarray_make(gc, 16, 1);
     dm_envs = flexarray_make(gc, 16, 1);
 
+    assert(state->dm_monitor_fd == -1);
+
     libxl__set_qemu_env_for_xsa_180(gc, dm_envs);
 
     flexarray_vappend(dm_args, dm,
@@ -1100,6 +1102,51 @@ static char *qemu_disk_ide_drive_string(libxl__gc *gc, const char *target_path,
     return drive;
 }
 
+static int libxl__pre_open_qmp_socket(libxl__gc *gc, libxl_domid domid,
+                                      int *fd_r)
+{
+    int rc, r;
+    int fd;
+    struct sockaddr_un un;
+    const char *path = libxl__qemu_qmp_path(gc, domid);
+
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0) {
+        LOGED(ERROR, domid, "socket() failed");
+        return ERROR_FAIL;
+    }
+
+    rc = libxl__prepare_sockaddr_un(gc, &un, path, "QEMU's QMP socket");
+    if (rc)
+        goto out;
+
+    rc = libxl__remove_file(gc, path);
+    if (rc)
+        goto out;
+
+    r = bind(fd, (struct sockaddr *) &un, sizeof(un));
+    if (r < 0) {
+        LOGED(ERROR, domid, "bind('%s') failed", path);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    r = listen(fd, 1);
+    if (r < 0) {
+        LOGED(ERROR, domid, "listen() failed");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    *fd_r = fd;
+    rc = 0;
+
+out:
+    if (rc && fd >= 0)
+        close(fd);
+    return rc;
+}
+
 static int libxl__build_device_model_args_new(libxl__gc *gc,
                                         const char *dm, int guest_domid,
                                         const libxl_domain_config *guest_config,
@@ -1132,10 +1179,16 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
                       GCSPRINTF("%d", guest_domid), NULL);
 
     flexarray_append(dm_args, "-chardev");
-    flexarray_append(dm_args,
-                     GCSPRINTF("socket,id=libxl-cmd,"
-                               "path=%s,server,nowait",
-                               libxl__qemu_qmp_path(gc, guest_domid)));
+    if (state->dm_monitor_fd >= 0) {
+        flexarray_append(dm_args,
+            GCSPRINTF("socket,id=libxl-cmd,fd=%d,server,nowait",
+                      state->dm_monitor_fd));
+    } else {
+        flexarray_append(dm_args,
+                         GCSPRINTF("socket,id=libxl-cmd,"
+                                   "path=%s,server,nowait",
+                                   libxl__qemu_qmp_path(gc, guest_domid)));
+    }
 
     flexarray_append(dm_args, "-no-shutdown");
     flexarray_append(dm_args, "-mon");
@@ -2437,6 +2490,16 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss)
     if (rc)
         goto out;
 
+    if (b_info->device_model_version
+            == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN &&
+        libxl_defbool_val(b_info->dm_restrict)) {
+        /* If we have to use dm_restrict, QEMU needs to be new enough
+         * and will have the new interface where we can pre-open the
+         * QMP socket. */
+        rc = libxl__pre_open_qmp_socket(gc, domid, &state->dm_monitor_fd);
+        if (rc) goto out;
+    }
+
     rc = libxl__build_device_model_args(gc, dm, domid, guest_config,
                                           &args, &envs, state,
                                           &dm_state_fd);
index 3d12748cbbf76ed7c28bda35fc47b9310e92cb3a..b50234482c99f49470b87ccb8dcc6a59d1c059fa 100644 (file)
@@ -1240,6 +1240,7 @@ typedef struct {
     char *console_tty;
 
     char *saved_state;
+    int dm_monitor_fd;
 
     libxl__file_reference pv_kernel;
     libxl__file_reference pv_ramdisk;