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