diff mbox series

[006/104] virtiofsd: Trim down imported files

Message ID 20191212163904.159893-7-dgilbert@redhat.com
State New
Headers show
Series virtiofs daemon [all] | expand

Commit Message

Dr. David Alan Gilbert Dec. 12, 2019, 4:37 p.m. UTC
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

There's a lot of the original fuse code we don't need; trim them down.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 tools/virtiofsd/fuse.h                |   8 -
 tools/virtiofsd/fuse_common.h         |   8 -
 tools/virtiofsd/fuse_i.h              |  22 -
 tools/virtiofsd/fuse_log.h            |   8 -
 tools/virtiofsd/fuse_loop_mt.c        | 308 ------------
 tools/virtiofsd/fuse_lowlevel.c       | 653 +-------------------------
 tools/virtiofsd/fuse_lowlevel.h       |   8 -
 tools/virtiofsd/fuse_opt.h            |   8 -
 tools/virtiofsd/helper.c              | 138 ------
 tools/virtiofsd/passthrough_helpers.h |  26 -
 10 files changed, 5 insertions(+), 1182 deletions(-)

Comments

Daniel P. Berrangé Jan. 3, 2020, 12:02 p.m. UTC | #1
On Thu, Dec 12, 2019 at 04:37:26PM +0000, Dr. David Alan Gilbert (git) wrote:
> From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> 
> There's a lot of the original fuse code we don't need; trim them down.
> 
> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
>  tools/virtiofsd/fuse.h                |   8 -
>  tools/virtiofsd/fuse_common.h         |   8 -
>  tools/virtiofsd/fuse_i.h              |  22 -
>  tools/virtiofsd/fuse_log.h            |   8 -
>  tools/virtiofsd/fuse_loop_mt.c        | 308 ------------
>  tools/virtiofsd/fuse_lowlevel.c       | 653 +-------------------------
>  tools/virtiofsd/fuse_lowlevel.h       |   8 -
>  tools/virtiofsd/fuse_opt.h            |   8 -
>  tools/virtiofsd/helper.c              | 138 ------
>  tools/virtiofsd/passthrough_helpers.h |  26 -
>  10 files changed, 5 insertions(+), 1182 deletions(-)

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>


Regards,
Daniel
Xiao Yang Jan. 21, 2020, 9:58 a.m. UTC | #2
On 2019/12/13 0:37, Dr. David Alan Gilbert (git) wrote:
> -	res = fuse_buf_copy(&pipe_buf, buf,
> -			    FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK);
> -	if (res<  0) {
> -		if (res == -EAGAIN || res == -EINVAL) {
> -			/*
> -			 * Should only get EAGAIN on kernels with
> -			 * broken SPLICE_F_NONBLOCK support (<=
> -			 * 2.6.35) where this error or a short read is
> -			 * returned even if the pipe itself is not
> -			 * full
> -			 *
> -			 * EINVAL might mean that splice can't handle
> -			 * this combination of input and output.
> -			 */
> -			if (res == -EAGAIN)
> -				se->broken_splice_nonblock = 1;
> -
> -			pthread_setspecific(se->pipe_key, NULL);
> -			fuse_ll_pipe_free(llp);
> -			goto fallback;
> -		}
> -		res = -res;
> -		goto clear_pipe;
> -	}
> -
> -	if (res != 0&&  res<  len) {
> -		struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
> -		void *mbuf;
> -		size_t now_len = res;
> -		/*
> -		 * For regular files a short count is either
> -		 *  1) due to EOF, or
> -		 *  2) because of broken SPLICE_F_NONBLOCK (see above)
> -		 *
> -		 * For other inputs it's possible that we overflowed
> -		 * the pipe because of small buffer fragments.
> -		 */
> -
> -		res = posix_memalign(&mbuf, pagesize, len);
> -		if (res != 0)
> -			goto clear_pipe;
> -
> -		mem_buf.buf[0].mem = mbuf;
> -		mem_buf.off = now_len;
> -		res = fuse_buf_copy(&mem_buf, buf, 0);
> -		if (res>  0) {
> -			char *tmpbuf;
> -			size_t extra_len = res;
> -			/*
> -			 * Trickiest case: got more data.  Need to get
> -			 * back the data from the pipe and then fall
> -			 * back to regular write.
> -			 */
> -			tmpbuf = malloc(headerlen);
> -			if (tmpbuf == NULL) {
> -				free(mbuf);
> -				res = ENOMEM;
> -				goto clear_pipe;
> -			}
> -			res = read_back(llp->pipe[0], tmpbuf, headerlen);
> -			free(tmpbuf);
> -			if (res != 0) {
> -				free(mbuf);
> -				goto clear_pipe;
> -			}
> -			res = read_back(llp->pipe[0], mbuf, now_len);
> -			if (res != 0) {
> -				free(mbuf);
> -				goto clear_pipe;
> -			}
> -			len = now_len + extra_len;
> -			iov[iov_count].iov_base = mbuf;
> -			iov[iov_count].iov_len = len;
> -			iov_count++;
> -			res = fuse_send_msg(se, ch, iov, iov_count);
> -			free(mbuf);
> -			return res;
> -		}
> -		free(mbuf);
> -		res = now_len;
> -	}
> -	len = res;
> -	out->len = headerlen + len;
> -
> -	if (se->debug) {
> -		fuse_log(FUSE_LOG_DEBUG,
> -			"   unique: %llu, success, outsize: %i (splice)\n",
> -			(unsigned long long) out->unique, out->len);
> -	}
> -
> -	splice_flags = 0;
> -	if ((flags&  FUSE_BUF_SPLICE_MOVE)&&
> -	    (se->conn.want&  FUSE_CAP_SPLICE_MOVE))
> -		splice_flags |= SPLICE_F_MOVE;
> -
> -	res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd,
> -		     NULL, out->len, splice_flags);
Hi,

1) In buffer.c, fuse_buf_splice() uses splice(2) to copy/move data in 
some cases if the syscall is supported.
2) One pipe needs to be passed to splice(2) so splice(2) without one 
pipe fails and then go back to use other ways(e.g. use fuse_buf_fd_to_fd()).
3) fuse_buf_copy() calls fuse_buf_splice() indirectly and this patch has 
removed all pipes used by fuse_buf_copy().

Is it necessary to leave the code related to splice(2)?  Is it going to 
be used in future?
We have to use splice(2) by the correct CONFIG_SPLICE macro If necessary.

