Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Apr 2019 19:47:43 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r346763 - projects/fuse2/sys/fs/fuse
Message-ID:  <201904261947.x3QJlhn7087703@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Fri Apr 26 19:47:43 2019
New Revision: 346763
URL: https://svnweb.freebsd.org/changeset/base/346763

Log:
  fusefs: fix a deadlock in VOP_PUTPAGES
  
  As of r346162 fuse now invalidates the cache during writes.  But it can't do
  that when writing from VOP_PUTPAGES, because the write is coming _from_ the
  cache.  Trying to invalidate the cache in that situation causes a deadlock
  in vm_object_page_remove, because the pages in question have already been
  busied by the same thread.
  
  PR:		235774
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_io.c
  projects/fuse2/sys/fs/fuse/fuse_io.h
  projects/fuse2/sys/fs/fuse/fuse_vnops.c

Modified: projects/fuse2/sys/fs/fuse/fuse_io.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_io.c	Fri Apr 26 19:02:21 2019	(r346762)
+++ projects/fuse2/sys/fs/fuse/fuse_io.c	Fri Apr 26 19:47:43 2019	(r346763)
@@ -122,7 +122,7 @@ fuse_write_biobackend(struct vnode *vp, struct uio *ui
 SDT_PROBE_DEFINE5(fusefs, , io, io_dispatch, "struct vnode*", "struct uio*",
 		"int", "struct ucred*", "struct fuse_filehandle*");
 int
-fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
+fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag, bool pages,
     struct ucred *cred, pid_t pid)
 {
 	struct fuse_filehandle *fufh;
@@ -172,13 +172,20 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, in
 		 * cached.
 		 */
 		if (directio || fuse_data_cache_mode == FUSE_CACHE_WT) {
+			const int iosize = fuse_iosize(vp);
 			off_t start, end;
 
 			SDT_PROBE2(fusefs, , io, trace, 1,
 				"direct write of vnode");
 			start = uio->uio_offset;
 			end = start + uio->uio_resid;
-			v_inval_buf_range(vp, start, end, fuse_iosize(vp));
+			/* 
+			 * Invalidate the write cache unless we're coming from
+			 * VOP_PUTPAGES, in which case we're writing _from_ the
+			 * write cache
+			 */
+			if (!pages )
+				v_inval_buf_range(vp, start, end, iosize);
 			err = fuse_write_directbackend(vp, uio, cred, fufh,
 				ioflag);
 		} else {

Modified: projects/fuse2/sys/fs/fuse/fuse_io.h
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_io.h	Fri Apr 26 19:02:21 2019	(r346762)
+++ projects/fuse2/sys/fs/fuse/fuse_io.h	Fri Apr 26 19:47:43 2019	(r346763)
@@ -60,7 +60,7 @@
 #ifndef _FUSE_IO_H_
 #define _FUSE_IO_H_
 
-int fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
+int fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag, bool pages,
     struct ucred *cred, pid_t pid);
 int fuse_io_strategy(struct vnode *vp, struct buf *bp);
 int fuse_io_flushbuf(struct vnode *vp, int waitfor, struct thread *td);

Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_vnops.c	Fri Apr 26 19:02:21 2019	(r346762)
+++ projects/fuse2/sys/fs/fuse/fuse_vnops.c	Fri Apr 26 19:47:43 2019	(r346763)
@@ -1222,7 +1222,7 @@ fuse_vnop_read(struct vop_read_args *ap)
 		ioflag |= IO_DIRECT;
 	}
 
-	return fuse_io_dispatch(vp, uio, ioflag, cred, pid);
+	return fuse_io_dispatch(vp, uio, ioflag, false, cred, pid);
 }
 
 /*
@@ -1729,7 +1729,7 @@ fuse_vnop_write(struct vop_write_args *ap)
 		ioflag |= IO_DIRECT;
 	}
 
-	return fuse_io_dispatch(vp, uio, ioflag, cred, pid);
+	return fuse_io_dispatch(vp, uio, ioflag, false, cred, pid);
 }
 
 SDT_PROBE_DEFINE1(fusefs, , vnops, vnop_getpages_error, "int");
@@ -1803,7 +1803,7 @@ fuse_vnop_getpages(struct vop_getpages_args *ap)
 	uio.uio_rw = UIO_READ;
 	uio.uio_td = td;
 
-	error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred, pid);
+	error = fuse_io_dispatch(vp, &uio, IO_DIRECT, true, cred, pid);
 	pmap_qremove(kva, npages);
 
 	uma_zfree(fuse_pbuf_zone, bp);
@@ -1936,7 +1936,7 @@ fuse_vnop_putpages(struct vop_putpages_args *ap)
 	uio.uio_rw = UIO_WRITE;
 	uio.uio_td = td;
 
-	error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred, pid);
+	error = fuse_io_dispatch(vp, &uio, IO_DIRECT, true, cred, pid);
 
 	pmap_qremove(kva, npages);
 	uma_zfree(fuse_pbuf_zone, bp);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904261947.x3QJlhn7087703>