All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com>
To: qemu-devel@nongnu.org, stefanha@redhat.com
Subject: [PULL 003/108] virtiofsd: Add auxiliary .c's
Date: Thu, 23 Jan 2020 16:44:45 +0000	[thread overview]
Message-ID: <20200123164630.91498-4-dgilbert@redhat.com> (raw)
In-Reply-To: <20200123164630.91498-1-dgilbert@redhat.com>

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Add most of the non-main .c files we need from upstream fuse-3.8.0

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 tools/virtiofsd/buffer.c       | 321 ++++++++++++++++++++++++
 tools/virtiofsd/fuse_log.c     |  40 +++
 tools/virtiofsd/fuse_opt.c     | 423 +++++++++++++++++++++++++++++++
 tools/virtiofsd/fuse_signals.c |  91 +++++++
 tools/virtiofsd/helper.c       | 440 +++++++++++++++++++++++++++++++++
 5 files changed, 1315 insertions(+)
 create mode 100644 tools/virtiofsd/buffer.c
 create mode 100644 tools/virtiofsd/fuse_log.c
 create mode 100644 tools/virtiofsd/fuse_opt.c
 create mode 100644 tools/virtiofsd/fuse_signals.c
 create mode 100644 tools/virtiofsd/helper.c

diff --git a/tools/virtiofsd/buffer.c b/tools/virtiofsd/buffer.c
new file mode 100644
index 0000000000..5ab9b87455
--- /dev/null
+++ b/tools/virtiofsd/buffer.c
@@ -0,0 +1,321 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2010  Miklos Szeredi <miklos@szeredi.hu>
+
+  Functions for dealing with `struct fuse_buf` and `struct
+  fuse_bufvec`.
+
+  This program can be distributed under the terms of the GNU LGPLv2.
+  See the file COPYING.LIB
+*/
+
+#define _GNU_SOURCE
+
+#include "config.h"
+#include "fuse_i.h"
+#include "fuse_lowlevel.h"
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+
+size_t fuse_buf_size(const struct fuse_bufvec *bufv)
+{
+	size_t i;
+	size_t size = 0;
+
+	for (i = 0; i < bufv->count; i++) {
+		if (bufv->buf[i].size == SIZE_MAX)
+			size = SIZE_MAX;
+		else
+			size += bufv->buf[i].size;
+	}
+
+	return size;
+}
+
+static size_t min_size(size_t s1, size_t s2)
+{
+	return s1 < s2 ? s1 : s2;
+}
+
+static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off,
+			      const struct fuse_buf *src, size_t src_off,
+			      size_t len)
+{
+	ssize_t res = 0;
+	size_t copied = 0;
+
+	while (len) {
+		if (dst->flags & FUSE_BUF_FD_SEEK) {
+			res = pwrite(dst->fd, (char *)src->mem + src_off, len,
+				     dst->pos + dst_off);
+		} else {
+			res = write(dst->fd, (char *)src->mem + src_off, len);
+		}
+		if (res == -1) {
+			if (!copied)
+				return -errno;
+			break;
+		}
+		if (res == 0)
+			break;
+
+		copied += res;
+		if (!(dst->flags & FUSE_BUF_FD_RETRY))
+			break;
+
+		src_off += res;
+		dst_off += res;
+		len -= res;
+	}
+
+	return copied;
+}
+
+static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off,
+			     const struct fuse_buf *src, size_t src_off,
+			     size_t len)
+{
+	ssize_t res = 0;
+	size_t copied = 0;
+
+	while (len) {
+		if (src->flags & FUSE_BUF_FD_SEEK) {
+			res = pread(src->fd, (char *)dst->mem + dst_off, len,
+				     src->pos + src_off);
+		} else {
+			res = read(src->fd, (char *)dst->mem + dst_off, len);
+		}
+		if (res == -1) {
+			if (!copied)
+				return -errno;
+			break;
+		}
+		if (res == 0)
+			break;
+
+		copied += res;
+		if (!(src->flags & FUSE_BUF_FD_RETRY))
+			break;
+
+		dst_off += res;
+		src_off += res;
+		len -= res;
+	}
+
+	return copied;
+}
+
+static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off,
+				 const struct fuse_buf *src, size_t src_off,
+				 size_t len)
+{
+	char buf[4096];
+	struct fuse_buf tmp = {
+		.size = sizeof(buf),
+		.flags = 0,
+	};
+	ssize_t res;
+	size_t copied = 0;
+
+	tmp.mem = buf;
+
+	while (len) {
+		size_t this_len = min_size(tmp.size, len);
+		size_t read_len;
+
+		res = fuse_buf_read(&tmp, 0, src, src_off, this_len);
+		if (res < 0) {
+			if (!copied)
+				return res;
+			break;
+		}
+		if (res == 0)
+			break;
+
+		read_len = res;
+		res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len);
+		if (res < 0) {
+			if (!copied)
+				return res;
+			break;
+		}
+		if (res == 0)
+			break;
+
+		copied += res;
+
+		if (res < this_len)
+			break;
+
+		dst_off += res;
+		src_off += res;
+		len -= res;
+	}
+
+	return copied;
+}
+
+#ifdef HAVE_SPLICE
+static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off,
+			       const struct fuse_buf *src, size_t src_off,
+			       size_t len, enum fuse_buf_copy_flags flags)
+{
+	int splice_flags = 0;
+	off_t *srcpos = NULL;
+	off_t *dstpos = NULL;
+	off_t srcpos_val;
+	off_t dstpos_val;
+	ssize_t res;
+	size_t copied = 0;
+
+	if (flags & FUSE_BUF_SPLICE_MOVE)
+		splice_flags |= SPLICE_F_MOVE;
+	if (flags & FUSE_BUF_SPLICE_NONBLOCK)
+		splice_flags |= SPLICE_F_NONBLOCK;
+
+	if (src->flags & FUSE_BUF_FD_SEEK) {
+		srcpos_val = src->pos + src_off;
+		srcpos = &srcpos_val;
+	}
+	if (dst->flags & FUSE_BUF_FD_SEEK) {
+		dstpos_val = dst->pos + dst_off;
+		dstpos = &dstpos_val;
+	}
+
+	while (len) {
+		res = splice(src->fd, srcpos, dst->fd, dstpos, len,
+			     splice_flags);
+		if (res == -1) {
+			if (copied)
+				break;
+
+			if (errno != EINVAL || (flags & FUSE_BUF_FORCE_SPLICE))
+				return -errno;
+
+			/* Maybe splice is not supported for this combination */
+			return fuse_buf_fd_to_fd(dst, dst_off, src, src_off,
+						 len);
+		}
+		if (res == 0)
+			break;
+
+		copied += res;
+		if (!(src->flags & FUSE_BUF_FD_RETRY) &&
+		    !(dst->flags & FUSE_BUF_FD_RETRY)) {
+			break;
+		}
+
+		len -= res;
+	}
+
+	return copied;
+}
+#else
+static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off,
+			       const struct fuse_buf *src, size_t src_off,
+			       size_t len, enum fuse_buf_copy_flags flags)
+{
+	(void) flags;
+
+	return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
+}
+#endif
+
+
+static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off,
+				 const struct fuse_buf *src, size_t src_off,
+				 size_t len, enum fuse_buf_copy_flags flags)
+{
+	int src_is_fd = src->flags & FUSE_BUF_IS_FD;
+	int dst_is_fd = dst->flags & FUSE_BUF_IS_FD;
+
+	if (!src_is_fd && !dst_is_fd) {
+		char *dstmem = (char *)dst->mem + dst_off;
+		char *srcmem = (char *)src->mem + src_off;
+
+		if (dstmem != srcmem) {
+			if (dstmem + len <= srcmem || srcmem + len <= dstmem)
+				memcpy(dstmem, srcmem, len);
+			else
+				memmove(dstmem, srcmem, len);
+		}
+
+		return len;
+	} else if (!src_is_fd) {
+		return fuse_buf_write(dst, dst_off, src, src_off, len);
+	} else if (!dst_is_fd) {
+		return fuse_buf_read(dst, dst_off, src, src_off, len);
+	} else if (flags & FUSE_BUF_NO_SPLICE) {
+		return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
+	} else {
+		return fuse_buf_splice(dst, dst_off, src, src_off, len, flags);
+	}
+}
+
+static const struct fuse_buf *fuse_bufvec_current(struct fuse_bufvec *bufv)
+{
+	if (bufv->idx < bufv->count)
+		return &bufv->buf[bufv->idx];
+	else
+		return NULL;
+}
+
+static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len)
+{
+	const struct fuse_buf *buf = fuse_bufvec_current(bufv);
+
+	bufv->off += len;
+	assert(bufv->off <= buf->size);
+	if (bufv->off == buf->size) {
+		assert(bufv->idx < bufv->count);
+		bufv->idx++;
+		if (bufv->idx == bufv->count)
+			return 0;
+		bufv->off = 0;
+	}
+	return 1;
+}
+
+ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv,
+		      enum fuse_buf_copy_flags flags)
+{
+	size_t copied = 0;
+
+	if (dstv == srcv)
+		return fuse_buf_size(dstv);
+
+	for (;;) {
+		const struct fuse_buf *src = fuse_bufvec_current(srcv);
+		const struct fuse_buf *dst = fuse_bufvec_current(dstv);
+		size_t src_len;
+		size_t dst_len;
+		size_t len;
+		ssize_t res;
+
+		if (src == NULL || dst == NULL)
+			break;
+
+		src_len = src->size - srcv->off;
+		dst_len = dst->size - dstv->off;
+		len = min_size(src_len, dst_len);
+
+		res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags);
+		if (res < 0) {
+			if (!copied)
+				return res;
+			break;
+		}
+		copied += res;
+
+		if (!fuse_bufvec_advance(srcv, res) ||
+		    !fuse_bufvec_advance(dstv, res))
+			break;
+
+		if (res < len)
+			break;
+	}
+
+	return copied;
+}
diff --git a/tools/virtiofsd/fuse_log.c b/tools/virtiofsd/fuse_log.c
new file mode 100644
index 0000000000..0d268ab014
--- /dev/null
+++ b/tools/virtiofsd/fuse_log.c
@@ -0,0 +1,40 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2019  Red Hat, Inc.
+
+  Logging API.
+
+  This program can be distributed under the terms of the GNU LGPLv2.
+  See the file COPYING.LIB
+*/
+
+#include "fuse_log.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+static void default_log_func(
+		__attribute__(( unused )) enum fuse_log_level level,
+		const char *fmt, va_list ap)
+{
+	vfprintf(stderr, fmt, ap);
+}
+
+static fuse_log_func_t log_func = default_log_func;
+
+void fuse_set_log_func(fuse_log_func_t func)
+{
+	if (!func)
+		func = default_log_func;
+
+	log_func = func;
+}
+
+void fuse_log(enum fuse_log_level level, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	log_func(level, fmt, ap);
+	va_end(ap);
+}
diff --git a/tools/virtiofsd/fuse_opt.c b/tools/virtiofsd/fuse_opt.c
new file mode 100644
index 0000000000..93066b926e
--- /dev/null
+++ b/tools/virtiofsd/fuse_opt.c
@@ -0,0 +1,423 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
+
+  Implementation of option parsing routines (dealing with `struct
+  fuse_args`).
+
+  This program can be distributed under the terms of the GNU LGPLv2.
+  See the file COPYING.LIB
+*/
+
+#include "config.h"
+#include "fuse_i.h"
+#include "fuse_opt.h"
+#include "fuse_misc.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+struct fuse_opt_context {
+	void *data;
+	const struct fuse_opt *opt;
+	fuse_opt_proc_t proc;
+	int argctr;
+	int argc;
+	char **argv;
+	struct fuse_args outargs;
+	char *opts;
+	int nonopt;
+};
+
+void fuse_opt_free_args(struct fuse_args *args)
+{
+	if (args) {
+		if (args->argv && args->allocated) {
+			int i;
+			for (i = 0; i < args->argc; i++)
+				free(args->argv[i]);
+			free(args->argv);
+		}
+		args->argc = 0;
+		args->argv = NULL;
+		args->allocated = 0;
+	}
+}
+
+static int alloc_failed(void)
+{
+	fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
+	return -1;
+}
+
+int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
+{
+	char **newargv;
+	char *newarg;
+
+	assert(!args->argv || args->allocated);
+
+	newarg = strdup(arg);
+	if (!newarg)
+		return alloc_failed();
+
+	newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
+	if (!newargv) {
+		free(newarg);
+		return alloc_failed();
+	}
+
+	args->argv = newargv;
+	args->allocated = 1;
+	args->argv[args->argc++] = newarg;
+	args->argv[args->argc] = NULL;
+	return 0;
+}
+
+static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos,
+				      const char *arg)
+{
+	assert(pos <= args->argc);
+	if (fuse_opt_add_arg(args, arg) == -1)
+		return -1;
+
+	if (pos != args->argc - 1) {
+		char *newarg = args->argv[args->argc - 1];
+		memmove(&args->argv[pos + 1], &args->argv[pos],
+			sizeof(char *) * (args->argc - pos - 1));
+		args->argv[pos] = newarg;
+	}
+	return 0;
+}
+
+int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
+{
+	return fuse_opt_insert_arg_common(args, pos, arg);
+}
+
+static int next_arg(struct fuse_opt_context *ctx, const char *opt)
+{
+	if (ctx->argctr + 1 >= ctx->argc) {
+		fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt);
+		return -1;
+	}
+	ctx->argctr++;
+	return 0;
+}
+
+static int add_arg(struct fuse_opt_context *ctx, const char *arg)
+{
+	return fuse_opt_add_arg(&ctx->outargs, arg);
+}
+
+static int add_opt_common(char **opts, const char *opt, int esc)
+{
+	unsigned oldlen = *opts ? strlen(*opts) : 0;
+	char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
+
+	if (!d)
+		return alloc_failed();
+
+	*opts = d;
+	if (oldlen) {
+		d += oldlen;
+		*d++ = ',';
+	}
+
+	for (; *opt; opt++) {
+		if (esc && (*opt == ',' || *opt == '\\'))
+			*d++ = '\\';
+		*d++ = *opt;
+	}
+	*d = '\0';
+
+	return 0;
+}
+
+int fuse_opt_add_opt(char **opts, const char *opt)
+{
+	return add_opt_common(opts, opt, 0);
+}
+
+int fuse_opt_add_opt_escaped(char **opts, const char *opt)
+{
+	return add_opt_common(opts, opt, 1);
+}
+
+static int add_opt(struct fuse_opt_context *ctx, const char *opt)
+{
+	return add_opt_common(&ctx->opts, opt, 1);
+}
+
+static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key,
+		     int iso)
+{
+	if (key == FUSE_OPT_KEY_DISCARD)
+		return 0;
+
+	if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
+		int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
+		if (res == -1 || !res)
+			return res;
+	}
+	if (iso)
+		return add_opt(ctx, arg);
+	else
+		return add_arg(ctx, arg);
+}
+
+static int match_template(const char *t, const char *arg, unsigned *sepp)
+{
+	int arglen = strlen(arg);
+	const char *sep = strchr(t, '=');
+	sep = sep ? sep : strchr(t, ' ');
+	if (sep && (!sep[1] || sep[1] == '%')) {
+		int tlen = sep - t;
+		if (sep[0] == '=')
+			tlen ++;
+		if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
+			*sepp = sep - t;
+			return 1;
+		}
+	}
+	if (strcmp(t, arg) == 0) {
+		*sepp = 0;
+		return 1;
+	}
+	return 0;
+}
+
+static const struct fuse_opt *find_opt(const struct fuse_opt *opt,
+				       const char *arg, unsigned *sepp)
+{
+	for (; opt && opt->templ; opt++)
+		if (match_template(opt->templ, arg, sepp))
+			return opt;
+	return NULL;
+}
+
+int fuse_opt_match(const struct fuse_opt *opts, const char *opt)
+{
+	unsigned dummy;
+	return find_opt(opts, opt, &dummy) ? 1 : 0;
+}
+
+static int process_opt_param(void *var, const char *format, const char *param,
+			     const char *arg)
+{
+	assert(format[0] == '%');
+	if (format[1] == 's') {
+		char **s = var;
+		char *copy = strdup(param);
+		if (!copy)
+			return alloc_failed();
+
+		free(*s);
+		*s = copy;
+	} else {
+		if (sscanf(param, format, var) != 1) {
+			fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n", arg);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int process_opt(struct fuse_opt_context *ctx,
+		       const struct fuse_opt *opt, unsigned sep,
+		       const char *arg, int iso)
+{
+	if (opt->offset == -1U) {
+		if (call_proc(ctx, arg, opt->value, iso) == -1)
+			return -1;
+	} else {
+		void *var = (char *)ctx->data + opt->offset;
+		if (sep && opt->templ[sep + 1]) {
+			const char *param = arg + sep;
+			if (opt->templ[sep] == '=')
+				param ++;
+			if (process_opt_param(var, opt->templ + sep + 1,
+					      param, arg) == -1)
+				return -1;
+		} else
+			*(int *)var = opt->value;
+	}
+	return 0;
+}
+
+static int process_opt_sep_arg(struct fuse_opt_context *ctx,
+			       const struct fuse_opt *opt, unsigned sep,
+			       const char *arg, int iso)
+{
+	int res;
+	char *newarg;
+	char *param;
+
+	if (next_arg(ctx, arg) == -1)
+		return -1;
+
+	param = ctx->argv[ctx->argctr];
+	newarg = malloc(sep + strlen(param) + 1);
+	if (!newarg)
+		return alloc_failed();
+
+	memcpy(newarg, arg, sep);
+	strcpy(newarg + sep, param);
+	res = process_opt(ctx, opt, sep, newarg, iso);
+	free(newarg);
+
+	return res;
+}
+
+static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
+{
+	unsigned sep;
+	const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
+	if (opt) {
+		for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
+			int res;
+			if (sep && opt->templ[sep] == ' ' && !arg[sep])
+				res = process_opt_sep_arg(ctx, opt, sep, arg,
+							  iso);
+			else
+				res = process_opt(ctx, opt, sep, arg, iso);
+			if (res == -1)
+				return -1;
+		}
+		return 0;
+	} else
+		return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
+}
+
+static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
+{
+	char *s = opts;
+	char *d = s;
+	int end = 0;
+
+	while (!end) {
+		if (*s == '\0')
+			end = 1;
+		if (*s == ',' || end) {
+			int res;
+
+			*d = '\0';
+			res = process_gopt(ctx, opts, 1);
+			if (res == -1)
+				return -1;
+			d = opts;
+		} else {
+			if (s[0] == '\\' && s[1] != '\0') {
+				s++;
+				if (s[0] >= '0' && s[0] <= '3' &&
+				    s[1] >= '0' && s[1] <= '7' &&
+				    s[2] >= '0' && s[2] <= '7') {
+					*d++ = (s[0] - '0') * 0100 +
+						(s[1] - '0') * 0010 +
+						(s[2] - '0');
+					s += 2;
+				} else {
+					*d++ = *s;
+				}
+			} else {
+				*d++ = *s;
+			}
+		}
+		s++;
+	}
+
+	return 0;
+}
+
+static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
+{
+	int res;
+	char *copy = strdup(opts);
+
+	if (!copy) {
+		fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
+		return -1;
+	}
+	res = process_real_option_group(ctx, copy);
+	free(copy);
+	return res;
+}
+
+static int process_one(struct fuse_opt_context *ctx, const char *arg)
+{
+	if (ctx->nonopt || arg[0] != '-')
+		return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0);
+	else if (arg[1] == 'o') {
+		if (arg[2])
+			return process_option_group(ctx, arg + 2);
+		else {
+			if (next_arg(ctx, arg) == -1)
+				return -1;
+
+			return process_option_group(ctx,
+						    ctx->argv[ctx->argctr]);
+		}
+	} else if (arg[1] == '-' && !arg[2]) {
+		if (add_arg(ctx, arg) == -1)
+			return -1;
+		ctx->nonopt = ctx->outargs.argc;
+		return 0;
+	} else
+		return process_gopt(ctx, arg, 0);
+}
+
+static int opt_parse(struct fuse_opt_context *ctx)
+{
+	if (ctx->argc) {
+		if (add_arg(ctx, ctx->argv[0]) == -1)
+			return -1;
+	}
+
+	for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++)
+		if (process_one(ctx, ctx->argv[ctx->argctr]) == -1)
+			return -1;
+
+	if (ctx->opts) {
+		if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
+		    fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1)
+			return -1;
+	}
+
+	/* If option separator ("--") is the last argument, remove it */
+	if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
+	    strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) {
+		free(ctx->outargs.argv[ctx->outargs.argc - 1]);
+		ctx->outargs.argv[--ctx->outargs.argc] = NULL;
+	}
+
+	return 0;
+}
+
+int fuse_opt_parse(struct fuse_args *args, void *data,
+		   const struct fuse_opt opts[], fuse_opt_proc_t proc)
+{
+	int res;
+	struct fuse_opt_context ctx = {
+		.data = data,
+		.opt = opts,
+		.proc = proc,
+	};
+
+	if (!args || !args->argv || !args->argc)
+		return 0;
+
+	ctx.argc = args->argc;
+	ctx.argv = args->argv;
+
+	res = opt_parse(&ctx);
+	if (res != -1) {
+		struct fuse_args tmp = *args;
+		*args = ctx.outargs;
+		ctx.outargs = tmp;
+	}
+	free(ctx.opts);
+	fuse_opt_free_args(&ctx.outargs);
+	return res;
+}
diff --git a/tools/virtiofsd/fuse_signals.c b/tools/virtiofsd/fuse_signals.c
new file mode 100644
index 0000000000..4271947bd4
--- /dev/null
+++ b/tools/virtiofsd/fuse_signals.c
@@ -0,0 +1,91 @@
+/*
+  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 "config.h"
+#include "fuse_lowlevel.h"
+#include "fuse_i.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.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) {
+		perror("fuse: cannot get old signal handler");
+		return -1;
+	}
+
+	if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
+	    sigaction(sig, &sa, NULL) == -1) {
+		perror("fuse: cannot set signal handler");
+		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);
+}
diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c
new file mode 100644
index 0000000000..64ff7ad6d5
--- /dev/null
+++ b/tools/virtiofsd/helper.c
@@ -0,0 +1,440 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
+
+  Helper functions to create (simple) standalone programs. With the
+  aid of these functions it should be possible to create full FUSE
+  file system by implementing nothing but the request handlers.
+
+  This program can be distributed under the terms of the GNU LGPLv2.
+  See the file COPYING.LIB.
+*/
+
+#include "config.h"
+#include "fuse_i.h"
+#include "fuse_misc.h"
+#include "fuse_opt.h"
+#include "fuse_lowlevel.h"
+#include "mount_util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/param.h>
+
+#define FUSE_HELPER_OPT(t, p) \
+	{ t, offsetof(struct fuse_cmdline_opts, p), 1 }
+
+static const struct fuse_opt fuse_helper_opts[] = {
+	FUSE_HELPER_OPT("-h",		show_help),
+	FUSE_HELPER_OPT("--help",	show_help),
+	FUSE_HELPER_OPT("-V",		show_version),
+	FUSE_HELPER_OPT("--version",	show_version),
+	FUSE_HELPER_OPT("-d",		debug),
+	FUSE_HELPER_OPT("debug",	debug),
+	FUSE_HELPER_OPT("-d",		foreground),
+	FUSE_HELPER_OPT("debug",	foreground),
+	FUSE_OPT_KEY("-d",		FUSE_OPT_KEY_KEEP),
+	FUSE_OPT_KEY("debug",		FUSE_OPT_KEY_KEEP),
+	FUSE_HELPER_OPT("-f",		foreground),
+	FUSE_HELPER_OPT("-s",		singlethread),
+	FUSE_HELPER_OPT("fsname=",	nodefault_subtype),
+	FUSE_OPT_KEY("fsname=",		FUSE_OPT_KEY_KEEP),
+#ifndef __FreeBSD__
+	FUSE_HELPER_OPT("subtype=",	nodefault_subtype),
+	FUSE_OPT_KEY("subtype=",	FUSE_OPT_KEY_KEEP),
+#endif
+	FUSE_HELPER_OPT("clone_fd",	clone_fd),
+	FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
+	FUSE_OPT_END
+};
+
+struct fuse_conn_info_opts {
+	int atomic_o_trunc;
+	int no_remote_posix_lock;
+	int no_remote_flock;
+	int splice_write;
+	int splice_move;
+	int splice_read;
+	int no_splice_write;
+	int no_splice_move;
+	int no_splice_read;
+	int auto_inval_data;
+	int no_auto_inval_data;
+	int no_readdirplus;
+	int no_readdirplus_auto;
+	int async_dio;
+	int no_async_dio;
+	int writeback_cache;
+	int no_writeback_cache;
+	int async_read;
+	int sync_read;
+	unsigned max_write;
+	unsigned max_readahead;
+	unsigned max_background;
+	unsigned congestion_threshold;
+	unsigned time_gran;
+	int set_max_write;
+	int set_max_readahead;
+	int set_max_background;
+	int set_congestion_threshold;
+	int set_time_gran;
+};
+
+#define CONN_OPTION(t, p, v)					\
+	{ t, offsetof(struct fuse_conn_info_opts, p), v }
+static const struct fuse_opt conn_info_opt_spec[] = {
+	CONN_OPTION("max_write=%u", max_write, 0),
+	CONN_OPTION("max_write=", set_max_write, 1),
+	CONN_OPTION("max_readahead=%u", max_readahead, 0),
+	CONN_OPTION("max_readahead=", set_max_readahead, 1),
+	CONN_OPTION("max_background=%u", max_background, 0),
+	CONN_OPTION("max_background=", set_max_background, 1),
+	CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
+	CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
+	CONN_OPTION("sync_read", sync_read, 1),
+	CONN_OPTION("async_read", async_read, 1),
+	CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
+	CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
+	CONN_OPTION("no_remote_lock", no_remote_flock, 1),
+	CONN_OPTION("no_remote_flock", no_remote_flock, 1),
+	CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
+	CONN_OPTION("splice_write", splice_write, 1),
+	CONN_OPTION("no_splice_write", no_splice_write, 1),
+	CONN_OPTION("splice_move", splice_move, 1),
+	CONN_OPTION("no_splice_move", no_splice_move, 1),
+	CONN_OPTION("splice_read", splice_read, 1),
+	CONN_OPTION("no_splice_read", no_splice_read, 1),
+	CONN_OPTION("auto_inval_data", auto_inval_data, 1),
+	CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
+	CONN_OPTION("readdirplus=no", no_readdirplus, 1),
+	CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
+	CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
+	CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
+	CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
+	CONN_OPTION("async_dio", async_dio, 1),
+	CONN_OPTION("no_async_dio", no_async_dio, 1),
+	CONN_OPTION("writeback_cache", writeback_cache, 1),
+	CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
+	CONN_OPTION("time_gran=%u", time_gran, 0),
+	CONN_OPTION("time_gran=", set_time_gran, 1),
+	FUSE_OPT_END
+};
+
+
+void fuse_cmdline_help(void)
+{
+	printf("    -h   --help            print help\n"
+	       "    -V   --version         print version\n"
+	       "    -d   -o debug          enable debug output (implies -f)\n"
+	       "    -f                     foreground operation\n"
+	       "    -s                     disable multi-threaded operation\n"
+	       "    -o clone_fd            use separate fuse device fd for each thread\n"
+	       "                           (may improve performance)\n"
+	       "    -o max_idle_threads    the maximum number of idle worker threads\n"
+	       "                           allowed (default: 10)\n");
+}
+
+static int fuse_helper_opt_proc(void *data, const char *arg, int key,
+				struct fuse_args *outargs)
+{
+	(void) outargs;
+	struct fuse_cmdline_opts *opts = data;
+
+	switch (key) {
+	case FUSE_OPT_KEY_NONOPT:
+		if (!opts->mountpoint) {
+			if (fuse_mnt_parse_fuse_fd(arg) != -1) {
+				return fuse_opt_add_opt(&opts->mountpoint, arg);
+			}
+
+			char mountpoint[PATH_MAX] = "";
+			if (realpath(arg, mountpoint) == NULL) {
+				fuse_log(FUSE_LOG_ERR,
+					"fuse: bad mount point `%s': %s\n",
+					arg, strerror(errno));
+				return -1;
+			}
+			return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
+		} else {
+			fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
+			return -1;
+		}
+
+	default:
+		/* Pass through unknown options */
+		return 1;
+	}
+}
+
+/* Under FreeBSD, there is no subtype option so this
+   function actually sets the fsname */
+static int add_default_subtype(const char *progname, struct fuse_args *args)
+{
+	int res;
+	char *subtype_opt;
+
+	const char *basename = strrchr(progname, '/');
+	if (basename == NULL)
+		basename = progname;
+	else if (basename[1] != '\0')
+		basename++;
+
+	subtype_opt = (char *) malloc(strlen(basename) + 64);
+	if (subtype_opt == NULL) {
+		fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
+		return -1;
+	}
+#ifdef __FreeBSD__
+	sprintf(subtype_opt, "-ofsname=%s", basename);
+#else
+	sprintf(subtype_opt, "-osubtype=%s", basename);
+#endif
+	res = fuse_opt_add_arg(args, subtype_opt);
+	free(subtype_opt);
+	return res;
+}
+
+int fuse_parse_cmdline(struct fuse_args *args,
+		       struct fuse_cmdline_opts *opts)
+{
+	memset(opts, 0, sizeof(struct fuse_cmdline_opts));
+
+	opts->max_idle_threads = 10;
+
+	if (fuse_opt_parse(args, opts, fuse_helper_opts,
+			   fuse_helper_opt_proc) == -1)
+		return -1;
+
+	/* *Linux*: if neither -o subtype nor -o fsname are specified,
+	   set subtype to program's basename.
+	   *FreeBSD*: if fsname is not specified, set to program's
+	   basename. */
+	if (!opts->nodefault_subtype)
+		if (add_default_subtype(args->argv[0], args) == -1)
+			return -1;
+
+	return 0;
+}
+
+
+int fuse_daemonize(int foreground)
+{
+	if (!foreground) {
+		int nullfd;
+		int waiter[2];
+		char completed;
+
+		if (pipe(waiter)) {
+			perror("fuse_daemonize: pipe");
+			return -1;
+		}
+
+		/*
+		 * demonize current process by forking it and killing the
+		 * parent.  This makes current process as a child of 'init'.
+		 */
+		switch(fork()) {
+		case -1:
+			perror("fuse_daemonize: fork");
+			return -1;
+		case 0:
+			break;
+		default:
+			(void) read(waiter[0], &completed, sizeof(completed));
+			_exit(0);
+		}
+
+		if (setsid() == -1) {
+			perror("fuse_daemonize: setsid");
+			return -1;
+		}
+
+		(void) chdir("/");
+
+		nullfd = open("/dev/null", O_RDWR, 0);
+		if (nullfd != -1) {
+			(void) dup2(nullfd, 0);
+			(void) dup2(nullfd, 1);
+			(void) dup2(nullfd, 2);
+			if (nullfd > 2)
+				close(nullfd);
+		}
+
+		/* Propagate completion of daemon initialization */
+		completed = 1;
+		(void) write(waiter[1], &completed, sizeof(completed));
+		close(waiter[0]);
+		close(waiter[1]);
+	} else {
+		(void) chdir("/");
+	}
+	return 0;
+}
+
+int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
+		   size_t op_size, void *user_data)
+{
+	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+	struct fuse *fuse;
+	struct fuse_cmdline_opts opts;
+	int res;
+
+	if (fuse_parse_cmdline(&args, &opts) != 0)
+		return 1;
+
+	if (opts.show_version) {
+		printf("FUSE library version %s\n", PACKAGE_VERSION);
+		fuse_lowlevel_version();
+		res = 0;
+		goto out1;
+	}
+
+	if (opts.show_help) {
+		if(args.argv[0][0] != '\0')
+			printf("usage: %s [options] <mountpoint>\n\n",
+			       args.argv[0]);
+		printf("FUSE options:\n");
+		fuse_cmdline_help();
+		fuse_lib_help(&args);
+		res = 0;
+		goto out1;
+	}
+
+	if (!opts.show_help &&
+	    !opts.mountpoint) {
+		fuse_log(FUSE_LOG_ERR, "error: no mountpoint specified\n");
+		res = 2;
+		goto out1;
+	}
+
+
+	fuse = fuse_new_31(&args, op, op_size, user_data);
+	if (fuse == NULL) {
+		res = 3;
+		goto out1;
+	}
+
+	if (fuse_mount(fuse,opts.mountpoint) != 0) {
+		res = 4;
+		goto out2;
+	}
+
+	if (fuse_daemonize(opts.foreground) != 0) {
+		res = 5;
+		goto out3;
+	}
+
+	struct fuse_session *se = fuse_get_session(fuse);
+	if (fuse_set_signal_handlers(se) != 0) {
+		res = 6;
+		goto out3;
+	}
+
+	if (opts.singlethread)
+		res = fuse_loop(fuse);
+	else {
+		struct fuse_loop_config loop_config;
+		loop_config.clone_fd = opts.clone_fd;
+		loop_config.max_idle_threads = opts.max_idle_threads;
+		res = fuse_loop_mt_32(fuse, &loop_config);
+	}
+	if (res)
+		res = 7;
+
+	fuse_remove_signal_handlers(se);
+out3:
+	fuse_unmount(fuse);
+out2:
+	fuse_destroy(fuse);
+out1:
+	free(opts.mountpoint);
+	fuse_opt_free_args(&args);
+	return res;
+}
+
+
+void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
+			       struct fuse_conn_info *conn)
+{
+	if(opts->set_max_write)
+		conn->max_write = opts->max_write;
+	if(opts->set_max_background)
+		conn->max_background = opts->max_background;
+	if(opts->set_congestion_threshold)
+		conn->congestion_threshold = opts->congestion_threshold;
+	if(opts->set_time_gran)
+		conn->time_gran = opts->time_gran;
+	if(opts->set_max_readahead)
+		conn->max_readahead = opts->max_readahead;
+
+#define LL_ENABLE(cond,cap) \
+	if (cond) conn->want |= (cap)
+#define LL_DISABLE(cond,cap) \
+	if (cond) conn->want &= ~(cap)
+
+	LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
+	LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
+
+	LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
+	LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
+
+	LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
+	LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
+
+	LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
+	LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
+
+	LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
+	LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
+
+	LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
+	LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
+
+	LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
+	LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
+
+	LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
+	LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
+
+	LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
+	LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
+}
+
+struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args)
+{
+	struct fuse_conn_info_opts *opts;
+
+	opts = calloc(1, sizeof(struct fuse_conn_info_opts));
+	if(opts == NULL) {
+		fuse_log(FUSE_LOG_ERR, "calloc failed\n");
+		return NULL;
+	}
+	if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
+		free(opts);
+		return NULL;
+	}
+	return opts;
+}
+
+int fuse_open_channel(const char *mountpoint, const char* options)
+{
+	struct mount_opts *opts = NULL;
+	int fd = -1;
+	const char *argv[] = { "", "-o", options };
+	int argc = sizeof(argv) / sizeof(argv[0]);
+	struct fuse_args args = FUSE_ARGS_INIT(argc, (char**) argv);
+
+	opts = parse_mount_opts(&args);
+	if (opts == NULL)
+		return -1;
+
+	fd = fuse_kern_mount(mountpoint, opts);
+	destroy_mount_opts(opts);
+
+	return fd;
+}
-- 
2.24.1



  parent reply	other threads:[~2020-01-23 18:31 UTC|newest]