Best Regards,
Xiao Yang
Dr. David Alan Gilbert Jan. 21, 2020, 10:51 a.m. UTC | #3
* Xiao Yang (yangx.jy@cn.fujitsu.com) wrote:
> On 2019/12/13 0:37, Dr. David Alan Gilbert (git) wrote:
> > -	res = fuse_buf_copy(&pipe_buf, buf,
> > -			    FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK);
> > -	if (res<  0) {
> > -		if (res == -EAGAIN || res == -EINVAL) {
> > -			/*
> > -			 * Should only get EAGAIN on kernels with
> > -			 * broken SPLICE_F_NONBLOCK support (<=
> > -			 * 2.6.35) where this error or a short read is
> > -			 * returned even if the pipe itself is not
> > -			 * full
> > -			 *
> > -			 * EINVAL might mean that splice can't handle
> > -			 * this combination of input and output.
> > -			 */
> > -			if (res == -EAGAIN)
> > -				se->broken_splice_nonblock = 1;
> > -
> > -			pthread_setspecific(se->pipe_key, NULL);
> > -			fuse_ll_pipe_free(llp);
> > -			goto fallback;
> > -		}
> > -		res = -res;
> > -		goto clear_pipe;
> > -	}
> > -
> > -	if (res != 0&&  res<  len) {
> > -		struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
> > -		void *mbuf;
> > -		size_t now_len = res;
> > -		/*
> > -		 * For regular files a short count is either
> > -		 *  1) due to EOF, or
> > -		 *  2) because of broken SPLICE_F_NONBLOCK (see above)
> > -		 *
> > -		 * For other inputs it's possible that we overflowed
> > -		 * the pipe because of small buffer fragments.
> > -		 */
> > -
> > -		res = posix_memalign(&mbuf, pagesize, len);
> > -		if (res != 0)
> > -			goto clear_pipe;
> > -
> > -		mem_buf.buf[0].mem = mbuf;
> > -		mem_buf.off = now_len;
> > -		res = fuse_buf_copy(&mem_buf, buf, 0);
> > -		if (res>  0) {
> > -			char *tmpbuf;
> > -			size_t extra_len = res;
> > -			/*
> > -			 * Trickiest case: got more data.  Need to get
> > -			 * back the data from the pipe and then fall
> > -			 * back to regular write.
> > -			 */
> > -			tmpbuf = malloc(headerlen);
> > -			if (tmpbuf == NULL) {
> > -				free(mbuf);
> > -				res = ENOMEM;
> > -				goto clear_pipe;
> > -			}
> > -			res = read_back(llp->pipe[0], tmpbuf, headerlen);
> > -			free(tmpbuf);
> > -			if (res != 0) {
> > -				free(mbuf);
> > -				goto clear_pipe;
> > -			}
> > -			res = read_back(llp->pipe[0], mbuf, now_len);
> > -			if (res != 0) {
> > -				free(mbuf);
> > -				goto clear_pipe;
> > -			}
> > -			len = now_len + extra_len;
> > -			iov[iov_count].iov_base = mbuf;
> > -			iov[iov_count].iov_len = len;
> > -			iov_count++;
> > -			res = fuse_send_msg(se, ch, iov, iov_count);
> > -			free(mbuf);
> > -			return res;
> > -		}
> > -		free(mbuf);
> > -		res = now_len;
> > -	}
> > -	len = res;
> > -	out->len = headerlen + len;
> > -
> > -	if (se->debug) {
> > -		fuse_log(FUSE_LOG_DEBUG,
> > -			"   unique: %llu, success, outsize: %i (splice)\n",
> > -			(unsigned long long) out->unique, out->len);
> > -	}
> > -
> > -	splice_flags = 0;
> > -	if ((flags&  FUSE_BUF_SPLICE_MOVE)&&
> > -	    (se->conn.want&  FUSE_CAP_SPLICE_MOVE))
> > -		splice_flags |= SPLICE_F_MOVE;
> > -
> > -	res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd,
> > -		     NULL, out->len, splice_flags);
> Hi,
> 
> 1) In buffer.c, fuse_buf_splice() uses splice(2) to copy/move data in some
> cases if the syscall is supported.
> 2) One pipe needs to be passed to splice(2) so splice(2) without one pipe
> fails and then go back to use other ways(e.g. use fuse_buf_fd_to_fd()).
> 3) fuse_buf_copy() calls fuse_buf_splice() indirectly and this patch has
> removed all pipes used by fuse_buf_copy().
> 
> Is it necessary to leave the code related to splice(2)?  Is it going to be
> used in future?
> We have to use splice(2) by the correct CONFIG_SPLICE macro If necessary.

Yes, I think we never set HAVE_SPLICE; so that code can go.
I'll change this patch to remove that as well.

Dave

> Best Regards,
> Xiao Yang
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
Xiao Yang Jan. 22, 2020, 12:57 a.m. UTC | #4
On 2020/1/21 18:51, Dr. David Alan Gilbert wrote:
> * Xiao Yang (yangx.jy@cn.fujitsu.com) wrote:
>> On 2019/12/13 0:37, Dr. David Alan Gilbert (git) wrote:
>>> -	res = fuse_buf_copy(&pipe_buf, buf,
>>> -			    FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK);
>>> -	if (res<   0) {
>>> -		if (res == -EAGAIN || res == -EINVAL) {
>>> -			/*
>>> -			 * Should only get EAGAIN on kernels with
>>> -			 * broken SPLICE_F_NONBLOCK support (<=
>>> -			 * 2.6.35) where this error or a short read is
>>> -			 * returned even if the pipe itself is not
>>> -			 * full
>>> -			 *
>>> -			 * EINVAL might mean that splice can't handle
>>> -			 * this combination of input and output.
>>> -			 */
>>> -			if (res == -EAGAIN)
>>> -				se->broken_splice_nonblock = 1;
>>> -
>>> -			pthread_setspecific(se->pipe_key, NULL);
>>> -			fuse_ll_pipe_free(llp);
>>> -			goto fallback;
>>> -		}
>>> -		res = -res;
>>> -		goto clear_pipe;
>>> -	}
>>> -
>>> -	if (res != 0&&   res<   len) {
>>> -		struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
>>> -		void *mbuf;
>>> -		size_t now_len = res;
>>> -		/*
>>> -		 * For regular files a short count is either
>>> -		 *  1) due to EOF, or
>>> -		 *  2) because of broken SPLICE_F_NONBLOCK (see above)
>>> -		 *
>>> -		 * For other inputs it's possible that we overflowed
>>> -		 * the pipe because of small buffer fragments.
>>> -		 */
>>> -
>>> -		res = posix_memalign(&mbuf, pagesize, len);
>>> -		if (res != 0)
>>> -			goto clear_pipe;
>>> -
>>> -		mem_buf.buf[0].mem = mbuf;
>>> -		mem_buf.off = now_len;
>>> -		res = fuse_buf_copy(&mem_buf, buf, 0);
>>> -		if (res>   0) {
>>> -			char *tmpbuf;
>>> -			size_t extra_len = res;
>>> -			/*
>>> -			 * Trickiest case: got more data.  Need to get
>>> -			 * back the data from the pipe and then fall
>>> -			 * back to regular write.
>>> -			 */
>>> -			tmpbuf = malloc(headerlen);
>>> -			if (tmpbuf == NULL) {
>>> -				free(mbuf);
>>> -				res = ENOMEM;
>>> -				goto clear_pipe;
>>> -			}
>>> -			res = read_back(llp->pipe[0], tmpbuf, headerlen);
>>> -			free(tmpbuf);
>>> -			if (res != 0) {
>>> -				free(mbuf);
>>> -				goto clear_pipe;
>>> -			}
>>> -			res = read_back(llp->pipe[0], mbuf, now_len);
>>> -			if (res != 0) {
>>> -				free(mbuf);
>>> -				goto clear_pipe;
>>> -			}
>>> -			len = now_len + extra_len;
>>> -			iov[iov_count].iov_base = mbuf;
>>> -			iov[iov_count].iov_len = len;
>>> -			iov_count++;
>>> -			res = fuse_send_msg(se, ch, iov, iov_count);
>>> -			free(mbuf);
>>> -			return res;
>>> -		}
>>> -		free(mbuf);
>>> -		res = now_len;
>>> -	}
>>> -	len = res;
>>> -	out->len = headerlen + len;
>>> -
>>> -	if (se->debug) {
>>> -		fuse_log(FUSE_LOG_DEBUG,
>>> -			"   unique: %llu, success, outsize: %i (splice)\n",
>>> -			(unsigned long long) out->unique, out->len);
>>> -	}
>>> -
>>> -	splice_flags = 0;
>>> -	if ((flags&   FUSE_BUF_SPLICE_MOVE)&&
>>> -	    (se->conn.want&   FUSE_CAP_SPLICE_MOVE))
>>> -		splice_flags |= SPLICE_F_MOVE;
>>> -
>>> -	res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd,
>>> -		     NULL, out->len, splice_flags);
>> Hi,
>>
>> 1) In buffer.c, fuse_buf_splice() uses splice(2) to copy/move data in some
>> cases if the syscall is supported.
>> 2) One pipe needs to be passed to splice(2) so splice(2) without one pipe
>> fails and then go back to use other ways(e.g. use fuse_buf_fd_to_fd()).
>> 3) fuse_buf_copy() calls fuse_buf_splice() indirectly and this patch has
>> removed all pipes used by fuse_buf_copy().
>>
>> Is it necessary to leave the code related to splice(2)?  Is it going to be
>> used in future?
>> We have to use splice(2) by the correct CONFIG_SPLICE macro If necessary.
> Yes, I think we never set HAVE_SPLICE; so that code can go.
> I'll change this patch to remove that as well.
>
Hi Dave,

