[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 30/31] libxl_dm: Pre-open QMP socket for QEMU



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

The pre-openning is conditionnal, 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 will be available in QEMU 3.0.

Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---

Notes:
    We may want to set cloexec on the socket up to the forking point. Because if
    the socket stay open in a random process, libxl will not detected right 
away if
    QEMU as failed to start.  On the other hand, we can rely on timeouts.

 tools/libxl/libxl_dm.c | 73 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 64 insertions(+), 9 deletions(-)

diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 18ada69e8b..10b35d822a 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -24,6 +24,8 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 static const char *libxl_tapif_script(libxl__gc *gc)
 {
@@ -913,7 +915,7 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
                                         const libxl_domain_config 
*guest_config,
                                         char ***args, char ***envs,
                                         const libxl__domain_build_state *state,
-                                        int *dm_state_fd)
+                                        int *dm_state_fd, int *dm_monitor_fd)
 {
     const libxl_domain_create_info *c_info = &guest_config->c_info;
     const libxl_domain_build_info *b_info = &guest_config->b_info;
@@ -942,10 +944,58 @@ 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/qmp-libxl-%d,server,nowait",
-                                    libxl__run_dir_path(), guest_domid));
+    /* If we have to use dm_restrict, QEMU need to be new enough and will have
+     * the new interface where we can pre-open the QMP socket. */
+    if (libxl_defbool_val(b_info->dm_restrict))
+    {
+        int socket_fd = -1;
+        struct sockaddr_un un;
+        const char *socket_path;
+
+        socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+        *dm_monitor_fd = socket_fd;
+        if (socket_fd < 0) {
+            LOGED(ERROR, guest_domid, "Failed to create UNIX socket");
+            return ERROR_FAIL;
+        }
+
+        socket_path = GCSPRINTF("%s/qmp-libxl-%d",
+                                libxl__run_dir_path(), guest_domid);
+        if (strlen(socket_path) > sizeof(un.sun_path)) {
+            LOGD(ERROR, guest_domid, "UNIX socket path '%s' is too long",
+                 socket_path);
+            LOGD(DEBUG, guest_domid, "Path must be less than %zu bytes",
+                 sizeof(un.sun_path));
+            return ERROR_FAIL;
+        }
+
+        if (unlink(socket_path) < 0 && errno != ENOENT) {
+            LOGED(ERROR, guest_domid, "Failed to unlink socket %s", 
socket_path);
+            return ERROR_FAIL;
+        }
+
+        memset(&un, 0, sizeof(un));
+        un.sun_family = AF_UNIX;
+        strncpy(un.sun_path, socket_path, sizeof(un.sun_path));
+        if (bind(socket_fd, (struct sockaddr*) &un, sizeof(un)) < 0) {
+            LOGED(ERROR, guest_domid, "Failed to bind socket to %s", 
socket_path);
+            return ERROR_FAIL;
+        }
+
+        if (listen(socket_fd, 1) < 0) {
+            LOGED(ERROR, guest_domid, "Failed to listen on socket");
+            return ERROR_FAIL;
+        }
+
+        flexarray_append(dm_args,
+                         GCSPRINTF("socket,id=libxl-cmd,fd=%d,server,nowait",
+                                   socket_fd));
+    } else {
+        flexarray_append(dm_args,
+                         GCSPRINTF("socket,id=libxl-cmd,"
+                                   "path=%s/qmp-libxl-%d,server,nowait",
+                                   libxl__run_dir_path(), guest_domid));
+    }
 
     flexarray_append(dm_args, "-no-shutdown");
     flexarray_append(dm_args, "-mon");
@@ -1722,7 +1772,8 @@ static int libxl__build_device_model_args(libxl__gc *gc,
                                         const libxl_domain_config 
*guest_config,
                                         char ***args, char ***envs,
                                         const libxl__domain_build_state *state,
-                                        int *dm_state_fd)
+                                        int *dm_state_fd,
+                                        int *dm_monitor_fd)
 /* dm_state_fd may be NULL iff caller knows we are using old stubdom
  * and therefore will be passing a filename rather than a fd. */
 {
@@ -1735,10 +1786,11 @@ static int libxl__build_device_model_args(libxl__gc *gc,
     case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
         assert(dm_state_fd != NULL);
         assert(*dm_state_fd < 0);
+        assert(dm_monitor_fd != NULL);
         return libxl__build_device_model_args_new(gc, dm,
                                                   guest_domid, guest_config,
                                                   args, envs,
-                                                  state, dm_state_fd);
+                                                  state, dm_state_fd, 
dm_monitor_fd);
     default:
         LOGED(ERROR, guest_domid, "unknown device model version %d",
               guest_config->b_info.device_model_version);
@@ -1958,7 +2010,7 @@ void libxl__spawn_stub_dm(libxl__egc *egc, 
libxl__stub_dm_spawn_state *sdss)
 
     ret = libxl__build_device_model_args(gc, "stubdom-dm", guest_domid,
                                          guest_config, &args, NULL,
-                                         d_state, NULL);
+                                         d_state, NULL, NULL);
     if (ret) {
         ret = ERROR_FAIL;
         goto out;
@@ -2244,6 +2296,7 @@ void libxl__spawn_local_dm(libxl__egc *egc, 
libxl__dm_spawn_state *dmss)
     char **pass_stuff;
     const char *dm;
     int dm_state_fd = -1;
+    int dm_monitor_fd = -1;
 
     if (libxl_defbool_val(b_info->device_model_stubdomain)) {
         abort();
@@ -2261,7 +2314,8 @@ void libxl__spawn_local_dm(libxl__egc *egc, 
libxl__dm_spawn_state *dmss)
     }
     rc = libxl__build_device_model_args(gc, dm, domid, guest_config,
                                           &args, &envs, state,
-                                          &dm_state_fd);
+                                          &dm_state_fd,
+                                          &dm_monitor_fd);
     if (rc)
         goto out;
 
@@ -2359,6 +2413,7 @@ out_close:
     if (logfile_w >= 0) close(logfile_w);
 out:
     if (dm_state_fd >= 0) close(dm_state_fd);
+    if (dm_monitor_fd >= 0) close(dm_monitor_fd);
     if (rc)
         device_model_spawn_outcome(egc, dmss, rc);
 }
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.