Thread overview: 113+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-23 16:44 [PULL 000/108] virtiofs queue Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 001/108] virtiofsd: Pull in upstream headers Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 002/108] virtiofsd: Pull in kernel's fuse.h Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` Dr. David Alan Gilbert (git) [this message]
2020-01-23 16:44 ` [PULL 004/108] virtiofsd: Add fuse_lowlevel.c Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 005/108] virtiofsd: Add passthrough_ll Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 006/108] virtiofsd: Trim down imported files Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 007/108] virtiofsd: Format imported files to qemu style Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 008/108] virtiofsd: remove mountpoint dummy argument Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 009/108] virtiofsd: remove unused notify reply support Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 010/108] virtiofsd: Remove unused enum fuse_buf_copy_flags Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 011/108] virtiofsd: Fix fuse_daemonize ignored return values Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 012/108] virtiofsd: Fix common header and define for QEMU builds Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 013/108] virtiofsd: Trim out compatibility code Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 014/108] vitriofsd/passthrough_ll: fix fallocate() ifdefs Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 015/108] virtiofsd: Make fsync work even if only inode is passed in Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 016/108] virtiofsd: Add options for virtio Dr. David Alan Gilbert (git)
2020-01-23 16:44 ` [PULL 017/108] virtiofsd: add -o source=PATH to help output Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 018/108] virtiofsd: Open vhost connection instead of mounting Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 019/108] virtiofsd: Start wiring up vhost-user Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 020/108] virtiofsd: Add main virtio loop Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 021/108] virtiofsd: get/set features callbacks Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 022/108] virtiofsd: Start queue threads Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 023/108] virtiofsd: Poll kick_fd for queue Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 024/108] virtiofsd: Start reading commands from queue Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 025/108] virtiofsd: Send replies to messages Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 026/108] virtiofsd: Keep track of replies Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 027/108] virtiofsd: Add Makefile wiring for virtiofsd contrib Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 028/108] virtiofsd: Fast path for virtio read Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 029/108] virtiofsd: add --fd=FDNUM fd passing option Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 030/108] virtiofsd: make -f (foreground) the default Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 031/108] virtiofsd: add vhost-user.json file Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 032/108] virtiofsd: add --print-capabilities option Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 033/108] virtiofs: Add maintainers entry Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 034/108] virtiofsd: passthrough_ll: create new files in caller's context Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 035/108] virtiofsd: passthrough_ll: add lo_map for ino/fh indirection Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 036/108] virtiofsd: passthrough_ll: add ino_map to hide lo_inode pointers Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 037/108] virtiofsd: passthrough_ll: add dirp_map to hide lo_dirp pointers Dr. David Alan Gilbert (git)
2020-03-20 13:38   ` Peter Maydell
2020-01-23 16:45 ` [PULL 038/108] virtiofsd: passthrough_ll: add fd_map to hide file descriptors Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 039/108] virtiofsd: passthrough_ll: add fallback for racy ops Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 040/108] virtiofsd: validate path components Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 041/108] virtiofsd: Plumb fuse_bufvec through to do_write_buf Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 042/108] virtiofsd: Pass write iov's all the way through Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 043/108] virtiofsd: add fuse_mbuf_iter API Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 044/108] virtiofsd: validate input buffer sizes in do_write_buf() Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 045/108] virtiofsd: check input buffer size in fuse_lowlevel.c ops Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 046/108] virtiofsd: prevent ".." escape in lo_do_lookup() Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 047/108] virtiofsd: prevent ".." escape in lo_do_readdir() Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 048/108] virtiofsd: use /proc/self/fd/ O_PATH file descriptor Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 049/108] virtiofsd: sandbox mount namespace Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 050/108] virtiofsd: move to an empty network namespace Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 051/108] virtiofsd: move to a new pid namespace Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 052/108] virtiofsd: add seccomp whitelist Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 053/108] virtiofsd: Parse flag FUSE_WRITE_KILL_PRIV Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 054/108] virtiofsd: cap-ng helpers Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 055/108] virtiofsd: Drop CAP_FSETID if client asked for it Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 056/108] virtiofsd: set maximum RLIMIT_NOFILE limit Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 057/108] virtiofsd: fix libfuse information leaks Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 058/108] virtiofsd: add --syslog command-line option Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 059/108] virtiofsd: print log only when priority is high enough Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 060/108] virtiofsd: Add ID to the log with FUSE_LOG_DEBUG level Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 061/108] virtiofsd: Add timestamp " Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 062/108] virtiofsd: Handle reinit Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 063/108] virtiofsd: Handle hard reboot Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 064/108] virtiofsd: Kill threads when queues are stopped Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 065/108] vhost-user: Print unexpected slave message types Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 066/108] contrib/libvhost-user: Protect slave fd with mutex Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 067/108] virtiofsd: passthrough_ll: add renameat2 support Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 068/108] virtiofsd: passthrough_ll: disable readdirplus on cache=never Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 069/108] virtiofsd: passthrough_ll: control readdirplus Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 070/108] virtiofsd: rename unref_inode() to unref_inode_lolocked() Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 071/108] virtiofsd: fail when parent inode isn't known in lo_do_lookup() Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 072/108] virtiofsd: extract root inode init into setup_root() Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 073/108] virtiofsd: passthrough_ll: clean up cache related options Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 074/108] virtiofsd: passthrough_ll: use hashtable Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 075/108] virtiofsd: Clean up inodes on destroy Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 076/108] virtiofsd: support nanosecond resolution for file timestamp Dr. David Alan Gilbert (git)
2020-01-23 16:45 ` [PULL 077/108] virtiofsd: fix error handling in main() Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 078/108] virtiofsd: cleanup allocated resource in se Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 079/108] virtiofsd: fix memory leak on lo.source Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 080/108] virtiofsd: add helper for lo_data cleanup Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 081/108] virtiofsd: Prevent multiply running with same vhost_user_socket Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 082/108] virtiofsd: enable PARALLEL_DIROPS during INIT Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 083/108] virtiofsd: fix incorrect error handling in lo_do_lookup Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 084/108] Virtiofsd: fix memory leak on fuse queueinfo Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 085/108] virtiofsd: Support remote posix locks Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 086/108] virtiofsd: use fuse_lowlevel_is_virtio() in fuse_session_destroy() Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 087/108] virtiofsd: prevent fv_queue_thread() vs virtio_loop() races Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 088/108] virtiofsd: make lo_release() atomic Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 089/108] virtiofsd: prevent races with lo_dirp_put() Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 090/108] virtiofsd: rename inode->refcount to inode->nlookup Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 091/108] libvhost-user: Fix some memtable remap cases Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 092/108] virtiofsd: passthrough_ll: fix refcounting on remove/rename Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 093/108] virtiofsd: introduce inode refcount to prevent use-after-free Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 094/108] virtiofsd: do not always set FUSE_FLOCK_LOCKS Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 095/108] virtiofsd: convert more fprintf and perror to use fuse log infra Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 096/108] virtiofsd: Reset O_DIRECT flag during file open Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 097/108] virtiofsd: Fix data corruption with O_APPEND write in writeback mode Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 098/108] virtiofsd: passthrough_ll: Use cache_readdir for directory open Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 099/108] virtiofsd: add definition of fuse_buf_writev() Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 100/108] virtiofsd: use fuse_buf_writev to replace fuse_buf_write for better performance Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 101/108] virtiofsd: process requests in a thread pool Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 102/108] virtiofsd: prevent FUSE_INIT/FUSE_DESTROY races Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 103/108] virtiofsd: fix lo_destroy() resource leaks Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 104/108] virtiofsd: add --thread-pool-size=NUM option Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 105/108] virtiofsd: Convert lo_destroy to take the lo->mutex lock itself Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 106/108] virtiofsd/passthrough_ll: Pass errno to fuse_reply_err() Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 107/108] virtiofsd: stop all queue threads on exit in virtio_loop() Dr. David Alan Gilbert (git)
2020-01-23 16:46 ` [PULL 108/108] virtiofsd: add some options to the help message Dr. David Alan Gilbert (git)
2020-01-23 19:32 ` [PULL 000/108] virtiofs queue Dr. David Alan Gilbert
2020-01-24 11:06   ` Peter Maydell
2020-01-23 21:18 ` no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200123164630.91498-4-dgilbert@redhat.com \
    --to=dgilbert@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.