Agreed.
Reviewed-by: Xiao Yang <yangx.jy@cn.fujitsu.com>

Best Regards,
Xiao Yang
> Dave
>
>> Best Regards,
>> Xiao Yang
>>
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
>
>
>
> .
>
diff mbox series

Patch

diff --git a/tools/virtiofsd/fuse.h b/tools/virtiofsd/fuse.h
index 883f6e59fb..6c16a0041d 100644
--- a/tools/virtiofsd/fuse.h
+++ b/tools/virtiofsd/fuse.h
@@ -25,10 +25,6 @@ 
 #include <sys/statvfs.h>
 #include <sys/uio.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* ----------------------------------------------------------- *
  * Basic FUSE API					       *
  * ----------------------------------------------------------- */
@@ -1268,8 +1264,4 @@  struct fuse_session *fuse_get_session(struct fuse *f);
  */
 int fuse_open_channel(const char *mountpoint, const char *options);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* FUSE_H_ */
diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h
index 2d686b2ac4..18fba813da 100644
--- a/tools/virtiofsd/fuse_common.h
+++ b/tools/virtiofsd/fuse_common.h
@@ -28,10 +28,6 @@ 
 #define FUSE_MAKE_VERSION(maj, min)  ((maj) * 10 + (min))
 #define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * Information about an open file.
  *
@@ -802,10 +798,6 @@  void fuse_remove_signal_handlers(struct fuse_session *se);
 #  error only API version 30 or greater is supported
 #endif
 
-#ifdef __cplusplus
-}
-#endif
-
 
 /*
  * This interface uses 64 bit off_t.
diff --git a/tools/virtiofsd/fuse_i.h b/tools/virtiofsd/fuse_i.h
index d38b630ac5..bcd6a140fc 100644
--- a/tools/virtiofsd/fuse_i.h
+++ b/tools/virtiofsd/fuse_i.h
@@ -9,8 +9,6 @@ 
 #include "fuse.h"
 #include "fuse_lowlevel.h"
 
-struct mount_opts;
-
 struct fuse_req {
 	struct fuse_session *se;
 	uint64_t unique;
@@ -45,7 +43,6 @@  struct fuse_session {
 	char *mountpoint;
 	volatile int exited;
 	int fd;
-	struct mount_opts *mo;
 	int debug;
 	int deny_others;
 	struct fuse_lowlevel_ops op;
@@ -58,7 +55,6 @@  struct fuse_session {
 	struct fuse_req interrupts;
 	pthread_mutex_t lock;
 	int got_destroy;
-	pthread_key_t pipe_key;
 	int broken_splice_nonblock;
 	uint64_t notify_ctr;
 	struct fuse_notify_req notify_list;
@@ -106,34 +102,16 @@  struct fuse_chan *fuse_chan_get(struct fuse_chan *ch);
  */
 void fuse_chan_put(struct fuse_chan *ch);
 
-struct mount_opts *parse_mount_opts(struct fuse_args *args);
-void destroy_mount_opts(struct mount_opts *mo);
-void fuse_mount_version(void);
-unsigned get_max_read(struct mount_opts *o);
-void fuse_kern_unmount(const char *mountpoint, int fd);
-int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo);
-
 int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
 			       int count);
 void fuse_free_req(fuse_req_t req);
 
-void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeide, const void *inarg);
-
-int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg);
-
-int fuse_session_receive_buf_int(struct fuse_session *se, struct fuse_buf *buf,
-				 struct fuse_chan *ch);
 void fuse_session_process_buf_int(struct fuse_session *se,
 				  const struct fuse_buf *buf, struct fuse_chan *ch);
 
-struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op,
-		      size_t op_size, void *private_data);
-int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config);
-int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
 
 #define FUSE_MAX_MAX_PAGES 256
 #define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
 
 /* room needed in buffer to accommodate header */
 #define FUSE_BUFFER_HEADER_SIZE 0x1000
-
diff --git a/tools/virtiofsd/fuse_log.h b/tools/virtiofsd/fuse_log.h
index 5e112e0f53..0af700da6b 100644
--- a/tools/virtiofsd/fuse_log.h
+++ b/tools/virtiofsd/fuse_log.h
@@ -16,10 +16,6 @@ 
 
 #include <stdarg.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * Log severity level
  *
@@ -75,8 +71,4 @@  void fuse_set_log_func(fuse_log_func_t func);
  */
 void fuse_log(enum fuse_log_level level, const char *fmt, ...);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* FUSE_LOG_H_ */
diff --git a/tools/virtiofsd/fuse_loop_mt.c b/tools/virtiofsd/fuse_loop_mt.c
index 445e9a0ab0..6fcd47e42c 100644
--- a/tools/virtiofsd/fuse_loop_mt.c
+++ b/tools/virtiofsd/fuse_loop_mt.c
@@ -28,48 +28,6 @@ 
 /* Environment var controlling the thread stack size */
 #define ENVNAME_THREAD_STACK "FUSE_THREAD_STACK"
 
-struct fuse_worker {
-	struct fuse_worker *prev;
-	struct fuse_worker *next;
-	pthread_t thread_id;
-	size_t bufsize;
-
-	// We need to include fuse_buf so that we can properly free
-	// it when a thread is terminated by pthread_cancel().
-	struct fuse_buf fbuf;
-	struct fuse_chan *ch;
-	struct fuse_mt *mt;
-};
-
-struct fuse_mt {
-	pthread_mutex_t lock;
-	int numworker;
-	int numavail;
-	struct fuse_session *se;
-	struct fuse_worker main;
-	sem_t finish;
-	int exit;
-	int error;
-	int clone_fd;
-	int max_idle;
-};
-
-static struct fuse_chan *fuse_chan_new(int fd)
-{
-	struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
-	if (ch == NULL) {
-		fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate channel\n");
-		return NULL;
-	}
-
-	memset(ch, 0, sizeof(*ch));
-	ch->fd = fd;
-	ch->ctr = 1;
-	fuse_mutex_init(&ch->lock);
-
-	return ch;
-}
-
 struct fuse_chan *fuse_chan_get(struct fuse_chan *ch)
 {
 	assert(ch->ctr > 0);
@@ -94,269 +52,3 @@  void fuse_chan_put(struct fuse_chan *ch)
 	} else
 		pthread_mutex_unlock(&ch->lock);
 }
