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>