From b44da712d003df1dc28ff136b4402c0fe38a5d28 Mon Sep 17 00:00:00 2001 From: asomers Date: Wed, 5 Jun 2019 20:18:56 +0000 Subject: [PATCH] fusefs: simplify fuse_write_biobackend. No functional change. Sponsored by: The FreeBSD Foundation --- sys/fs/fuse/fuse_io.c | 90 +++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c index d760a93146b..faa0a2d455d 100644 --- a/sys/fs/fuse/fuse_io.c +++ b/sys/fs/fuse/fuse_io.c @@ -594,6 +594,8 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio, * no point optimizing for something that really won't ever happen. */ do { + bool direct_append, extending; + if (fuse_isdeadfs(vp)) { err = ENXIO; break; @@ -603,68 +605,54 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio, n = MIN((unsigned)(biosize - on), uio->uio_resid); again: - /* - * Handle direct append and file extension cases, calculate - * unaligned buffer size. - */ - if (uio->uio_offset == filesize && n) { - /* - * Get the buffer (in its pre-append state to maintain - * B_CACHE if it was previously set). Resize the - * nfsnode after we have locked the buffer to prevent - * readers from reading garbage. - */ - bcount = on; - SDT_PROBE6(fusefs, , io, write_biobackend_start, - lbn, on, n, uio, bcount, true); - bp = getblk(vp, lbn, bcount, PCATCH, 0, 0); - + /* Get or create a buffer for the write */ + direct_append = uio->uio_offset == filesize && n; + if ((off_t)lbn * biosize + on + n < filesize) { + extending = false; + if ((off_t)(lbn + 1) * biosize < filesize) { + /* Not the file's last block */ + bcount = biosize; + } else { + /* The file's last block */ + bcount = filesize - (off_t)lbn *biosize; + } + } else { + extending = true; + bcount = on + n; + } + if (direct_append) { + /* + * Take care to preserve the buffer's B_CACHE state so + * as not to cause an unnecessary read. + */ + bp = getblk(vp, lbn, on, PCATCH, 0, 0); if (bp != NULL) { - long save; - - err = fuse_vnode_setsize(vp, cred, - uio->uio_offset + n); - fvdat->flag |= FN_SIZECHANGE; - - if (err) { - brelse(bp); - break; - } - save = bp->b_flags & B_CACHE; - bcount += n; + uint32_t save = bp->b_flags & B_CACHE; allocbuf(bp, bcount); bp->b_flags |= save; } } else { - /* - * Obtain the locked cache block first, and then - * adjust the file's size as appropriate. - */ - bcount = on + n; - if ((off_t)lbn * biosize + bcount < filesize) { - if ((off_t)(lbn + 1) * biosize < filesize) - bcount = biosize; - else - bcount = filesize - (off_t)lbn *biosize; - } - SDT_PROBE6(fusefs, , io, write_biobackend_start, - lbn, on, n, uio, bcount, false); bp = getblk(vp, lbn, bcount, PCATCH, 0, 0); - if (bp && uio->uio_offset + n > filesize) { - err = fuse_vnode_setsize(vp, cred, - uio->uio_offset + n); - fvdat->flag |= FN_SIZECHANGE; - if (err) { - brelse(bp); - break; - } - } } - if (!bp) { err = EINTR; break; } + if (extending) { + /* + * Extend file _after_ locking buffer so we won't race + * with other readers + */ + err = fuse_vnode_setsize(vp, cred, uio->uio_offset + n); + fvdat->flag |= FN_SIZECHANGE; + if (err) { + brelse(bp); + break; + } + } + + SDT_PROBE6(fusefs, , io, write_biobackend_start, + lbn, on, n, uio, bcount, direct_append); /* * Issue a READ if B_CACHE is not set. In special-append * mode, B_CACHE is based on the buffer prior to the write -- 2.45.0