-
-static void list_add_worker(struct fuse_worker *w, struct fuse_worker *next)
-{
-	struct fuse_worker *prev = next->prev;
-	w->next = next;
-	w->prev = prev;
-	prev->next = w;
-	next->prev = w;
-}
-
-static void list_del_worker(struct fuse_worker *w)
-{
-	struct fuse_worker *prev = w->prev;
-	struct fuse_worker *next = w->next;
-	prev->next = next;
-	next->prev = prev;
-}
-
-static int fuse_loop_start_thread(struct fuse_mt *mt);
-
-static void *fuse_do_work(void *data)
-{
-	struct fuse_worker *w = (struct fuse_worker *) data;
-	struct fuse_mt *mt = w->mt;
-
-	while (!fuse_session_exited(mt->se)) {
-		int isforget = 0;
-		int res;
-
-		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-		res = fuse_session_receive_buf_int(mt->se, &w->fbuf, w->ch);
-		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-		if (res == -EINTR)
-			continue;
-		if (res <= 0) {
-			if (res < 0) {
-				fuse_session_exit(mt->se);
-				mt->error = res;
-			}
-			break;
-		}
-
-		pthread_mutex_lock(&mt->lock);
-		if (mt->exit) {
-			pthread_mutex_unlock(&mt->lock);
-			return NULL;
-		}
-
-		/*
-		 * This disgusting hack is needed so that zillions of threads
-		 * are not created on a burst of FORGET messages
-		 */
-		if (!(w->fbuf.flags & FUSE_BUF_IS_FD)) {
-			struct fuse_in_header *in = w->fbuf.mem;
-
-			if (in->opcode == FUSE_FORGET ||
-			    in->opcode == FUSE_BATCH_FORGET)
-				isforget = 1;
-		}
-
-		if (!isforget)
-			mt->numavail--;
-		if (mt->numavail == 0)
-			fuse_loop_start_thread(mt);
-		pthread_mutex_unlock(&mt->lock);
-
-		fuse_session_process_buf_int(mt->se, &w->fbuf, w->ch);
-
-		pthread_mutex_lock(&mt->lock);
-		if (!isforget)
-			mt->numavail++;
-		if (mt->numavail > mt->max_idle) {
-			if (mt->exit) {
-				pthread_mutex_unlock(&mt->lock);
-				return NULL;
-			}
-			list_del_worker(w);
-			mt->numavail--;
-			mt->numworker--;
-			pthread_mutex_unlock(&mt->lock);
-
-			pthread_detach(w->thread_id);
-			free(w->fbuf.mem);
-			fuse_chan_put(w->ch);
-			free(w);
-			return NULL;
-		}
-		pthread_mutex_unlock(&mt->lock);
-	}
-
-	sem_post(&mt->finish);
-
-	return NULL;
-}
-
-int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg)
-{
-	sigset_t oldset;
-	sigset_t newset;
-	int res;
-	pthread_attr_t attr;
-	char *stack_size;
-
-	/* Override default stack size */
-	pthread_attr_init(&attr);
-	stack_size = getenv(ENVNAME_THREAD_STACK);
-	if (stack_size && pthread_attr_setstacksize(&attr, atoi(stack_size)))
-		fuse_log(FUSE_LOG_ERR, "fuse: invalid stack size: %s\n", stack_size);
-
-	/* Disallow signal reception in worker threads */
-	sigemptyset(&newset);
-	sigaddset(&newset, SIGTERM);
-	sigaddset(&newset, SIGINT);
-	sigaddset(&newset, SIGHUP);
-	sigaddset(&newset, SIGQUIT);
-	pthread_sigmask(SIG_BLOCK, &newset, &oldset);
-	res = pthread_create(thread_id, &attr, func, arg);
-	pthread_sigmask(SIG_SETMASK, &oldset, NULL);
-	pthread_attr_destroy(&attr);
-	if (res != 0) {
-		fuse_log(FUSE_LOG_ERR, "fuse: error creating thread: %s\n",
-			strerror(res));
-		return -1;
-	}
-
-	return 0;
-}
-
-static struct fuse_chan *fuse_clone_chan(struct fuse_mt *mt)
-{
-	int res;
-	int clonefd;
-	uint32_t masterfd;
-	struct fuse_chan *newch;
-	const char *devname = "/dev/fuse";
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-	clonefd = open(devname, O_RDWR | O_CLOEXEC);
-	if (clonefd == -1) {
-		fuse_log(FUSE_LOG_ERR, "fuse: failed to open %s: %s\n", devname,
-			strerror(errno));
-		return NULL;
-	}
-	fcntl(clonefd, F_SETFD, FD_CLOEXEC);
-
-	masterfd = mt->se->fd;
-	res = ioctl(clonefd, FUSE_DEV_IOC_CLONE, &masterfd);
-	if (res == -1) {
-		fuse_log(FUSE_LOG_ERR, "fuse: failed to clone device fd: %s\n",
-			strerror(errno));
-		close(clonefd);
-		return NULL;
-	}
-	newch = fuse_chan_new(clonefd);
-	if (newch == NULL)
-		close(clonefd);
-
-	return newch;
-}
-
-static int fuse_loop_start_thread(struct fuse_mt *mt)
-{
-	int res;
-
-	struct fuse_worker *w = malloc(sizeof(struct fuse_worker));
-	if (!w) {
-		fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate worker structure\n");
-		return -1;
-	}
-	memset(w, 0, sizeof(struct fuse_worker));
-	w->fbuf.mem = NULL;
-	w->mt = mt;
-
-	w->ch = NULL;
-	if (mt->clone_fd) {
-		w->ch = fuse_clone_chan(mt);
-		if(!w->ch) {
-			/* Don't attempt this again */
-			fuse_log(FUSE_LOG_ERR, "fuse: trying to continue "
-				"without -o clone_fd.\n");
-			mt->clone_fd = 0;
-		}
-	}
-
-	res = fuse_start_thread(&w->thread_id, fuse_do_work, w);
-	if (res == -1) {
-		fuse_chan_put(w->ch);
-		free(w);
-		return -1;
-	}
-	list_add_worker(w, &mt->main);
-	mt->numavail ++;
-	mt->numworker ++;
-
-	return 0;
-}
-
-static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w)
-{
-	pthread_join(w->thread_id, NULL);
-	pthread_mutex_lock(&mt->lock);
-	list_del_worker(w);
-	pthread_mutex_unlock(&mt->lock);
-	free(w->fbuf.mem);
-	fuse_chan_put(w->ch);
-	free(w);
-}
-
-FUSE_SYMVER(".symver fuse_session_loop_mt_32,fuse_session_loop_mt@@FUSE_3.2");
-int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config)
-{
-	int err;
-	struct fuse_mt mt;
-	struct fuse_worker *w;
-
-	memset(&mt, 0, sizeof(struct fuse_mt));
-	mt.se = se;
-	mt.clone_fd = config->clone_fd;
-	mt.error = 0;
-	mt.numworker = 0;
-	mt.numavail = 0;
-	mt.max_idle = config->max_idle_threads;
-	mt.main.thread_id = pthread_self();
-	mt.main.prev = mt.main.next = &mt.main;
-	sem_init(&mt.finish, 0, 0);
-	fuse_mutex_init(&mt.lock);
-
-	pthread_mutex_lock(&mt.lock);
-	err = fuse_loop_start_thread(&mt);
-	pthread_mutex_unlock(&mt.lock);
-	if (!err) {
-		/* sem_wait() is interruptible */
-		while (!fuse_session_exited(se))
-			sem_wait(&mt.finish);
-
-		pthread_mutex_lock(&mt.lock);
-		for (w = mt.main.next; w != &mt.main; w = w->next)
-			pthread_cancel(w->thread_id);
-		mt.exit = 1;
-		pthread_mutex_unlock(&mt.lock);
-
-		while (mt.main.next != &mt.main)
-			fuse_join_worker(&mt, mt.main.next);
-
-		err = mt.error;
-	}
-
-	pthread_mutex_destroy(&mt.lock);
-	sem_destroy(&mt.finish);
-	if(se->error != 0)
-		err = se->error;
-	fuse_session_reset(se);
-	return err;
-}
-
-int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
-FUSE_SYMVER(".symver fuse_session_loop_mt_31,fuse_session_loop_mt@FUSE_3.0");
-int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd)
-{
-	struct fuse_loop_config config;
-	config.clone_fd = clone_fd;
-	config.max_idle_threads = 10;
-	return fuse_session_loop_mt_32(se, &config);
-}
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index f2d7038e34..5d915666d8 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -28,12 +28,6 @@ 
 #include <assert.h>
 #include <sys/file.h>
 
