Date: Tue, 26 Jul 2011 06:10:34 GMT From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 196726 for review Message-ID: <201107260610.p6Q6AYYw042706@skunkworks.freebsd.org>
index | next in thread | raw e-mail
http://p4web.freebsd.org/@@196726?ac=10 Change 196726 by ilya@ilya_triton2011 on 2011/07/26 06:10:12 Cache file size in kernel, add sysctls to delay resize and force size refresh. Don't invalidate cached attributes in read* Only flush cache, don't invalidate buffers if vnode inactive. Add data_cache_invalidate sysctl to change action Affected files ... .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#20 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.h#11 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#21 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#20 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#44 edit Differences ... ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#20 (text+ko) ==== @@ -99,6 +99,7 @@ DEBUG("direct write of vnode %ju via file handle %ju\n", (uintmax_t)VTOILLU(vp), (uintmax_t)fufh->fh_id); err = fuse_write_directbackend(vp, uio, cred, fufh); + fuse_invalidate_attr(vp); } else { DEBUG("buffered write of vnode %ju\n", (uintmax_t)VTOILLU(vp)); err = fuse_write_biobackend(vp, uio, cred, fufh); @@ -108,8 +109,6 @@ panic("uninterpreted mode passed to fuse_io_dispatch"); } - fuse_invalidate_attr(vp); - return (err); } @@ -301,7 +300,7 @@ } uio->uio_resid += diff; - uio->uio_offset -= diff; + uio->uio_offset -= diff; if (uio->uio_offset > fvdat->filesize) fuse_vnode_setsize(vp, cred, uio->uio_offset); } @@ -373,7 +372,7 @@ if (bp != NULL) { long save; - err = fuse_vnode_extend(vp, cred, uio->uio_offset + n); + err = fuse_vnode_setsize(vp, cred, uio->uio_offset + n); if (err) { brelse(bp); break; @@ -399,7 +398,7 @@ DEBUG("getting block from OS, bcount %d\n", bcount); bp = getblk(vp, lbn, bcount, PCATCH, 0, 0); if (bp && uio->uio_offset + n > fvdat->filesize) { - err = fuse_vnode_extend(vp, cred, uio->uio_offset + n); + err = fuse_vnode_setsize(vp, cred, uio->uio_offset + n); if (err) { brelse(bp); break; @@ -538,6 +537,9 @@ break; } while (uio->uio_resid > 0 && n > 0); + if (fuse_sync_resize && (fvdat->flag & FN_SIZECHANGE) != 0) + fuse_vnode_savesize(vp, cred); + return (err); } @@ -668,6 +670,18 @@ return (error); } +int +fuse_io_flushbuf(struct vnode *vp, int waitfor, struct thread *td) +{ + struct vop_fsync_args a = { + .a_vp = vp, + .a_waitfor = waitfor, + .a_td = td, + }; + + return (vop_stdfsync(&a)); +} + /* * Flush and invalidate all dirty buffers. If another process is already * doing the flush, just wait for completion. ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.h#11 (text+ko) ==== @@ -4,6 +4,7 @@ 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); +int fuse_io_flushbuf(struct vnode *vp, int waitfor, struct thread *td); int fuse_io_invalbuf(struct vnode *vp, struct thread *td); #endif /* _FUSE_IO_H_ */ ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#21 (text+ko) ==== @@ -49,10 +49,22 @@ SYSCTL_INT(_vfs_fuse, OID_AUTO, data_cache_enable, CTLFLAG_RW, &fuse_data_cache_enable, 0, ""); +int fuse_data_cache_invalidate = 0; +SYSCTL_INT(_vfs_fuse, OID_AUTO, data_cache_invalidate, CTLFLAG_RW, + &fuse_data_cache_invalidate, 0, ""); + int fuse_mmap_enable = 1; SYSCTL_INT(_vfs_fuse, OID_AUTO, mmap_enable, CTLFLAG_RW, &fuse_mmap_enable, 0, ""); +int fuse_refresh_size = 0; +SYSCTL_INT(_vfs_fuse, OID_AUTO, refresh_size, CTLFLAG_RW, + &fuse_refresh_size, 0, ""); + +int fuse_sync_resize = 1; +SYSCTL_INT(_vfs_fuse, OID_AUTO, sync_resize, CTLFLAG_RW, + &fuse_sync_resize, 0, ""); + static void fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat, uint64_t nodeid, enum vtype vtyp) @@ -224,18 +236,17 @@ } int -fuse_vnode_extend(struct vnode *vp, struct ucred *cred, off_t newsize) +fuse_vnode_savesize(struct vnode *vp, struct ucred *cred) { + struct fuse_vnode_data *fvdat = VTOFUD(vp); struct thread *td = curthread; struct fuse_filehandle *fufh = NULL; struct fuse_dispatcher fdi; struct fuse_setattr_in *fsai; int err = 0; - DEBUG("inode=%jd oldsize=%jd newsize=%jd\n", - VTOI(vp), VTOFUD(vp)->filesize, newsize); + DEBUG("inode=%jd size=%jd\n", VTOI(vp), fvdat->filesize); ASSERT_VOP_ELOCKED(vp, "fuse_io_extend"); - MPASS(newsize > VTOFUD(vp)->filesize); if (fuse_isdeadfs(vp)) { return EBADF; @@ -259,7 +270,7 @@ fsai->valid = 0; // Truncate to a new value. - fsai->size = newsize; + fsai->size = fvdat->filesize; fsai->valid |= FATTR_SIZE; fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh); @@ -270,11 +281,10 @@ err = fdisp_wait_answ(&fdi); fdisp_destroy(&fdi); + if (err == 0) + fvdat->flag &= ~FN_SIZECHANGE; fuse_invalidate_attr(vp); - if (!err) { - fuse_vnode_setsize(vp, cred, newsize); - } return err; } @@ -282,20 +292,25 @@ void fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred) { + + struct fuse_vnode_data *fvdat = VTOFUD(vp); struct vattr va; - if (fuse_isvalid_attr(vp)) + if ((fvdat->flag & FN_SIZECHANGE) != 0 || + (fuse_refresh_size == 0 && fvdat->filesize != 0) || + fuse_isvalid_attr(vp)) return; VOP_GETATTR(vp, &va, cred); DEBUG("refreshed file size: %jd\n", VTOFUD(vp)->filesize); } -void +int fuse_vnode_setsize(struct vnode *vp, struct ucred *cred, off_t newsize) { struct fuse_vnode_data *fvdat = VTOFUD(vp); off_t oldsize; + int err = 0; DEBUG("inode=%jd oldsize=%jd newsize=%jd\n", VTOI(vp), fvdat->filesize, newsize); @@ -303,11 +318,14 @@ oldsize = fvdat->filesize; fvdat->filesize = newsize; + fvdat->flag |= FN_SIZECHANGE; if (newsize < oldsize) { - vtruncbuf(vp, cred, curthread, newsize, fuse_iosize(vp)); + err = vtruncbuf(vp, cred, curthread, newsize, fuse_iosize(vp)); } vnode_pager_setsize(vp, newsize); fuse_invalidate_attr(vp); + + return err; } ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#20 (text+ko) ==== @@ -14,6 +14,7 @@ #define FN_REVOKED 0x00000020 #define FN_FLUSHINPROG 0x00000040 #define FN_FLUSHWANT 0x00000080 +#define FN_SIZECHANGE 0x00000100 struct fuse_vnode_data { /** self **/ @@ -47,7 +48,9 @@ extern struct vop_vector fuse_vnops; extern int fuse_data_cache_enable; +extern int fuse_data_cache_invalidate; extern int fuse_mmap_enable; +extern int fuse_sync_resize; static __inline__ void @@ -94,10 +97,10 @@ int32_t fuse_open_flags, struct thread *td); -int fuse_vnode_extend(struct vnode *vp, struct ucred *cred, off_t newsize); +void fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred); -void fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred); +int fuse_vnode_savesize(struct vnode *vp, struct ucred *cred); -void fuse_vnode_setsize(struct vnode *vp, struct ucred *cred, off_t newsize); +int fuse_vnode_setsize(struct vnode *vp, struct ucred *cred, off_t newsize); #endif /* _FUSE_NODE_H_ */ ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#44 (text+ko) ==== @@ -204,6 +204,7 @@ fuse_vnop_close(struct vop_close_args *ap) { struct vnode *vp = ap->a_vp; + struct ucred *cred = ap->a_cred; int fflag = ap->a_fflag; int isdir = (vnode_isdir(vp)) ? 1 : 0; fufh_type_t fufh_type; @@ -234,6 +235,10 @@ fufh_type, fflag); } + if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { + fuse_vnode_savesize(vp, cred); + } + return 0; } @@ -445,6 +450,7 @@ struct vattr *vap = ap->a_vap; struct ucred *cred = ap->a_cred; struct thread *td = curthread; + struct fuse_vnode_data *fvdat = VTOFUD(vp); int err = 0; int dataflags; @@ -461,7 +467,10 @@ if (vap != VTOVA(vp)) { memcpy(vap, VTOVA(vp), sizeof(*vap)); } - debug_printf("fuse_getattr a: returning 0\n"); + if ((fvdat->flag & FN_SIZECHANGE) != 0) { + vap->va_size = fvdat->filesize; + } + debug_printf("return cached: inode=%jd\n", VTOI(vp)); return 0; } @@ -493,13 +502,14 @@ if (vap != VTOVA(vp)) { memcpy(vap, VTOVA(vp), sizeof(*vap)); } + if ((fvdat->flag & FN_SIZECHANGE) != 0) + vap->va_size = fvdat->filesize; - if (vnode_isreg(vp)) { + if (vnode_isreg(vp) && (fvdat->flag & FN_SIZECHANGE) == 0) { /* * This is for those cases when the file size changed without us * knowing, and we want to catch up. */ - struct fuse_vnode_data *fvdat = VTOFUD(vp); off_t new_filesize = ((struct fuse_attr_out *)fdi.answ)->attr.size; if (fvdat->filesize != new_filesize) { @@ -536,16 +546,22 @@ struct fuse_vnode_data *fvdat = VTOFUD(vp); struct fuse_filehandle *fufh = NULL; - int type, need_invalbuf = 1; + int type, need_flush = 1; DEBUG("inode=%jd\n", (uintmax_t)VTOI(vp)); for (type = 0; type < FUFH_MAXTYPE; type++) { fufh = &(fvdat->fufh[type]); if (FUFH_IS_VALID(fufh)) { - if (need_invalbuf) { - fuse_io_invalbuf(vp, td); - need_invalbuf = 0; + if (need_flush) { + if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { + fuse_vnode_savesize(vp, NULL); + } + if (fuse_data_cache_invalidate) + fuse_io_invalbuf(vp, td); + else + fuse_io_flushbuf(vp, MNT_WAIT, td); + need_flush = 0; } fuse_filehandle_close(vp, type, td, NULL, FUSE_OP_BACKGROUNDED); } @@ -1104,7 +1120,7 @@ err = fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKNOD, &fmni, sizeof(fmni), vap->va_type); - if (err== 0) { + if (err == 0) { fuse_invalidate_attr(dvp); } @@ -1247,8 +1263,6 @@ FUSE_OP_FOREGROUNDED); } - fuse_invalidate_attr(vp); - return err; } @@ -1295,8 +1309,6 @@ err = uiomove(fdi.answ, fdi.iosize, uio); } - fuse_invalidate_attr(vp); - out: fdisp_destroy(&fdi); return err; @@ -1655,6 +1667,7 @@ if (!err && sizechanged) { fuse_invalidate_attr(vp); fuse_vnode_setsize(vp, cred, newsize); + VTOFUD(vp)->flag &= ~FN_SIZECHANGE; } return err;home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107260610.p6Q6AYYw042706>
