yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-virtiofsd-Open-vhost-connection-instead-of-mounting.patch

ddf19c
From a96042f05eaf494fbe26a9cbd940f5f815f782f9 Mon Sep 17 00:00:00 2001
ddf19c
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
ddf19c
Date: Mon, 27 Jan 2020 19:00:56 +0100
ddf19c
Subject: [PATCH 025/116] virtiofsd: Open vhost connection instead of mounting
ddf19c
MIME-Version: 1.0
ddf19c
Content-Type: text/plain; charset=UTF-8
ddf19c
Content-Transfer-Encoding: 8bit
ddf19c
ddf19c
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
ddf19c
Message-id: <20200127190227.40942-22-dgilbert@redhat.com>
ddf19c
Patchwork-id: 93476
ddf19c
O-Subject: [RHEL-AV-8.2 qemu-kvm PATCH 021/112] virtiofsd: Open vhost connection instead of mounting
ddf19c
Bugzilla: 1694164
ddf19c
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
ddf19c
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
ddf19c
ddf19c
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
ddf19c
ddf19c
When run with vhost-user options we conect to the QEMU instead
ddf19c
via a socket.  Start this off by creating the socket.
ddf19c
ddf19c
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
ddf19c
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
ddf19c
Reviewed-by: Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
ddf19c
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
ddf19c
(cherry picked from commit d14bf584dd965821e80d14c16d9292a464b1ab85)
ddf19c
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ddf19c
---
ddf19c
 tools/virtiofsd/fuse_i.h        |  7 ++--
ddf19c
 tools/virtiofsd/fuse_lowlevel.c | 55 ++++------------------------
ddf19c
 tools/virtiofsd/fuse_virtio.c   | 79 +++++++++++++++++++++++++++++++++++++++++
ddf19c
 tools/virtiofsd/fuse_virtio.h   | 23 ++++++++++++
ddf19c
 4 files changed, 114 insertions(+), 50 deletions(-)
ddf19c
 create mode 100644 tools/virtiofsd/fuse_virtio.c
ddf19c
 create mode 100644 tools/virtiofsd/fuse_virtio.h
ddf19c
ddf19c
diff --git a/tools/virtiofsd/fuse_i.h b/tools/virtiofsd/fuse_i.h
ddf19c
index 26b1a7d..82d6ac7 100644
ddf19c
--- a/tools/virtiofsd/fuse_i.h
ddf19c
+++ b/tools/virtiofsd/fuse_i.h
ddf19c
@@ -6,9 +6,10 @@
ddf19c
  * See the file COPYING.LIB
ddf19c
  */
ddf19c
 
ddf19c
-#define FUSE_USE_VERSION 31
ddf19c
-
ddf19c
+#ifndef FUSE_I_H
ddf19c
+#define FUSE_I_H
ddf19c
 
ddf19c
+#define FUSE_USE_VERSION 31
ddf19c
 #include "fuse.h"
ddf19c
 #include "fuse_lowlevel.h"
ddf19c
 