-#ifndef F_LINUX_SPECIFIC_BASE
-#define F_LINUX_SPECIFIC_BASE       1024
-#endif
-#ifndef F_SETPIPE_SZ
-#define F_SETPIPE_SZ	(F_LINUX_SPECIFIC_BASE + 7)
-#endif
 
 
 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
@@ -184,19 +178,7 @@  static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
 		}
 	}
 
-	ssize_t res = writev(ch ? ch->fd : se->fd,
-			     iov, count);
-	int err = errno;
-
-	if (res == -1) {
-		assert(se != NULL);
-
-		/* ENOENT means the operation was interrupted */
-		if (!fuse_session_exited(se) && err != ENOENT)
-			perror("fuse: writing device");
-		return -err;
-	}
-
+	abort(); /* virtio should have taken it before here */
 	return 0;
 }
 
@@ -480,10 +462,6 @@  static int fuse_send_data_iov_fallback(struct fuse_session *se,
 				       struct fuse_bufvec *buf,
 				       size_t len)
 {
-	struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
-	void *mbuf;
-	int res;
-
 	/* Optimize common case */
 	if (buf->count == 1 && buf->idx == 0 && buf->off == 0 &&
 	    !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
@@ -496,350 +474,10 @@  static int fuse_send_data_iov_fallback(struct fuse_session *se,
 		return fuse_send_msg(se, ch, iov, iov_count);
 	}
 
-	res = posix_memalign(&mbuf, pagesize, len);
-	if (res != 0)
-		return res;
-
-	mem_buf.buf[0].mem = mbuf;
-	res = fuse_buf_copy(&mem_buf, buf, 0);
-	if (res < 0) {
-		free(mbuf);
-		return -res;
-	}
-	len = res;
-
-	iov[iov_count].iov_base = mbuf;
-	iov[iov_count].iov_len = len;
-	iov_count++;
-	res = fuse_send_msg(se, ch, iov, iov_count);
-	free(mbuf);
-
-	return res;
-}
-
-struct fuse_ll_pipe {
-	size_t size;
-	int can_grow;
-	int pipe[2];
-};
-
-static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
-{
-	close(llp->pipe[0]);
-	close(llp->pipe[1]);
-	free(llp);
-}
-
-#ifdef HAVE_SPLICE
-#if !defined(HAVE_PIPE2) || !defined(O_CLOEXEC)
-static int fuse_pipe(int fds[2])
-{
-	int rv = pipe(fds);
-
-	if (rv == -1)
-		return rv;
-
-	if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
-	    fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1 ||
-	    fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
-	    fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
-		close(fds[0]);
-		close(fds[1]);
-		rv = -1;
-	}
-	return rv;
-}
-#else
-static int fuse_pipe(int fds[2])
-{
-	return pipe2(fds, O_CLOEXEC | O_NONBLOCK);
-}
-#endif
-
-static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_session *se)
-{
-	struct fuse_ll_pipe *llp = pthread_getspecific(se->pipe_key);
-	if (llp == NULL) {
-		int res;
-
-		llp = malloc(sizeof(struct fuse_ll_pipe));
-		if (llp == NULL)
-			return NULL;
-
-		res = fuse_pipe(llp->pipe);
-		if (res == -1) {
-			free(llp);
-			return NULL;
-		}
-
-		/*
-		 *the default size is 16 pages on linux
-		 */
-		llp->size = pagesize * 16;
-		llp->can_grow = 1;
-
-		pthread_setspecific(se->pipe_key, llp);
-	}
-
-	return llp;
-}
-#endif
-
-static void fuse_ll_clear_pipe(struct fuse_session *se)
-{
-	struct fuse_ll_pipe *llp = pthread_getspecific(se->pipe_key);
-	if (llp) {
-		pthread_setspecific(se->pipe_key, NULL);
-		fuse_ll_pipe_free(llp);
-	}
-}
-
-#if defined(HAVE_SPLICE) && defined(HAVE_VMSPLICE)
-static int read_back(int fd, char *buf, size_t len)
-{
-	int res;
-
-	res = read(fd, buf, len);
-	if (res == -1) {
-		fuse_log(FUSE_LOG_ERR, "fuse: internal error: failed to read back from pipe: %s\n", strerror(errno));
-		return -EIO;
-	}
-	if (res != len) {
-		fuse_log(FUSE_LOG_ERR, "fuse: internal error: short read back from pipe: %i from %zi\n", res, len);
-		return -EIO;
-	}
+	abort(); /* Will have taken vhost path */
 	return 0;
 }
 
