Date: Sat, 9 Jul 2011 08:59:30 GMT From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 195925 for review Message-ID: <201107090859.p698xUsI043254@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@195925?ac=10 Change 195925 by ilya@ilya_triton2011 on 2011/07/09 08:59:09 Rewrite fuse_io_strategy to be similar to NFS. Set iosize to PAGE_SIZE (was MAXBSIZE) Set file size in fuse_write_directbackend Refresh file size before write Remove fuse_std_buffeater Affected files ... .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#17 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#16 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.h#9 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#15 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#15 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vfsops.c#20 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#37 edit Differences ... ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#17 (text+ko) ==== @@ -130,6 +130,13 @@ return fuse_isdeadfs_mp(vnode_mount(vp)); } +static __inline__ +int +fuse_iosize(struct vnode *vp) +{ + return vp->v_mount->mnt_stat.f_iosize; +} + /* access */ #define FVP_ACCESS_NOOP 0x01 ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#16 (text+ko) ==== @@ -38,27 +38,32 @@ #include "fuse.h" #include "fuse_file.h" #include "fuse_node.h" +#include "fuse_internal.h" #include "fuse_ipc.h" #include "fuse_io.h" #define FUSE_DEBUG_MODULE IO #include "fuse_debug.h" -static int fuse_read_directbackend(struct fuse_io_data *fioda); -static int fuse_read_biobackend(struct fuse_io_data *fioda); -static int fuse_write_directbackend(struct fuse_io_data *fioda); -static int fuse_write_biobackend(struct fuse_io_data *fioda); -static fuse_buffeater_t fuse_std_buffeater; +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, + struct ucred *cred, struct fuse_filehandle *fufh); +static int fuse_write_directbackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh); +static int fuse_write_biobackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh); int fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { struct fuse_filehandle *fufh; - struct fuse_io_data fioda; int err, directio; + MPASS(vp->v_type == VREG); + err = fuse_filehandle_getrw(vp, (uio->uio_rw == UIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh); if (err) { @@ -66,13 +71,6 @@ return err; } - bzero(&fioda, sizeof(fioda)); - fioda.vp = vp; - fioda.fufh = fufh; - fioda.uio = uio; - fioda.cred = cred; - fioda.td = curthread; - /* * Ideally, when the daemon asks for direct io at open time, the * standard file flag should be set according to this, so that would @@ -87,26 +85,23 @@ switch (uio->uio_rw) { case UIO_READ: - fioda.opcode = FUSE_READ; - fioda.buffeater = fuse_std_buffeater; - if (directio) { DEBUG("direct read of vnode %ju via file handle %ju\n", (uintmax_t)VTOILLU(vp), (uintmax_t)fufh->fh_id); - err = fuse_read_directbackend(&fioda); + err = fuse_read_directbackend(vp, uio, cred, fufh); } else { DEBUG("buffered read of vnode %ju\n", (uintmax_t)VTOILLU(vp)); - err = fuse_read_biobackend(&fioda); + err = fuse_read_biobackend(vp, uio, cred, fufh); } break; case UIO_WRITE: if (directio) { DEBUG("direct write of vnode %ju via file handle %ju\n", (uintmax_t)VTOILLU(vp), (uintmax_t)fufh->fh_id); - err = fuse_write_directbackend(&fioda); + err = fuse_write_directbackend(vp, uio, cred, fufh); } else { DEBUG("buffered write of vnode %ju\n", (uintmax_t)VTOILLU(vp)); - err = fuse_write_biobackend(&fioda); + err = fuse_write_biobackend(vp, uio, cred, fufh); } break; default: @@ -119,30 +114,28 @@ } static int -fuse_read_biobackend(struct fuse_io_data *fioda) +fuse_read_biobackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh) { - - struct vnode *vp = fioda->vp; - struct fuse_filehandle *fufh = fioda->fufh; - struct uio *uio = fioda->uio; - enum fuse_opcode op = fioda->opcode; - fuse_buffeater_t *buffe = fioda->buffeater; - void *param = fioda->param; - - int biosize; struct buf *bp; daddr_t lbn; int bcount; - int bbcount; int err = 0, n = 0, on = 0; + off_t filesize; + + const int biosize = fuse_iosize(vp); + + DEBUG("resid=%zx offset=%jx fsize=%jx\n", + uio->uio_resid, uio->uio_offset, VTOFUD(vp)->filesize); if (uio->uio_resid == 0) return (0); + if (uio->uio_offset < 0) + return (EINVAL); - biosize = vp->v_mount->mnt_stat.f_iosize; bcount = MIN(MAXBSIZE, biosize); + filesize = VTOFUD(vp)->filesize; - DEBUG2G("entering loop\n"); do { lbn = uio->uio_offset / biosize; on = uio->uio_offset & (biosize - 1); @@ -160,6 +153,11 @@ * * Note that bcount is *not* DEV_BSIZE aligned. */ + if ((off_t)lbn * biosize >= filesize) { + bcount = 0; + } else if ((off_t)(lbn + 1) * biosize > filesize) { + bcount = filesize - (off_t)lbn * biosize; + } bp = getblk(vp, lbn, bcount, PCATCH, 0, 0); @@ -174,7 +172,7 @@ if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; vfs_busy_pages(bp, 0); - err = fuse_io_strategy(vp, bp, fufh, op); + err = fuse_io_strategy(vp, bp); if (err) { brelse(bp); return (err); @@ -190,43 +188,25 @@ */ n = 0; - /* - * If we zero pad the buf, bp->b_resid will be 0, so then - * just ignore it - */ - bbcount = bcount - bp->b_resid; - if (on < bbcount) - n = bbcount - on; + if (on < bcount) + n = MIN((unsigned)(bcount - on), uio->uio_resid); if (n > 0) { DEBUG2G("feeding buffeater with %d bytes of buffer %p, saying %d was asked for\n", n, bp->b_data + on, n + (int)bp->b_resid); -#if 0 && _DEBUG - prettyprint(bp->b_data + on, n); - printf("\n"); -#endif - err = buffe(uio, n + bp->b_resid, bp->b_data + on, n, - param); + err = uiomove(bp->b_data + on, n, uio); } brelse(bp); DEBUG2G("end of turn, err %d, uio->uio_resid %zd, n %d\n", err, uio->uio_resid, n); } while (err == 0 && uio->uio_resid > 0 && n > 0); - return ((err == -1) ? 0 : err); + return (err); } static int -fuse_read_directbackend(struct fuse_io_data *fioda) +fuse_read_directbackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh) { - struct vnode *vp = fioda->vp; - struct fuse_filehandle *fufh = fioda->fufh; - struct uio *uio = fioda->uio; - struct ucred *cred = fioda->cred; - struct thread *td = fioda->td; - enum fuse_opcode op = fioda->opcode; - fuse_buffeater_t *buffe = fioda->buffeater; - void *param = fioda->param; - struct fuse_dispatcher fdi; struct fuse_read_in *fri; int err = 0; @@ -234,8 +214,6 @@ if (uio->uio_resid == 0) return (0); - DEBUG("bug daemon for food\n"); - fdisp_init(&fdi, 0); /* @@ -248,7 +226,7 @@ */ while (uio->uio_resid > 0) { fdi.iosize = sizeof(*fri); - fdisp_make_vp(&fdi, op, vp, td, cred); + fdisp_make_vp(&fdi, FUSE_READ, vp, uio->uio_td, cred); fri = fdi.indata; fri->fh = fufh->fh_id; fri->offset = uio->uio_offset; @@ -260,48 +238,31 @@ if ((err = fdisp_wait_answ(&fdi))) goto out; - DEBUG2G("%zd bytes asked for from offset %ju, passing on the %jd we got\n", - uio->uio_resid, (uintmax_t)uio->uio_offset, (uintmax_t)fdi.iosize); + DEBUG2G("complete: got iosize=%d, requested fri.size=%zd; " + "resid=%zd offset=%ju\n", + fri->size, fdi.iosize, uio->uio_resid, (uintmax_t)uio->uio_offset); - if ((err = buffe(uio, fri->size, fdi.answ, fdi.iosize, param))) + if ((err = uiomove(fdi.answ, MIN(fri->size, fdi.iosize), uio))) break; + if (fdi.iosize < fri->size) + break; } fuse_ticket_drop(fdi.tick); out: - return ((err == -1) ? 0 : err); + return (err); } -/* Simple standard way for transmitting input */ static int -fuse_std_buffeater(struct uio *uio, size_t reqsize, void *buf, size_t bufsize, void *param) -{ - int err; - - if ((err = uiomove(buf, MIN(reqsize, bufsize), uio))) - return (err); - - if (bufsize < reqsize) - return (-1); - - return (0); -} - - -static int -fuse_write_directbackend(struct fuse_io_data *fioda) +fuse_write_directbackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh) { - struct vnode *vp = fioda->vp; - uint64_t fh_id = fioda->fufh->fh_id; - struct uio *uio = fioda->uio; - struct ucred *cred = fioda->cred; - struct thread *td = fioda->td; - + struct fuse_vnode_data *fvdat = VTOFUD(vp); + struct fuse_write_in *fwi; + struct fuse_dispatcher fdi; size_t chunksize; int diff; - struct fuse_write_in *fwi; - struct fuse_dispatcher fdi; int err = 0; if (! uio->uio_resid) @@ -314,10 +275,10 @@ fuse_get_mpdata(vp->v_mount)->max_write); fdi.iosize = sizeof(*fwi) + chunksize; - fdisp_make_vp(&fdi, FUSE_WRITE, vp, td, cred); + fdisp_make_vp(&fdi, FUSE_WRITE, vp, uio->uio_td, cred); fwi = fdi.indata; - fwi->fh = fh_id; + fwi->fh = fufh->fh_id; fwi->offset = uio->uio_offset; fwi->size = chunksize; @@ -336,6 +297,8 @@ uio->uio_resid += diff; uio->uio_offset -= diff; + if (uio->uio_offset > fvdat->filesize) + fuse_vnode_setsize(vp, uio->uio_offset); } fuse_ticket_drop(fdi.tick); @@ -344,23 +307,26 @@ } static int -fuse_write_biobackend(struct fuse_io_data *fioda) +fuse_write_biobackend(struct vnode *vp, struct uio *uio, + struct ucred *cred, struct fuse_filehandle *fufh) { - struct vnode *vp = fioda->vp; - struct uio *uio = fioda->uio; - struct ucred *cred = fioda->cred; struct fuse_vnode_data *fvdat = VTOFUD(vp); - - int biosize; - struct buf *bp; daddr_t lbn; int bcount; int n, on, err = 0; - DEBUG2G("fsize %ju\n", (uintmax_t)fvdat->filesize); + const int biosize = fuse_iosize(vp); - biosize = vp->v_mount->mnt_stat.f_iosize; + KASSERT(uio->uio_rw == UIO_WRITE, ("ncl_write mode")); + DEBUG("resid=%zx offset=%jx fsize=%jx\n", + uio->uio_resid, uio->uio_offset, fvdat->filesize); + if (vp->v_type != VREG) + return (EIO); + if (uio->uio_offset < 0) + return (EINVAL); + if (uio->uio_resid == 0) + return (0); /* * Find all of this file's B_NEEDCOMMIT buffers. If our writes @@ -383,7 +349,6 @@ * Handle direct append and file extension cases, calculate * unaligned buffer size. */ - if (uio->uio_offset == fvdat->filesize && n) { /* * Get the buffer (in its pre-append state to maintain @@ -457,7 +422,7 @@ if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; vfs_busy_pages(bp, 0); - fuse_io_strategy(vp, bp, NULL, 0); + fuse_io_strategy(vp, bp); if ((err = bp->b_error)) { brelse(bp); break; @@ -476,7 +441,7 @@ */ if (bp->b_dirtyend > bcount) { - DEBUG("Fuse append race @%lx:%d\n", + DEBUG("FUSE append race @%lx:%d\n", (long)bp->b_blkno * biosize, bp->b_dirtyend - bcount); bp->b_dirtyend = bcount; @@ -550,8 +515,8 @@ vfs_bio_set_valid(bp, on, n); } - bwrite(bp); - if ((err = bp->b_error)) + err = bwrite(bp); + if (err) break; } while (uio->uio_resid > 0 && n > 0); @@ -559,31 +524,42 @@ } int -fuse_io_strategy(struct vnode *vp, struct buf *bp, struct fuse_filehandle *fufh, - enum fuse_opcode op) +fuse_io_strategy(struct vnode *vp, struct buf *bp) { + struct fuse_filehandle *fufh; struct fuse_vnode_data *fvdat = VTOFUD(vp); - struct fuse_dispatcher fdi; - struct ucred *cred; - int err = 0; - int chunksize, respsize; - caddr_t bufdat; - int biosize = vp->v_mount->mnt_stat.f_iosize; + struct ucred *cred; + struct uio *uiop; + struct uio uio; + struct iovec io; + int error = 0; + + const int biosize = fuse_iosize(vp); + + MPASS(vp->v_type == VREG); + MPASS(bp->b_iocmd == BIO_READ || bp->b_iocmd == BIO_WRITE); + DEBUG("inode=%jd offset=%jd resid=%jd\n", + VTOI(vp), ((off_t)bp->b_blkno) * biosize, bp->b_bcount); - if (! (vp->v_type == VREG || vp->v_type == VDIR)) { - DEBUG("for vnode #%ju v_type is %d, dropping\n", - (uintmax_t)VTOILLU(vp), vp->v_type); - return (EOPNOTSUPP); + error = fuse_filehandle_getrw(vp, + (bp->b_iocmd == BIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh); + if (error) { + DEBUG("fetching filehandle failed\n"); + bp->b_ioflags |= BIO_ERROR; + bp->b_error = error; + return (error); } - if (bp->b_iocmd != BIO_READ && bp->b_iocmd != BIO_WRITE) { - DEBUG("for vnode #%ju bio tried with biocmd %#x, dropping\n", - (uintmax_t)VTOILLU(vp), bp->b_iocmd); - return (EOPNOTSUPP); - } + cred = bp->b_iocmd == BIO_READ ? bp->b_rcred : bp->b_wcred; + + uiop = &uio; + uiop->uio_iov = &io; + uiop->uio_iovcnt = 1; + uiop->uio_segflg = UIO_SYSSPACE; + uiop->uio_td = curthread; /* - * clear BIO_ERROR and B_INVAL state prior to initiating the I/O. We + * clear BIO_ERROR and B_INVAL state prior to initiating the I/O. We * do this here so we do not have to do it in all the code that * calls us. */ @@ -591,157 +567,85 @@ bp->b_ioflags &= ~BIO_ERROR; KASSERT(!(bp->b_flags & B_DONE), - ("fuse_strategy: bp %p already marked done", bp)); - - if (bp->b_bcount == 0) - return (0); - - cred = bp->b_iocmd == BIO_READ ? bp->b_rcred : bp->b_wcred; - - err = fuse_filehandle_getrw(vp, - (bp->b_iocmd == BIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh); - if (err) { - DEBUG("fetching filehandle failed\n"); - goto out; - } - - DEBUG2G("vp #%ju, fufh #%ju\n", - (uintmax_t)VTOILLU(vp), (uintmax_t)fufh->fh_id); - - fdisp_init(&fdi, 0); - + ("fuse_io_strategy: bp %p already marked done", bp)); if (bp->b_iocmd == BIO_READ) { - struct fuse_read_in *fri; - int ioff = 0; + io.iov_len = uiop->uio_resid = bp->b_bcount; + io.iov_base = bp->b_data; + uiop->uio_rw = UIO_READ; - bufdat = bp->b_data; - bp->b_resid = bp->b_bcount; - while (bp->b_resid > 0) { - DEBUG2G("starting bio with resid %ld\n", bp->b_resid); - chunksize = MIN(bp->b_resid, - fuse_get_mpdata(vp->v_mount)->max_read); - fdi.iosize = sizeof(*fri); - if (! op) - op = vp->v_type == VDIR ? FUSE_READDIR : FUSE_READ; - fdisp_make_vp(&fdi, op, vp, curthread, cred); + uiop->uio_offset = ((off_t)bp->b_blkno) * biosize; + error = fuse_read_directbackend(vp, uiop, cred, fufh); - fri = fdi.indata; - fri->fh = fufh->fh_id; - fri->offset = ((off_t)bp->b_blkno) * biosize + ioff; - chunksize = MIN(chunksize, - MIN(fri->offset + bp->b_resid, - fvdat->filesize) - fri->offset); - if (chunksize == 0) { - respsize = -1; - goto eval; - } - fri->size = chunksize; - fdi.tick->tk_aw_type = FT_A_BUF; - fdi.tick->tk_aw_bufdata = bufdat; + if (!error && uiop->uio_resid) { + /* + * If we had a short read with no error, we must have + * hit a file hole. We should zero-fill the remainder. + * This can also occur if the server hits the file EOF. + * + * Holes used to be able to occur due to pending + * writes, but that is not possible any longer. + */ + int nread = bp->b_bcount - uiop->uio_resid; + int left = uiop->uio_resid; - DEBUG("waiting for answer\n"); - if ((err = fdisp_wait_answ(&fdi))) - goto out; - - respsize = fdi.tick->tk_aw_bufsize; - DEBUG2G("chunksize %d, respsize %d, bp->b_resid %ld, bp->b_bcount %ld\n", - chunksize, respsize, bp->b_resid, bp->b_bcount); - bp->b_resid -= respsize; - bufdat += respsize; - ioff += respsize; - -eval: - DEBUG2G("%d bytes asked for from offset %llu, passing on the %d we got\n", - chunksize, (long long unsigned)fri->offset, respsize); - - if (respsize < chunksize) { - /* - * if we don't get enough data, just fill the - * rest with zeros. - */ - DEBUG("zeroing tail of %ld bytes\n", - bp->b_resid); - bzero((char *)bp->b_data + bp->b_bcount - bp->b_resid, - bp->b_resid); - if (chunksize) - bp->b_resid = 0; - break; - } - if (respsize > chunksize) { - fuse_ticket_drop(fdi.tick); - err = EINVAL; - goto out; - } - DEBUG("bp->b_data %p\n", bp->b_data); + if (left > 0) + bzero((char *)bp->b_data + nread, left); + uiop->uio_resid = 0; + } + if (error) { + bp->b_ioflags |= BIO_ERROR; + bp->b_error = error; } } else { - struct fuse_write_in *fwi; - struct fuse_write_out *fwo; - int diff; - int merr = 0; + /* + * If we only need to commit, try to commit + */ + if (bp->b_flags & B_NEEDCOMMIT) { + DEBUG("write: B_NEEDCOMMIT flags set\n"); + } - bufdat = bp->b_data + bp->b_dirtyoff; - while (bp->b_dirtyend > bp->b_dirtyoff) { - chunksize = MIN(bp->b_dirtyend - bp->b_dirtyoff, - fuse_get_mpdata(vp->v_mount)->max_write); + /* + * Setup for actual write + */ + if ((off_t)bp->b_blkno * biosize + bp->b_dirtyend > fvdat->filesize) + bp->b_dirtyend = fvdat->filesize - (off_t)bp->b_blkno * biosize; - fdi.iosize = sizeof(*fwi); - op = op ?: FUSE_WRITE; - fdisp_make_vp(&fdi, op, vp, NULL, cred); + if (bp->b_dirtyend > bp->b_dirtyoff) { + io.iov_len = uiop->uio_resid = bp->b_dirtyend + - bp->b_dirtyoff; + uiop->uio_offset = (off_t)bp->b_blkno * biosize + + bp->b_dirtyoff; + io.iov_base = (char *)bp->b_data + bp->b_dirtyoff; + uiop->uio_rw = UIO_WRITE; - fwi = fdi.indata; - fwi->fh = fufh->fh_id; - fwi->offset = (off_t)bp->b_blkno * biosize + bp->b_dirtyoff; - fwi->size = chunksize; - fdi.tick->tk_ms_type = FT_M_BUF; - fdi.tick->tk_ms_bufdata = bufdat; - fdi.tick->tk_ms_bufsize = chunksize; + error = fuse_write_directbackend(vp, uiop, cred, fufh); - if ((err = fdisp_wait_answ(&fdi))) { - merr = 1; - break; - } + if (error == EINTR || error == ETIMEDOUT + || (!error && (bp->b_flags & B_NEEDCOMMIT))) { - fwo = fdi.answ; - diff = chunksize - fwo->size; - if (diff < 0) { - err = EINVAL; - break; + bp->b_flags &= ~(B_INVAL|B_NOCACHE); + if ((bp->b_flags & B_PAGING) == 0) { + bdirty(bp); + bp->b_flags &= ~B_DONE; + } + if ((error == EINTR || error == ETIMEDOUT) && + (bp->b_flags & B_ASYNC) == 0) + bp->b_flags |= B_EINTR; + } else { + if (error) { + bp->b_ioflags |= BIO_ERROR; + bp->b_flags |= B_INVAL; + bp->b_error = error; + } + bp->b_dirtyoff = bp->b_dirtyend = 0; } - if (diff > 0) { - /* - * Tolerating a short read would mean - * keeping dirty data around and we - * don't do that. - */ - err = EIO; - break; - } - - bp->b_dirtyoff += fwo->size; + } else { + bp->b_resid = 0; + bufdone(bp); + return (0); } - - if (bp->b_dirtyend == bp->b_dirtyoff) - bp->b_dirtyend = bp->b_dirtyoff = 0; - - bp->b_resid = bp->b_dirtyend - bp->b_dirtyoff; - - if (merr) - goto out; } - - if (fdi.tick) - fuse_ticket_drop(fdi.tick); - else - DEBUG("no ticket on leave\n"); - -out: - if (err) { - bp->b_ioflags |= BIO_ERROR; - bp->b_error = err; - } - DEBUG("calling bufdone\n"); + bp->b_resid = uiop->uio_resid; bufdone(bp); - - return (err); -} + return (error); +} ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.h#9 (text+ko) ==== @@ -1,26 +1,8 @@ #ifndef _FUSE_IO_H_ #define _FUSE_IO_H_ -/* prototype for processing an input data buffer and an uio - for reading related acivities */ -typedef int fuse_buffeater_t(struct uio *uio, size_t reqsize, - void *buf, size_t bufsize, void *param); - -/* data used through an I/O operation */ -struct fuse_io_data { - struct vnode *vp; - struct fuse_filehandle *fufh; - struct uio *uio; - struct ucred *cred; - struct thread *td; - enum fuse_opcode opcode; - fuse_buffeater_t *buffeater; - void *param; -}; - int fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred); -int fuse_io_strategy(struct vnode *vp, struct buf *bp, - struct fuse_filehandle *fufh, enum fuse_opcode op); +int fuse_io_strategy(struct vnode *vp, struct buf *bp); #endif /* _FUSE_IO_H_ */ ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#15 (text+ko) ==== @@ -33,6 +33,7 @@ #include "fuse.h" #include "fuse_node.h" #include "fuse_internal.h" +#include "fuse_io.h" #include "fuse_ipc.h" #define FUSE_DEBUG_MODULE VNOPS @@ -228,6 +229,18 @@ } void +fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred) +{ + struct vattr va; + + if (fuse_isvalid_attr(vp)) + return; + + VOP_GETATTR(vp, &va, cred); + DEBUG("refreshed file size: %jd\n", VTOFUD(vp)->filesize); +} + +void fuse_vnode_setsize(struct vnode *vp, off_t newsize) { struct fuse_vnode_data *fvdat = VTOFUD(vp); ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#15 (text+ko) ==== @@ -103,6 +103,8 @@ int32_t fuse_open_flags, struct thread *td); +void fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred); + void fuse_vnode_setsize(struct vnode *vp, off_t newsize); #endif /* _FUSE_NODE_H_ */ ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vfsops.c#20 (text+ko) ==== @@ -241,7 +241,7 @@ } /* We need this here as this slot is used by getnewvnode() */ - mp->mnt_stat.f_iosize = MAXBSIZE; + mp->mnt_stat.f_iosize = PAGE_SIZE; mp->mnt_data = data; ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#37 (text+ko) ==== @@ -1737,7 +1737,10 @@ return EIO; } - (void)fuse_io_strategy(vp, bp, NULL, 0); + if (bp->b_iocmd == BIO_WRITE) + fuse_vnode_refreshsize(vp, NOCRED); + + (void)fuse_io_strategy(vp, bp); /* * This is a dangerous function. If returns error, that might mean a @@ -1827,6 +1830,8 @@ return EIO; } + fuse_vnode_refreshsize(vp, cred); + return fuse_io_dispatch(vp, uio, ioflag, cred); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107090859.p698xUsI043254>