summary refs log tree commit diff stats
path: root/tools/virtiofsd/fuse_signals.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-01-24 09:59:11 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-01-24 09:59:11 +0000
commita43efa34c7d7b628cbf1ec0fe60043e5c91043ea (patch)
tree244116ae14402ea336fd32de0d4c07fa5409eb09 /tools/virtiofsd/fuse_signals.c
parentc0248b36d8d190933a43919b9f71013a255e866c (diff)
parent1d59b1b210d7c3b0bdf4b10ebe0bb1fccfcb8b95 (diff)
downloadfocaccia-qemu-a43efa34c7d7b628cbf1ec0fe60043e5c91043ea.tar.gz
focaccia-qemu-a43efa34c7d7b628cbf1ec0fe60043e5c91043ea.zip
Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-virtiofs-20200123b' into staging
virtiofsd first pull v2

Import our virtiofsd.
This pulls in the daemon to drive a file system connected to the
existing qemu virtiofsd device.
It's derived from upstream libfuse with lots of changes (and a lot
trimmed out).
The daemon lives in the newly created qemu/tools/virtiofsd

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

v2
  drop the docs while we discuss where they should live
  and we need to redo the manpage in anything but texi

# gpg: Signature made Thu 23 Jan 2020 16:45:18 GMT
# gpg:                using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert-gitlab/tags/pull-virtiofs-20200123b: (108 commits)
  virtiofsd: add some options to the help message
  virtiofsd: stop all queue threads on exit in virtio_loop()
  virtiofsd/passthrough_ll: Pass errno to fuse_reply_err()
  virtiofsd: Convert lo_destroy to take the lo->mutex lock itself
  virtiofsd: add --thread-pool-size=NUM option
  virtiofsd: fix lo_destroy() resource leaks
  virtiofsd: prevent FUSE_INIT/FUSE_DESTROY races
  virtiofsd: process requests in a thread pool
  virtiofsd: use fuse_buf_writev to replace fuse_buf_write for better performance
  virtiofsd: add definition of fuse_buf_writev()
  virtiofsd: passthrough_ll: Use cache_readdir for directory open
  virtiofsd: Fix data corruption with O_APPEND write in writeback mode
  virtiofsd: Reset O_DIRECT flag during file open
  virtiofsd: convert more fprintf and perror to use fuse log infra
  virtiofsd: do not always set FUSE_FLOCK_LOCKS
  virtiofsd: introduce inode refcount to prevent use-after-free
  virtiofsd: passthrough_ll: fix refcounting on remove/rename
  libvhost-user: Fix some memtable remap cases
  virtiofsd: rename inode->refcount to inode->nlookup
  virtiofsd: prevent races with lo_dirp_put()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tools/virtiofsd/fuse_signals.c')
-rw-r--r--tools/virtiofsd/fuse_signals.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/tools/virtiofsd/fuse_signals.c b/tools/virtiofsd/fuse_signals.c
new file mode 100644
index 0000000000..f18625b6e2
--- /dev/null
+++ b/tools/virtiofsd/fuse_signals.c
@@ -0,0 +1,98 @@
+/*
+ * FUSE: Filesystem in Userspace
+ * Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
+ *
+ * Utility functions for setting signal handlers.
+ *
+ * This program can be distributed under the terms of the GNU LGPLv2.
+ * See the file COPYING.LIB
+ */
+
+#include "qemu/osdep.h"
+#include "fuse_i.h"
+#include "fuse_lowlevel.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct fuse_session *fuse_instance;
+
+static void exit_handler(int sig)
+{
+    if (fuse_instance) {
+        fuse_session_exit(fuse_instance);
+        if (sig <= 0) {
+            fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
+            abort();
+        }
+        fuse_instance->error = sig;
+    }
+}
+
+static void do_nothing(int sig)
+{
+    (void)sig;
+}
+
+static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
+{
+    struct sigaction sa;
+    struct sigaction old_sa;
+
+    memset(&sa, 0, sizeof(struct sigaction));
+    sa.sa_handler = remove ? SIG_DFL : handler;
+    sigemptyset(&(sa.sa_mask));
+    sa.sa_flags = 0;
+
+    if (sigaction(sig, NULL, &old_sa) == -1) {
+        fuse_log(FUSE_LOG_ERR, "fuse: cannot get old signal handler: %s\n",
+                 strerror(errno));
+        return -1;
+    }
+
+    if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
+        sigaction(sig, &sa, NULL) == -1) {
+        fuse_log(FUSE_LOG_ERR, "fuse: cannot set signal handler: %s\n",
+                 strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+int fuse_set_signal_handlers(struct fuse_session *se)
+{
+    /*
+     * If we used SIG_IGN instead of the do_nothing function,
+     * then we would be unable to tell if we set SIG_IGN (and
+     * thus should reset to SIG_DFL in fuse_remove_signal_handlers)
+     * or if it was already set to SIG_IGN (and should be left
+     * untouched.
+     */
+    if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
+        set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
+        set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
+        set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1) {
+        return -1;
+    }
+
+    fuse_instance = se;
+    return 0;
+}
+
+void fuse_remove_signal_handlers(struct fuse_session *se)
+{
+    if (fuse_instance != se) {
+        fuse_log(FUSE_LOG_ERR,
+                 "fuse: fuse_remove_signal_handlers: unknown session\n");
+    } else {
+        fuse_instance = NULL;
+    }
+
+    set_one_signal_handler(SIGHUP, exit_handler, 1);
+    set_one_signal_handler(SIGINT, exit_handler, 1);
+    set_one_signal_handler(SIGTERM, exit_handler, 1);
+    set_one_signal_handler(SIGPIPE, do_nothing, 1);
+}