-static int grow_pipe_to_max(int pipefd)
-{
-	int max;
-	int res;
-	int maxfd;
-	char buf[32];
-
-	maxfd = open("/proc/sys/fs/pipe-max-size", O_RDONLY);
-	if (maxfd < 0)
-		return -errno;
-
-	res = read(maxfd, buf, sizeof(buf) - 1);
-	if (res < 0) {
-		int saved_errno;
-
-		saved_errno = errno;
-		close(maxfd);
-		return -saved_errno;
-	}
-	close(maxfd);
-	buf[res] = '\0';
-
-	max = atoi(buf);
-	res = fcntl(pipefd, F_SETPIPE_SZ, max);
-	if (res < 0)
-		return -errno;
-	return max;
-}
-
-static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
-			       struct iovec *iov, int iov_count,
-			       struct fuse_bufvec *buf, unsigned int flags)
-{
-	int res;
-	size_t len = fuse_buf_size(buf);
-	struct fuse_out_header *out = iov[0].iov_base;
-	struct fuse_ll_pipe *llp;
-	int splice_flags;
-	size_t pipesize;
-	size_t total_fd_size;
-	size_t idx;
-	size_t headerlen;
-	struct fuse_bufvec pipe_buf = FUSE_BUFVEC_INIT(len);
-
-	if (se->broken_splice_nonblock)
-		goto fallback;
-
-	if (flags & FUSE_BUF_NO_SPLICE)
-		goto fallback;
-
-	total_fd_size = 0;
-	for (idx = buf->idx; idx < buf->count; idx++) {
-		if (buf->buf[idx].flags & FUSE_BUF_IS_FD) {
-			total_fd_size = buf->buf[idx].size;
-			if (idx == buf->idx)
-				total_fd_size -= buf->off;
-		}
-	}
-	if (total_fd_size < 2 * pagesize)
-		goto fallback;
-
-	if (se->conn.proto_minor < 14 ||
-	    !(se->conn.want & FUSE_CAP_SPLICE_WRITE))
-		goto fallback;
-
-	llp = fuse_ll_get_pipe(se);
-	if (llp == NULL)
-		goto fallback;
-
-
-	headerlen = iov_length(iov, iov_count);
-
-	out->len = headerlen + len;
-
-	/*
-	 * Heuristic for the required pipe size, does not work if the
-	 * source contains less than page size fragments
-	 */
-	pipesize = pagesize * (iov_count + buf->count + 1) + out->len;
-
-	if (llp->size < pipesize) {
-		if (llp->can_grow) {
-			res = fcntl(llp->pipe[0], F_SETPIPE_SZ, pipesize);
-			if (res == -1) {
-				res = grow_pipe_to_max(llp->pipe[0]);
-				if (res > 0)
-					llp->size = res;
-				llp->can_grow = 0;
-				goto fallback;
-			}
-			llp->size = res;
-		}
-		if (llp->size < pipesize)
-			goto fallback;
-	}
-
-
-	res = vmsplice(llp->pipe[1], iov, iov_count, SPLICE_F_NONBLOCK);
-	if (res == -1)
-		goto fallback;
-
-	if (res != headerlen) {
-		res = -EIO;
-		fuse_log(FUSE_LOG_ERR, "fuse: short vmsplice to pipe: %u/%zu\n", res,
-			headerlen);
-		goto clear_pipe;
-	}
-
-	pipe_buf.buf[0].flags = FUSE_BUF_IS_FD;
-	pipe_buf.buf[0].fd = llp->pipe[1];
-
-	res = fuse_buf_copy(&pipe_buf, buf,
-			    FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK);
-	if (res < 0) {
-		if (res == -EAGAIN || res == -EINVAL) {
-			/*
-			 * Should only get EAGAIN on kernels with
-			 * broken SPLICE_F_NONBLOCK support (<=
-			 * 2.6.35) where this error or a short read is
-			 * returned even if the pipe itself is not
-			 * full
-			 *
-			 * EINVAL might mean that splice can't handle
-			 * this combination of input and output.
-			 */
-			if (res == -EAGAIN)
-				se->broken_splice_nonblock = 1;
-
-			pthread_setspecific(se->pipe_key, NULL);
-			fuse_ll_pipe_free(llp);
-			goto fallback;
-		}
-		res = -res;
-		goto clear_pipe;
-	}
-
-	if (res != 0 && res < len) {
-		struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
-		void *mbuf;
-		size_t now_len = res;
-		/*
-		 * For regular files a short count is either
-		 *  1) due to EOF, or
-		 *  2) because of broken SPLICE_F_NONBLOCK (see above)
-		 *
-		 * For other inputs it's possible that we overflowed
-		 * the pipe because of small buffer fragments.
-		 */
-
-		res = posix_memalign(&mbuf, pagesize, len);
-		if (res != 0)
-			goto clear_pipe;
-
-		mem_buf.buf[0].mem = mbuf;
-		mem_buf.off = now_len;
-		res = fuse_buf_copy(&mem_buf, buf, 0);
-		if (res > 0) {
-			char *tmpbuf;
-			size_t extra_len = res;
-			/*
-			 * Trickiest case: got more data.  Need to get
-			 * back the data from the pipe and then fall
-			 * back to regular write.
-			 */
-			tmpbuf = malloc(headerlen);
-			if (tmpbuf == NULL) {
-				free(mbuf);
-				res = ENOMEM;
-				goto clear_pipe;
-			}
-			res = read_back(llp->pipe[0], tmpbuf, headerlen);
-			free(tmpbuf);
-			if (res != 0) {
-				free(mbuf);
-				goto clear_pipe;
-			}
-			res = read_back(llp->pipe[0], mbuf, now_len);
-			if (res != 0) {
-				free(mbuf);
-				goto clear_pipe;
-			}
-			len = now_len + extra_len;
-			iov[iov_count].iov_base = mbuf;
-			iov[iov_count].iov_len = len;
-			iov_count++;
-			res = fuse_send_msg(se, ch, iov, iov_count);
-			free(mbuf);
-			return res;
-		}
-		free(mbuf);
-		res = now_len;
-	}
-	len = res;
-	out->len = headerlen + len;
-
-	if (se->debug) {
-		fuse_log(FUSE_LOG_DEBUG,
-			"   unique: %llu, success, outsize: %i (splice)\n",
-			(unsigned long long) out->unique, out->len);
-	}
-
-	splice_flags = 0;
-	if ((flags & FUSE_BUF_SPLICE_MOVE) &&
-	    (se->conn.want & FUSE_CAP_SPLICE_MOVE))
-		splice_flags |= SPLICE_F_MOVE;
-
-	res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd,
-		     NULL, out->len, splice_flags);
-	if (res == -1) {
-		res = -errno;
-		perror("fuse: splice from pipe");
-		goto clear_pipe;
-	}
-	if (res != out->len) {
-		res = -EIO;
-		fuse_log(FUSE_LOG_ERR, "fuse: short splice from pipe: %u/%u\n",
-			res, out->len);
-		goto clear_pipe;
-	}
-	return 0;
-
-clear_pipe:
-	fuse_ll_clear_pipe(se);
-	return res;
-
-fallback:
-	return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
-}
-#else
 static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
 			       struct iovec *iov, int iov_count,
 			       struct fuse_bufvec *buf, unsigned int flags)
@@ -849,7 +487,6 @@  static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
 
 	return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
 }
-#endif
 
 int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
 		    enum fuse_buf_copy_flags flags)
@@ -1408,16 +1045,11 @@  static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *inarg,
 	if (bufv.buf[0].size < arg->size) {
 		fuse_log(FUSE_LOG_ERR, "fuse: do_write_buf: buffer size too small\n");
 		fuse_reply_err(req, EIO);
-		goto out;
+		return;
 	}
 	bufv.buf[0].size = arg->size;
 
 	se->op.write_buf(req, nodeid, &bufv, arg->offset, &fi);
-
-out:
-	/* Need to reset the pipe if ->write_buf() didn't consume all data */
-	if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
-		fuse_ll_clear_pipe(se);
 }
 
 static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
@@ -2038,17 +1670,6 @@  static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		return;
 	}
 
-	unsigned max_read_mo = get_max_read(se->mo);
-	if (se->conn.max_read != max_read_mo) {
-		fuse_log(FUSE_LOG_ERR, "fuse: error: init() and fuse_session_new() "
-			"requested different maximum read size (%u vs %u)\n",
-			se->conn.max_read, max_read_mo);
-		fuse_reply_err(req, EPROTO);
-		se->error = -EPROTO;
-		fuse_session_exit(se);
-		return;
-	}
-
 	if (se->conn.max_write < bufsize - FUSE_BUFFER_HEADER_SIZE) {
 		se->bufsize = se->conn.max_write + FUSE_BUFFER_HEADER_SIZE;
 	}
@@ -2364,8 +1985,6 @@  static void fuse_ll_retrieve_reply(struct fuse_notify_req *nreq,
 	}
 out:
 	free(rreq);
-	if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
-		fuse_ll_clear_pipe(se);
 }
 
 int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino,
@@ -2509,21 +2128,6 @@  static const char *opname(enum fuse_opcode opcode)
 		return fuse_ll_ops[opcode].name;
 }
 
