From nobody Mon Jan 03 03:03:35 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id C98631923289; Mon, 3 Jan 2022 03:03:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4JS0tv3vs3z3FMc; Mon, 3 Jan 2022 03:03:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 65C7C1DE9A; Mon, 3 Jan 2022 03:03:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 20333ZSt099521; Mon, 3 Jan 2022 03:03:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 20333ZOs099520; Mon, 3 Jan 2022 03:03:35 GMT (envelope-from git) Date: Mon, 3 Jan 2022 03:03:35 GMT Message-Id: <202201030303.20333ZOs099520@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alan Somers Subject: git: d056bc6f401a - stable/13 - fusefs: inline fuse_io_dispatch List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: asomers X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: d056bc6f401a01115b6f5fed532c5ce58c0b0414 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1641179015; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dvbZU1fR38JKdj1daYKwbdOHAuETfQGgyVLghmD1Qj0=; b=fsTWW4ALDSA4FDmZE82eVR7TYd9n0CHB9dWaYjiioS/EEePpBELKXoLdfnvMxjmlbUhgoz BE9z9BawUODyip1rNTjAkLOXKGn4t07y8RhO1Sa6W3yZYi4YowFEqi1wzjVHOo2HTAfz7B lAe28RxqATD55RIpp1ANPURFAiDMqhSr5mKR7lfr6Y7Zrvfdt1ke3zig0SDDM+yK8opChV KL+7/xwxxCatcGZW94+44BnxzAPYVU/5rKtGhj6yLNqVtf4a/GqZZp6QwcNhaIXTp4Fs3M cBv2Jz/j/saEeg8KH1Uk/C6yNBODOyKRmKRewgeg+SLNAUUr3t4e6aA2tJ8EhA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1641179015; a=rsa-sha256; cv=none; b=N3TTGfRFOUOE6fqaOHvPeItr9ZsdHqtc74TqNt9odul8TUp/gRPZeoFInZPoPRRgAptYt+ GhVlWJ06gcIi7ZYx2/GVsLLIoPCFyvAZCmCBJyi/DkH0utjckSMjybQZbI9XLbGdIzc6HX NTShkjZ9VaSuG5TPzVVvuoXNaaScWpbXgE7pzDMEJe0rXvmCMz7LeK+ABpAMDb0ZnyyVUw k2oWw2qsZH5pxI29SRjeIShTbRbA9/YwB2pyt0KIPDXGemyu4PzH9r0981a8IUMQxAztWY 8kKmcxmHh+zXdDEWft8AO9WCMymVGpq8FQfy653Kv67GJ1oxsK0kRtPiV5pa+g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=d056bc6f401a01115b6f5fed532c5ce58c0b0414 commit d056bc6f401a01115b6f5fed532c5ce58c0b0414 Author: Alan Somers AuthorDate: 2021-12-05 21:25:17 +0000 Commit: Alan Somers CommitDate: 2022-01-03 02:54:39 +0000 fusefs: inline fuse_io_dispatch This function was always confusing, because it created an H-shaped callgraph: two functions called in and left via different paths based on which which called. (cherry picked from commit dc433e1530af26b0430d66c06c342889e9609590) --- sys/fs/fuse/fuse_io.c | 181 ++--------------------------------------------- sys/fs/fuse/fuse_io.h | 11 ++- sys/fs/fuse/fuse_vnops.c | 167 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 178 insertions(+), 181 deletions(-) diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c index f85d17517ee0..609d08f9e3d5 100644 --- a/sys/fs/fuse/fuse_io.c +++ b/sys/fs/fuse/fuse_io.c @@ -120,184 +120,11 @@ SDT_PROVIDER_DECLARE(fusefs); */ SDT_PROBE_DEFINE2(fusefs, , io, trace, "int", "char*"); -static int -fuse_inval_buf_range(struct vnode *vp, off_t filesize, off_t start, off_t end); -static int -fuse_read_directbackend(struct vnode *vp, struct uio *uio, - struct ucred *cred, struct fuse_filehandle *fufh); -static int -fuse_read_biobackend(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred, struct fuse_filehandle *fufh, pid_t pid); -static int -fuse_write_directbackend(struct vnode *vp, struct uio *uio, - struct ucred *cred, struct fuse_filehandle *fufh, off_t filesize, - int ioflag, bool pages); -static int -fuse_write_biobackend(struct vnode *vp, struct uio *uio, - struct ucred *cred, struct fuse_filehandle *fufh, int ioflag, pid_t pid); - -/* Invalidate a range of cached data, whether dirty of not */ -static int -fuse_inval_buf_range(struct vnode *vp, off_t filesize, off_t start, off_t end) -{ - struct buf *bp; - daddr_t left_lbn, end_lbn, right_lbn; - off_t new_filesize; - int iosize, left_on, right_on, right_blksize; - - iosize = fuse_iosize(vp); - left_lbn = start / iosize; - end_lbn = howmany(end, iosize); - left_on = start & (iosize - 1); - if (left_on != 0) { - bp = getblk(vp, left_lbn, iosize, PCATCH, 0, 0); - if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyend >= left_on) { - /* - * Flush the dirty buffer, because we don't have a - * byte-granular way to record which parts of the - * buffer are valid. - */ - bwrite(bp); - if (bp->b_error) - return (bp->b_error); - } else { - brelse(bp); - } - } - right_on = end & (iosize - 1); - if (right_on != 0) { - right_lbn = end / iosize; - new_filesize = MAX(filesize, end); - right_blksize = MIN(iosize, new_filesize - iosize * right_lbn); - bp = getblk(vp, right_lbn, right_blksize, PCATCH, 0, 0); - if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyoff < right_on) { - /* - * Flush the dirty buffer, because we don't have a - * byte-granular way to record which parts of the - * buffer are valid. - */ - bwrite(bp); - if (bp->b_error) - return (bp->b_error); - } else { - brelse(bp); - } - } - - v_inval_buf_range(vp, left_lbn, end_lbn, iosize); - return (0); -} - -SDT_PROBE_DEFINE5(fusefs, , io, io_dispatch, "struct vnode*", "struct uio*", - "int", "struct ucred*", "struct fuse_filehandle*"); -SDT_PROBE_DEFINE4(fusefs, , io, io_dispatch_filehandles_closed, "struct vnode*", - "struct uio*", "int", "struct ucred*"); -int -fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred, pid_t pid) -{ - struct fuse_filehandle *fufh; - int err, directio; - int fflag; - bool closefufh = false; - - MPASS(vp->v_type == VREG || vp->v_type == VDIR); - - fflag = (uio->uio_rw == UIO_READ) ? FREAD : FWRITE; - err = fuse_filehandle_getrw(vp, fflag, &fufh, cred, pid); - if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) { - /* - * nfsd will do I/O without first doing VOP_OPEN. We - * must implicitly open the file here - */ - err = fuse_filehandle_open(vp, fflag, &fufh, curthread, cred); - closefufh = true; - } - else if (err) { - SDT_PROBE4(fusefs, , io, io_dispatch_filehandles_closed, - vp, uio, ioflag, cred); - printf("FUSE: io dispatch: filehandles are closed\n"); - return err; - } - if (err) - goto out; - SDT_PROBE5(fusefs, , io, io_dispatch, vp, uio, ioflag, cred, fufh); - - /* - * Ideally, when the daemon asks for direct io at open time, the - * standard file flag should be set according to this, so that would - * just change the default mode, which later on could be changed via - * fcntl(2). - * But this doesn't work, the O_DIRECT flag gets cleared at some point - * (don't know where). So to make any use of the Fuse direct_io option, - * we hardwire it into the file's private data (similarly to Linux, - * btw.). - */ - directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp)); - - switch (uio->uio_rw) { - case UIO_READ: - fuse_vnode_update(vp, FN_ATIMECHANGE); - if (directio) { - SDT_PROBE2(fusefs, , io, trace, 1, - "direct read of vnode"); - err = fuse_read_directbackend(vp, uio, cred, fufh); - } else { - SDT_PROBE2(fusefs, , io, trace, 1, - "buffered read of vnode"); - err = fuse_read_biobackend(vp, uio, ioflag, cred, fufh, - pid); - } - break; - case UIO_WRITE: - fuse_vnode_update(vp, FN_MTIMECHANGE | FN_CTIMECHANGE); - if (directio) { - off_t start, end, filesize; - bool pages = (ioflag & IO_VMIO) != 0; - - SDT_PROBE2(fusefs, , io, trace, 1, - "direct write of vnode"); - - err = fuse_vnode_size(vp, &filesize, cred, curthread); - if (err) - goto out; - - start = uio->uio_offset; - end = start + uio->uio_resid; - if (!pages) { - err = fuse_inval_buf_range(vp, filesize, start, - end); - if (err) - return (err); - } - err = fuse_write_directbackend(vp, uio, cred, fufh, - filesize, ioflag, pages); - } else { - SDT_PROBE2(fusefs, , io, trace, 1, - "buffered write of vnode"); - if (!fsess_opt_writeback(vnode_mount(vp))) - ioflag |= IO_SYNC; - err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag, - pid); - } - fuse_internal_clear_suid_on_write(vp, cred, uio->uio_td); - break; - default: - panic("uninterpreted mode passed to fuse_io_dispatch"); - } - -out: - if (closefufh) - fuse_filehandle_close(vp, fufh, curthread, cred); - - return (err); -} - SDT_PROBE_DEFINE4(fusefs, , io, read_bio_backend_start, "int", "int", "int", "int"); SDT_PROBE_DEFINE2(fusefs, , io, read_bio_backend_feed, "int", "struct buf*"); SDT_PROBE_DEFINE4(fusefs, , io, read_bio_backend_end, "int", "ssize_t", "int", "struct buf*"); -static int +int fuse_read_biobackend(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred, struct fuse_filehandle *fufh, pid_t pid) { @@ -403,7 +230,7 @@ SDT_PROBE_DEFINE1(fusefs, , io, read_directbackend_start, SDT_PROBE_DEFINE3(fusefs, , io, read_directbackend_complete, "struct fuse_dispatcher*", "struct fuse_read_in*", "struct uio*"); -static int +int fuse_read_directbackend(struct vnode *vp, struct uio *uio, struct ucred *cred, struct fuse_filehandle *fufh) { @@ -465,7 +292,7 @@ out: return (err); } -static int +int fuse_write_directbackend(struct vnode *vp, struct uio *uio, struct ucred *cred, struct fuse_filehandle *fufh, off_t filesize, int ioflag, bool pages) @@ -628,7 +455,7 @@ SDT_PROBE_DEFINE6(fusefs, , io, write_biobackend_start, "int64_t", "int", "int", SDT_PROBE_DEFINE2(fusefs, , io, write_biobackend_append_race, "long", "int"); SDT_PROBE_DEFINE2(fusefs, , io, write_biobackend_issue, "int", "struct buf*"); -static int +int fuse_write_biobackend(struct vnode *vp, struct uio *uio, struct ucred *cred, struct fuse_filehandle *fufh, int ioflag, pid_t pid) { diff --git a/sys/fs/fuse/fuse_io.h b/sys/fs/fuse/fuse_io.h index 6240b6e89775..8305171fc941 100644 --- a/sys/fs/fuse/fuse_io.h +++ b/sys/fs/fuse/fuse_io.h @@ -65,10 +65,17 @@ #ifndef _FUSE_IO_H_ #define _FUSE_IO_H_ -int fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag, - 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); int fuse_io_invalbuf(struct vnode *vp, struct thread *td); +int fuse_read_directbackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh); +int fuse_read_biobackend(struct vnode *vp, struct uio *uio, int ioflag, + struct ucred *cred, struct fuse_filehandle *fufh, pid_t pid); +int fuse_write_directbackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh, off_t filesize, + int ioflag, bool pages); +int fuse_write_biobackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh, int ioflag, pid_t pid); #endif /* _FUSE_IO_H_ */ diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index d0f4cae302c1..36507fae4d59 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -318,6 +318,59 @@ fuse_fifo_close(struct vop_close_args *ap) return (fifo_specops.vop_close(ap)); } +/* Invalidate a range of cached data, whether dirty of not */ +static int +fuse_inval_buf_range(struct vnode *vp, off_t filesize, off_t start, off_t end) +{ + struct buf *bp; + daddr_t left_lbn, end_lbn, right_lbn; + off_t new_filesize; + int iosize, left_on, right_on, right_blksize; + + iosize = fuse_iosize(vp); + left_lbn = start / iosize; + end_lbn = howmany(end, iosize); + left_on = start & (iosize - 1); + if (left_on != 0) { + bp = getblk(vp, left_lbn, iosize, PCATCH, 0, 0); + if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyend >= left_on) { + /* + * Flush the dirty buffer, because we don't have a + * byte-granular way to record which parts of the + * buffer are valid. + */ + bwrite(bp); + if (bp->b_error) + return (bp->b_error); + } else { + brelse(bp); + } + } + right_on = end & (iosize - 1); + if (right_on != 0) { + right_lbn = end / iosize; + new_filesize = MAX(filesize, end); + right_blksize = MIN(iosize, new_filesize - iosize * right_lbn); + bp = getblk(vp, right_lbn, right_blksize, PCATCH, 0, 0); + if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyoff < right_on) { + /* + * Flush the dirty buffer, because we don't have a + * byte-granular way to record which parts of the + * buffer are valid. + */ + bwrite(bp); + if (bp->b_error) + return (bp->b_error); + } else { + brelse(bp); + } + } + + v_inval_buf_range(vp, left_lbn, end_lbn, iosize); + return (0); +} + + /* Send FUSE_LSEEK for this node */ static int fuse_vnop_do_lseek(struct vnode *vp, struct thread *td, struct ucred *cred, @@ -1587,6 +1640,8 @@ fuse_vnop_pathconf(struct vop_pathconf_args *ap) } } +SDT_PROBE_DEFINE3(fusefs, , vnops, filehandles_closed, "struct vnode*", + "struct uio*", "struct ucred*"); /* struct vnop_read_args { struct vnode *a_vp; @@ -1603,6 +1658,11 @@ fuse_vnop_read(struct vop_read_args *ap) int ioflag = ap->a_ioflag; struct ucred *cred = ap->a_cred; pid_t pid = curthread->td_proc->p_pid; + struct fuse_filehandle *fufh; + int err; + bool closefufh = false, directio; + + MPASS(vp->v_type == VREG || vp->v_type == VDIR); if (fuse_isdeadfs(vp)) { return ENXIO; @@ -1612,7 +1672,45 @@ fuse_vnop_read(struct vop_read_args *ap) ioflag |= IO_DIRECT; } - return fuse_io_dispatch(vp, uio, ioflag, cred, pid); + err = fuse_filehandle_getrw(vp, FREAD, &fufh, cred, pid); + if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) { + /* + * nfsd will do I/O without first doing VOP_OPEN. We + * must implicitly open the file here + */ + err = fuse_filehandle_open(vp, FREAD, &fufh, curthread, cred); + closefufh = true; + } + if (err) { + SDT_PROBE3(fusefs, , vnops, filehandles_closed, vp, uio, cred); + return err; + } + + /* + * Ideally, when the daemon asks for direct io at open time, the + * standard file flag should be set according to this, so that would + * just change the default mode, which later on could be changed via + * fcntl(2). + * But this doesn't work, the O_DIRECT flag gets cleared at some point + * (don't know where). So to make any use of the Fuse direct_io option, + * we hardwire it into the file's private data (similarly to Linux, + * btw.). + */ + directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp)); + + fuse_vnode_update(vp, FN_ATIMECHANGE); + if (directio) { + SDT_PROBE2(fusefs, , vnops, trace, 1, "direct read of vnode"); + err = fuse_read_directbackend(vp, uio, cred, fufh); + } else { + SDT_PROBE2(fusefs, , vnops, trace, 1, "buffered read of vnode"); + err = fuse_read_biobackend(vp, uio, ioflag, cred, fufh, pid); + } + + if (closefufh) + fuse_filehandle_close(vp, fufh, curthread, cred); + + return (err); } /* @@ -2165,6 +2263,11 @@ fuse_vnop_write(struct vop_write_args *ap) int ioflag = ap->a_ioflag; struct ucred *cred = ap->a_cred; pid_t pid = curthread->td_proc->p_pid; + struct fuse_filehandle *fufh; + int err; + bool closefufh = false, directio; + + MPASS(vp->v_type == VREG || vp->v_type == VDIR); if (fuse_isdeadfs(vp)) { return ENXIO; @@ -2174,7 +2277,67 @@ fuse_vnop_write(struct vop_write_args *ap) ioflag |= IO_DIRECT; } - return fuse_io_dispatch(vp, uio, ioflag, cred, pid); + err = fuse_filehandle_getrw(vp, FWRITE, &fufh, cred, pid); + if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) { + /* + * nfsd will do I/O without first doing VOP_OPEN. We + * must implicitly open the file here + */ + err = fuse_filehandle_open(vp, FWRITE, &fufh, curthread, cred); + closefufh = true; + } + if (err) { + SDT_PROBE3(fusefs, , vnops, filehandles_closed, vp, uio, cred); + return err; + } + + /* + * Ideally, when the daemon asks for direct io at open time, the + * standard file flag should be set according to this, so that would + * just change the default mode, which later on could be changed via + * fcntl(2). + * But this doesn't work, the O_DIRECT flag gets cleared at some point + * (don't know where). So to make any use of the Fuse direct_io option, + * we hardwire it into the file's private data (similarly to Linux, + * btw.). + */ + directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp)); + + fuse_vnode_update(vp, FN_MTIMECHANGE | FN_CTIMECHANGE); + if (directio) { + off_t start, end, filesize; + bool pages = (ioflag & IO_VMIO) != 0; + + SDT_PROBE2(fusefs, , vnops, trace, 1, "direct write of vnode"); + + err = fuse_vnode_size(vp, &filesize, cred, curthread); + if (err) + goto out; + + start = uio->uio_offset; + end = start + uio->uio_resid; + if (!pages) { + err = fuse_inval_buf_range(vp, filesize, start, + end); + if (err) + goto out; + } + err = fuse_write_directbackend(vp, uio, cred, fufh, + filesize, ioflag, pages); + } else { + SDT_PROBE2(fusefs, , vnops, trace, 1, + "buffered write of vnode"); + if (!fsess_opt_writeback(vnode_mount(vp))) + ioflag |= IO_SYNC; + err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag, pid); + } + fuse_internal_clear_suid_on_write(vp, cred, uio->uio_td); + +out: + if (closefufh) + fuse_filehandle_close(vp, fufh, curthread, cred); + + return (err); } static daddr_t