ddf19c
@@ -101,3 +102,5 @@ void fuse_session_process_buf_int(struct fuse_session *se,
ddf19c
 
ddf19c
 /* room needed in buffer to accommodate header */
ddf19c
 #define FUSE_BUFFER_HEADER_SIZE 0x1000
ddf19c
+
ddf19c
+#endif
ddf19c
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
ddf19c
index 17e8718..5df124e 100644
ddf19c
--- a/tools/virtiofsd/fuse_lowlevel.c
ddf19c
+++ b/tools/virtiofsd/fuse_lowlevel.c
ddf19c
@@ -14,6 +14,7 @@
ddf19c
 #include "standard-headers/linux/fuse.h"
ddf19c
 #include "fuse_misc.h"
ddf19c
 #include "fuse_opt.h"
ddf19c
+#include "fuse_virtio.h"
ddf19c
 
ddf19c
 #include <assert.h>
ddf19c
 #include <errno.h>
ddf19c
@@ -2202,6 +2203,11 @@ struct fuse_session *fuse_session_new(struct fuse_args *args,
ddf19c
         goto out4;
ddf19c
     }
ddf19c
 
ddf19c
+    if (!se->vu_socket_path) {
ddf19c
+        fprintf(stderr, "fuse: missing -o vhost_user_socket option\n");
ddf19c
+        goto out4;
ddf19c
+    }
ddf19c
+
ddf19c
     se->bufsize = FUSE_MAX_MAX_PAGES * getpagesize() + FUSE_BUFFER_HEADER_SIZE;
ddf19c
 
ddf19c
     list_init_req(&se->list);
ddf19c
@@ -2224,54 +2230,7 @@ out1:
ddf19c
 
ddf19c
 int fuse_session_mount(struct fuse_session *se)
ddf19c
 {
ddf19c
-    int fd;
ddf19c
-
ddf19c
-    /*
ddf19c
-     * Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
ddf19c
-     * would ensue.
ddf19c
-     */
ddf19c
-    do {
ddf19c
-        fd = open("/dev/null", O_RDWR);
ddf19c
-        if (fd > 2) {
ddf19c
-            close(fd);
ddf19c
-        }
ddf19c
-    } while (fd >= 0 && fd <= 2);
ddf19c
-
ddf19c
-    /*
ddf19c
-     * To allow FUSE daemons to run without privileges, the caller may open
ddf19c
-     * /dev/fuse before launching the file system and pass on the file
ddf19c
-     * descriptor by specifying /dev/fd/N as the mount point. Note that the
ddf19c
-     * parent process takes care of performing the mount in this case.
ddf19c
-     */
ddf19c
-    fd = fuse_mnt_parse_fuse_fd(mountpoint);
ddf19c
-    if (fd != -1) {
ddf19c
-        if (fcntl(fd, F_GETFD) == -1) {
ddf19c
-            fuse_log(FUSE_LOG_ERR, "fuse: Invalid file descriptor /dev/fd/%u\n",
ddf19c
-                     fd);
ddf19c
-            return -1;
ddf19c
-        }
ddf19c
-        se->fd = fd;
ddf19c
-        return 0;
ddf19c
-    }
ddf19c
-
ddf19c
-    /* Open channel */
ddf19c
-    fd = fuse_kern_mount(mountpoint, se->mo);
ddf19c
-    if (fd == -1) {
ddf19c
-        return -1;
ddf19c
-    }
ddf19c
-    se->fd = fd;
ddf19c
-
ddf19c
-    /* Save mountpoint */
ddf19c
-    se->mountpoint = strdup(mountpoint);
ddf19c
-    if (se->mountpoint == NULL) {
ddf19c
-        goto error_out;
ddf19c
-    }
ddf19c
-
ddf19c
-    return 0;
ddf19c
-
ddf19c
-error_out:
ddf19c
-    fuse_kern_unmount(mountpoint, fd);
ddf19c
-    return -1;
ddf19c
+    return virtio_session_mount(se);
ddf19c
 }
ddf19c
 
ddf19c
 int fuse_session_fd(struct fuse_session *se)
ddf19c
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
ddf19c
new file mode 100644
ddf19c
index 0000000..cbef6ff
ddf19c
--- /dev/null
ddf19c
+++ b/tools/virtiofsd/fuse_virtio.c
ddf19c
@@ -0,0 +1,79 @@
ddf19c
+/*
ddf19c
+ * virtio-fs glue for FUSE
ddf19c
+ * Copyright (C) 2018 Red Hat, Inc. and/or its affiliates
ddf19c
+ *
ddf19c
+ * Authors:
ddf19c
+ *   Dave Gilbert  <dgilbert@redhat.com>
ddf19c
+ *
ddf19c
+ * Implements the glue between libfuse and libvhost-user
ddf19c
+ *
ddf19c
+ * This program can be distributed under the terms of the GNU LGPLv2.
ddf19c
+ * See the file COPYING.LIB
ddf19c
+ */
ddf19c
+
ddf19c
+#include "fuse_i.h"
ddf19c
+#include "standard-headers/linux/fuse.h"
ddf19c
+#include "fuse_misc.h"
ddf19c
+#include "fuse_opt.h"
ddf19c
+#include "fuse_virtio.h"
ddf19c
+
ddf19c
+#include <stdint.h>
ddf19c
+#include <stdio.h>
ddf19c
+#include <string.h>
ddf19c
+#include <sys/socket.h>
ddf19c
+#include <sys/types.h>
ddf19c
+#include <sys/un.h>
ddf19c
+#include <unistd.h>
ddf19c
+
ddf19c
+/* From spec */
ddf19c
+struct virtio_fs_config {
ddf19c
+    char tag[36];
ddf19c
+    uint32_t num_queues;
ddf19c
+};
ddf19c
+
ddf19c
+int virtio_session_mount(struct fuse_session *se)
ddf19c
+{
ddf19c
+    struct sockaddr_un un;
ddf19c
+    mode_t old_umask;
ddf19c
+
ddf19c
+    if (strlen(se->vu_socket_path) >= sizeof(un.sun_path)) {
ddf19c
+        fuse_log(FUSE_LOG_ERR, "Socket path too long\n");
ddf19c
+        return -1;
ddf19c
+    }
ddf19c
+
ddf19c
+    se->fd = -1;
ddf19c
+
ddf19c
+    /*
ddf19c
+     * Create the Unix socket to communicate with qemu
ddf19c
+     * based on QEMU's vhost-user-bridge
ddf19c
+     */
ddf19c
+    unlink(se->vu_socket_path);
ddf19c
+    strcpy(un.sun_path, se->vu_socket_path);
ddf19c
+    size_t addr_len = sizeof(un);
ddf19c
+
ddf19c
+    int listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
ddf19c
+    if (listen_sock == -1) {
ddf19c
+        fuse_log(FUSE_LOG_ERR, "vhost socket creation: %m\n");
ddf19c
+        return -1;
ddf19c
+    }
ddf19c
+    un.sun_family = AF_UNIX;
ddf19c
+
ddf19c
+    /*
ddf19c
+     * Unfortunately bind doesn't let you set the mask on the socket,
ddf19c
+     * so set umask to 077 and restore it later.
ddf19c
+     */
ddf19c
+    old_umask = umask(0077);
ddf19c
+    if (bind(listen_sock, (struct sockaddr *)&un, addr_len) == -1) {
ddf19c
+        fuse_log(FUSE_LOG_ERR, "vhost socket bind: %m\n");
ddf19c
+        umask(old_umask);
ddf19c
+        return -1;
ddf19c
+    }
ddf19c
+    umask(old_umask);
ddf19c
+
ddf19c
+    if (listen(listen_sock, 1) == -1) {
ddf19c
+        fuse_log(FUSE_LOG_ERR, "vhost socket listen: %m\n");
ddf19c
+        return -1;
ddf19c
+    }
ddf19c
+
ddf19c
+    return -1;
ddf19c
+}
ddf19c
diff --git a/tools/virtiofsd/fuse_virtio.h b/tools/virtiofsd/fuse_virtio.h
ddf19c
new file mode 100644
ddf19c
index 0000000..8f2edb6
ddf19c
--- /dev/null
ddf19c
+++ b/tools/virtiofsd/fuse_virtio.h
ddf19c
@@ -0,0 +1,23 @@
ddf19c
+/*
ddf19c
+ * virtio-fs glue for FUSE
ddf19c
+ * Copyright (C) 2018 Red Hat, Inc. and/or its affiliates
ddf19c
+ *
ddf19c
+ * Authors:
ddf19c
+ *   Dave Gilbert  <dgilbert@redhat.com>
ddf19c
+ *
ddf19c
+ * Implements the glue between libfuse and libvhost-user
ddf19c
+ *
ddf19c
+ * This program can be distributed under the terms of the GNU LGPLv2.
ddf19c
+ *  See the file COPYING.LIB
ddf19c
+ */
ddf19c
+
ddf19c
+#ifndef FUSE_VIRTIO_H
ddf19c
+#define FUSE_VIRTIO_H
ddf19c
+
ddf19c
+#include "fuse_i.h"
ddf19c
+
ddf19c
+struct fuse_session;
ddf19c
+
ddf19c
+int virtio_session_mount(struct fuse_session *se);
ddf19c
+
ddf19c
+#endif
ddf19c
-- 
ddf19c
1.8.3.1
ddf19c