-static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst,
-				  struct fuse_bufvec *src)
-{
-	ssize_t res = fuse_buf_copy(dst, src, 0);
-	if (res < 0) {
-		fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: %s\n", strerror(-res));
-		return res;
-	}
-	if ((size_t)res < fuse_buf_size(dst)) {
-		fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: short read\n");
-		return -1;
-	}
-	return 0;
-}
-
 void fuse_session_process_buf(struct fuse_session *se,
 			      const struct fuse_buf *buf)
 {
@@ -2533,36 +2137,12 @@  void fuse_session_process_buf(struct fuse_session *se,
 void fuse_session_process_buf_int(struct fuse_session *se,
 				  const struct fuse_buf *buf, struct fuse_chan *ch)
 {
-	const size_t write_header_size = sizeof(struct fuse_in_header) +
-		sizeof(struct fuse_write_in);
-	struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 };
-	struct fuse_bufvec tmpbuf = FUSE_BUFVEC_INIT(write_header_size);
 	struct fuse_in_header *in;
 	const void *inarg;
 	struct fuse_req *req;
-	void *mbuf = NULL;
 	int err;
-	int res;
 
-	if (buf->flags & FUSE_BUF_IS_FD) {
-		if (buf->size < tmpbuf.buf[0].size)
-			tmpbuf.buf[0].size = buf->size;
-
-		mbuf = malloc(tmpbuf.buf[0].size);
-		if (mbuf == NULL) {
-			fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate header\n");
-			goto clear_pipe;
-		}
-		tmpbuf.buf[0].mem = mbuf;
-
-		res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
-		if (res < 0)
-			goto clear_pipe;
-
-		in = mbuf;
-	} else {
-		in = buf->mem;
-	}
+	in = buf->mem;
 
 	if (se->debug) {
 		fuse_log(FUSE_LOG_DEBUG,
@@ -2584,7 +2164,7 @@  void fuse_session_process_buf_int(struct fuse_session *se,
 		};
 
 		fuse_send_msg(se, ch, &iov, 1);
-		goto clear_pipe;
+		return;
 	}
 
 	req->unique = in->unique;
@@ -2627,28 +2207,6 @@  void fuse_session_process_buf_int(struct fuse_session *se,
 			fuse_reply_err(intr, EAGAIN);
 	}
 
-	if ((buf->flags & FUSE_BUF_IS_FD) && write_header_size < buf->size &&
-	    (in->opcode != FUSE_WRITE || !se->op.write_buf) &&
-	    in->opcode != FUSE_NOTIFY_REPLY) {
-		void *newmbuf;
-
-		err = ENOMEM;
-		newmbuf = realloc(mbuf, buf->size);
-		if (newmbuf == NULL)
-			goto reply_err;
-		mbuf = newmbuf;
-
-		tmpbuf = FUSE_BUFVEC_INIT(buf->size - write_header_size);
-		tmpbuf.buf[0].mem = (char *)mbuf + write_header_size;
-
-		res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
-		err = -res;
-		if (res < 0)
-			goto reply_err;
-
-		in = mbuf;
-	}
-
 	inarg = (void *) &in[1];
 	if (in->opcode == FUSE_WRITE && se->op.write_buf)
 		do_write_buf(req, in->nodeid, inarg, buf);
@@ -2657,16 +2215,10 @@  void fuse_session_process_buf_int(struct fuse_session *se,
 	else
 		fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
 
-out_free:
-	free(mbuf);
 	return;
 
 reply_err:
 	fuse_reply_err(req, err);
-clear_pipe:
-	if (buf->flags & FUSE_BUF_IS_FD)
-		fuse_ll_clear_pipe(se);
-	goto out_free;
 }
 
 #define LL_OPTION(n,o,v) \
@@ -2699,197 +2251,23 @@  void fuse_lowlevel_help(void)
 
 void fuse_session_destroy(struct fuse_session *se)
 {
-	struct fuse_ll_pipe *llp;
-
 	if (se->got_init && !se->got_destroy) {
 		if (se->op.destroy)
 			se->op.destroy(se->userdata);
 	}
-	llp = pthread_getspecific(se->pipe_key);
-	if (llp != NULL)
-		fuse_ll_pipe_free(llp);
-	pthread_key_delete(se->pipe_key);
 	pthread_mutex_destroy(&se->lock);
 	free(se->cuse_data);
 	if (se->fd != -1)
 		close(se->fd);
-	destroy_mount_opts(se->mo);
 	free(se);
 }
 
 
-static void fuse_ll_pipe_destructor(void *data)
-{
-	struct fuse_ll_pipe *llp = data;
-	fuse_ll_pipe_free(llp);
-}
-
-int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf)
-{
-	return fuse_session_receive_buf_int(se, buf, NULL);
-}
-
-int fuse_session_receive_buf_int(struct fuse_session *se, struct fuse_buf *buf,
-				 struct fuse_chan *ch)
-{
-	int err;
-	ssize_t res;
-#ifdef HAVE_SPLICE
-	size_t bufsize = se->bufsize;
-	struct fuse_ll_pipe *llp;
-	struct fuse_buf tmpbuf;
-
-	if (se->conn.proto_minor < 14 || !(se->conn.want & FUSE_CAP_SPLICE_READ))
-		goto fallback;
-
-	llp = fuse_ll_get_pipe(se);
-	if (llp == NULL)
-		goto fallback;
-
-	if (llp->size < bufsize) {
-		if (llp->can_grow) {
-			res = fcntl(llp->pipe[0], F_SETPIPE_SZ, bufsize);
-			if (res == -1) {
-				llp->can_grow = 0;
-				res = grow_pipe_to_max(llp->pipe[0]);
-				if (res > 0)
-					llp->size = res;
-				goto fallback;
-			}
-			llp->size = res;
-		}
-		if (llp->size < bufsize)
-			goto fallback;
-	}
-
-	res = splice(ch ? ch->fd : se->fd,
-		     NULL, llp->pipe[1], NULL, bufsize, 0);
-	err = errno;
-
-	if (fuse_session_exited(se))
-		return 0;
-
-	if (res == -1) {
-		if (err == ENODEV) {
-			/* Filesystem was unmounted, or connection was aborted
-			   via /sys/fs/fuse/connections */
-			fuse_session_exit(se);
-			return 0;
-		}
-		if (err != EINTR && err != EAGAIN)
-			perror("fuse: splice from device");
-		return -err;
-	}
-
-	if (res < sizeof(struct fuse_in_header)) {
-		fuse_log(FUSE_LOG_ERR, "short splice from fuse device\n");
-		return -EIO;
-	}
-
-	tmpbuf = (struct fuse_buf) {
-		.size = res,
-		.flags = FUSE_BUF_IS_FD,
-		.fd = llp->pipe[0],
-	};
-
-	/*
-	 * Don't bother with zero copy for small requests.
-	 * fuse_loop_mt() needs to check for FORGET so this more than
-	 * just an optimization.
-	 */
-	if (res < sizeof(struct fuse_in_header) +
-	    sizeof(struct fuse_write_in) + pagesize) {
-		struct fuse_bufvec src = { .buf[0] = tmpbuf, .count = 1 };
-		struct fuse_bufvec dst = { .count = 1 };
-
-		if (!buf->mem) {
-			buf->mem = malloc(se->bufsize);
-			if (!buf->mem) {
-				fuse_log(FUSE_LOG_ERR,
-					"fuse: failed to allocate read buffer\n");
-				return -ENOMEM;
-			}
-		}
-		buf->size = se->bufsize;
-		buf->flags = 0;
-		dst.buf[0] = *buf;
-
-		res = fuse_buf_copy(&dst, &src, 0);
-		if (res < 0) {
-			fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: %s\n",
-				strerror(-res));
-			fuse_ll_clear_pipe(se);
-			return res;
-		}
-		if (res < tmpbuf.size) {
-			fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: short read\n");
-			fuse_ll_clear_pipe(se);
-			return -EIO;
-		}
-		assert(res == tmpbuf.size);
-
-	} else {
-		/* Don't overwrite buf->mem, as that would cause a leak */
-		buf->fd = tmpbuf.fd;
-		buf->flags = tmpbuf.flags;
-	}
-	buf->size = tmpbuf.size;
-
-	return res;
-
-fallback:
-#endif
-	if (!buf->mem) {
-		buf->mem = malloc(se->bufsize);
-		if (!buf->mem) {
-			fuse_log(FUSE_LOG_ERR,
-				"fuse: failed to allocate read buffer\n");
-			return -ENOMEM;
-		}
-	}
-
-restart:
-	res = read(ch ? ch->fd : se->fd, buf->mem, se->bufsize);
-	err = errno;
-
-	if (fuse_session_exited(se))
-		return 0;
-	if (res == -1) {
-		/* ENOENT means the operation was interrupted, it's safe
-		   to restart */
-		if (err == ENOENT)
-			goto restart;
-
-		if (err == ENODEV) {
-			/* Filesystem was unmounted, or connection was aborted
-			   via /sys/fs/fuse/connections */
-			fuse_session_exit(se);
-			return 0;
-		}
-		/* Errors occurring during normal operation: EINTR (read
-		   interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
-		   umounted) */
-		if (err != EINTR && err != EAGAIN)
-			perror("fuse: reading device");
-		return -err;
-	}
-	if ((size_t) res < sizeof(struct fuse_in_header)) {
-		fuse_log(FUSE_LOG_ERR, "short read on fuse device\n");
-		return -EIO;
-	}
-
-	buf->size = res;
-
-	return res;
-}
-
 struct fuse_session *fuse_session_new(struct fuse_args *args,
 				      const struct fuse_lowlevel_ops *op,
 				      size_t op_size, void *userdata)
 {
-	int err;
 	struct fuse_session *se;
-	struct mount_opts *mo;
 
 	if (sizeof(struct fuse_lowlevel_ops) < op_size) {
 		fuse_log(FUSE_LOG_ERR, "fuse: warning: library too old, some operations may not work\n");
@@ -2923,10 +2301,6 @@  struct fuse_session *fuse_session_new(struct fuse_args *args,
 		if(fuse_opt_add_arg(args, "-oallow_other") == -1)
 			goto out2;
 	}
-	mo = parse_mount_opts(args);
-	if (mo == NULL)
-		goto out3;
-
 	if(args->argc == 1 &&
 	   args->argv[0][0] == '-') {
 		fuse_log(FUSE_LOG_ERR, "fuse: warning: argv[0] looks like an option, but "
@@ -2952,26 +2326,14 @@  struct fuse_session *fuse_session_new(struct fuse_args *args,
 	se->notify_ctr = 1;
 	fuse_mutex_init(&se->lock);
 
-	err = pthread_key_create(&se->pipe_key, fuse_ll_pipe_destructor);
-	if (err) {
-		fuse_log(FUSE_LOG_ERR, "fuse: failed to create thread specific key: %s\n",
-			strerror(err));
-		goto out5;
-	}
-
 	memcpy(&se->op, op, op_size);
 	se->owner = getuid();
 	se->userdata = userdata;
 
-	se->mo = mo;
 	return se;
 
-out5:
-	pthread_mutex_destroy(&se->lock);
 out4:
 	fuse_opt_free_args(args);
-out3:
-	free(mo);
 out2:
 	free(se);
 out1:
@@ -3035,11 +2397,6 @@  int fuse_session_fd(struct fuse_session *se)
 
 void fuse_session_unmount(struct fuse_session *se)
 {
-	if (se->mountpoint != NULL) {
-		fuse_kern_unmount(se->mountpoint, se->fd);
-		free(se->mountpoint);
-		se->mountpoint = NULL;
-	}
 }
 
 #ifdef linux
diff --git a/tools/virtiofsd/fuse_lowlevel.h b/tools/virtiofsd/fuse_lowlevel.h
index 18c6363f07..7aa7bad5b2 100644
--- a/tools/virtiofsd/fuse_lowlevel.h
+++ b/tools/virtiofsd/fuse_lowlevel.h
@@ -31,10 +31,6 @@ 
 #include <sys/statvfs.h>
 #include <sys/uio.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* ----------------------------------------------------------- *
  * Miscellaneous definitions				       *
  * ----------------------------------------------------------- */
@@ -2082,8 +2078,4 @@  void fuse_session_process_buf(struct fuse_session *se,
  */
 int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* FUSE_LOWLEVEL_H_ */
diff --git a/tools/virtiofsd/fuse_opt.h b/tools/virtiofsd/fuse_opt.h
index d8573e74fd..69102555be 100644
--- a/tools/virtiofsd/fuse_opt.h
+++ b/tools/virtiofsd/fuse_opt.h
@@ -14,10 +14,6 @@ 
  * This file defines the option parsing interface of FUSE
  */
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * Option description
  *
@@ -264,8 +260,4 @@  void fuse_opt_free_args(struct fuse_args *args);
  */
 int fuse_opt_match(const struct fuse_opt opts[], const char *opt);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* FUSE_OPT_H_ */
diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c
index 64ff7ad6d5..511f981ce6 100644
--- a/tools/virtiofsd/helper.c
+++ b/tools/virtiofsd/helper.c
@@ -44,10 +44,8 @@  static const struct fuse_opt fuse_helper_opts[] = {
 	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
@@ -171,34 +169,6 @@  static int fuse_helper_opt_proc(void *data, const char *arg, int key,
 	}
 }
 
-/* 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)
 {
@@ -210,14 +180,6 @@  int fuse_parse_cmdline(struct fuse_args *args,
 			   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;
 }
 
@@ -276,88 +238,6 @@  int fuse_daemonize(int foreground)
 	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)
 {
@@ -420,21 +300,3 @@  struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args)
 	}
 	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;
-}
diff --git a/tools/virtiofsd/passthrough_helpers.h b/tools/virtiofsd/passthrough_helpers.h
index 6b77c33600..7c5f561fbc 100644
--- a/tools/virtiofsd/passthrough_helpers.h
+++ b/tools/virtiofsd/passthrough_helpers.h
@@ -42,32 +42,6 @@  static int mknod_wrapper(int dirfd, const char *path, const char *link,
 		res = symlinkat(link, dirfd, path);
 	} else if (S_ISFIFO(mode)) {
 		res = mkfifoat(dirfd, path, mode);
-#ifdef __FreeBSD__
-	} else if (S_ISSOCK(mode)) {
-		struct sockaddr_un su;
-		int fd;
-
-		if (strlen(path) >= sizeof(su.sun_path)) {
-			errno = ENAMETOOLONG;
-			return -1;
-		}
-		fd = socket(AF_UNIX, SOCK_STREAM, 0);
-		if (fd >= 0) {
-			/*
-			 * We must bind the socket to the underlying file
-			 * system to create the socket file, even though
-			 * we'll never listen on this socket.
-			 */
-			su.sun_family = AF_UNIX;
-			strncpy(su.sun_path, path, sizeof(su.sun_path));
-			res = bindat(dirfd, fd, (struct sockaddr*)&su,
-				sizeof(su));
-			if (res == 0)
-				close(fd);
-		} else {
-			res = -1;
-		}
-#endif
 	} else {
 		res = mknodat(dirfd, path, mode, rdev);
 	}