Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/fuse/fuse_io.c
Show First 20 Lines • Show All 565 Lines • ▼ Show 20 Lines | retry: | ||||
fwo = ((struct fuse_write_out *)fdi.answ); | fwo = ((struct fuse_write_out *)fdi.answ); | ||||
/* Adjust the uio in the case of short writes */ | /* Adjust the uio in the case of short writes */ | ||||
diff = fwi->size - fwo->size; | diff = fwi->size - fwo->size; | ||||
as_written_offset = uio->uio_offset - diff; | as_written_offset = uio->uio_offset - diff; | ||||
if (as_written_offset - diff > filesize) | if (as_written_offset - diff > filesize) | ||||
fuse_vnode_setsize(vp, as_written_offset); | fuse_vnode_setsize(vp, as_written_offset, false); | ||||
if (as_written_offset - diff >= filesize) | if (as_written_offset - diff >= filesize) | ||||
fvdat->flag &= ~FN_SIZECHANGE; | fvdat->flag &= ~FN_SIZECHANGE; | ||||
if (diff < 0) { | if (diff < 0) { | ||||
fuse_warn(data, FSESS_WARN_WROTE_LONG, | fuse_warn(data, FSESS_WARN_WROTE_LONG, | ||||
"wrote more data than we provided it."); | "wrote more data than we provided it."); | ||||
err = EINVAL; | err = EINVAL; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | if (!bp) { | ||||
err = EINTR; | err = EINTR; | ||||
break; | break; | ||||
} | } | ||||
if (extending) { | if (extending) { | ||||
/* | /* | ||||
* Extend file _after_ locking buffer so we won't race | * Extend file _after_ locking buffer so we won't race | ||||
* with other readers | * with other readers | ||||
*/ | */ | ||||
err = fuse_vnode_setsize(vp, uio->uio_offset + n); | err = fuse_vnode_setsize(vp, uio->uio_offset + n, false); | ||||
filesize = uio->uio_offset + n; | filesize = uio->uio_offset + n; | ||||
fvdat->flag |= FN_SIZECHANGE; | fvdat->flag |= FN_SIZECHANGE; | ||||
if (err) { | if (err) { | ||||
brelse(bp); | brelse(bp); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | if (bp->b_iocmd == BIO_READ) { | ||||
if (error) { | if (error) { | ||||
bp->b_ioflags |= BIO_ERROR; | bp->b_ioflags |= BIO_ERROR; | ||||
bp->b_error = error; | bp->b_error = error; | ||||
} | } | ||||
} else { | } else { | ||||
/* | /* | ||||
* Setup for actual write | * Setup for actual write | ||||
*/ | */ | ||||
error = fuse_vnode_size(vp, &filesize, cred, curthread); | /* | ||||
if (error) { | * If the file's size is cached, use that value, even if the | ||||
bp->b_ioflags |= BIO_ERROR; | * cache is expired. At this point we're already committed to | ||||
bp->b_error = error; | * writing something. If the FUSE server has changed the | ||||
bufdone(bp); | * file's size behind our back, it's too late for us to do | ||||
return (error); | * anything about it. In particular, we can't invalidate any | ||||
} | * part of the file's buffers because VOP_STRATEGY is called | ||||
* with them already locked. | |||||
*/ | |||||
filesize = fvdat->cached_attrs.va_size; | |||||
/* filesize must've been cached by fuse_vnop_open. */ | |||||
KASSERT(filesize != VNOVAL, ("filesize should've been cached")); | |||||
if ((off_t)bp->b_lblkno * biosize + bp->b_dirtyend > filesize) | if ((off_t)bp->b_lblkno * biosize + bp->b_dirtyend > filesize) | ||||
bp->b_dirtyend = filesize - | bp->b_dirtyend = filesize - | ||||
(off_t)bp->b_lblkno * biosize; | (off_t)bp->b_lblkno * biosize; | ||||
if (bp->b_dirtyend > bp->b_dirtyoff) { | if (bp->b_dirtyend > bp->b_dirtyoff) { | ||||
io.iov_len = uiop->uio_resid = bp->b_dirtyend | io.iov_len = uiop->uio_resid = bp->b_dirtyend | ||||
- bp->b_dirtyoff; | - bp->b_dirtyoff; | ||||
▲ Show 20 Lines • Show All 103 Lines • Show Last 20 Lines |