PERFORCE change 196726 for review
Ilya Putsikau
ilya at FreeBSD.org
Tue Jul 26 06:10:35 UTC 2011
http://p4web.freebsd.org/@@196726?ac=10
Change 196726 by ilya at 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;
More information about the p4-projects
mailing list