PERFORCE change 197356 for review

Ilya Putsikau ilya at FreeBSD.org
Mon Aug 8 13:02:01 UTC 2011


http://p4web.freebsd.org/@@197356?ac=10

Change 197356 by ilya at ilya_triton2011 on 2011/08/08 13:01:12

	Change version to 0.4.4
	Fix memory leak in fuse_read_directbackend
	Make options per file system, check global sysctl values first
	Add helper functions to track operations implemented by daemon
	Add workround for broken io
	Close directory filehandles in vnop_close()
	Fixes for broken file systems like smbnetfs

Affected files ...

.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_internal.c#2 edit
.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_io.c#3 edit
.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_ipc.h#3 edit
.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_node.c#3 edit
.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_node.h#3 edit
.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_version.h#3 edit
.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_vfsops.c#2 edit
.. //depot/projects/soc2011/ilya_fuse/fuse/fuse_vnops.c#4 edit
.. //depot/projects/soc2011/ilya_fuse/mount_fusefs/mount_fusefs.c#3 edit

Differences ...

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_internal.c#2 (text+ko) ====

@@ -106,7 +106,7 @@
 #endif
     }
 
-    if (fuse_get_mpdata(mp)->dataflags & FSESS_NOACCESS) {
+    if (!fsess_isimpl(mp, FUSE_ACCESS)) {
         // Let the kernel handle this.
         return 0;
     }
@@ -146,7 +146,7 @@
     fdisp_destroy(&fdi);
 
     if (err == ENOSYS) {
-        fuse_get_mpdata(mp)->dataflags |= FSESS_NOACCESS;
+        fsess_set_notimpl(mp, FUSE_ACCESS);
         err = 0;
     }
 
@@ -161,8 +161,7 @@
     fuse_trace_printf_func();
 
     if (tick->tk_aw_ohead.error == ENOSYS) {
-        tick->tk_data->dataflags |= (fticket_opcode(tick) == FUSE_FSYNC) ?
-                                        FSESS_NOFSYNC : FSESS_NOFSYNCDIR;
+        fsess_set_notimpl(tick->tk_data->mp, fticket_opcode(tick));
     }
 
     return 0;

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_io.c#3 (text+ko) ====

@@ -79,7 +79,7 @@
      * we hardwire it into the file's private data (similarly to Linux,
      * btw.).
      */
-    directio = (ioflag & IO_DIRECT) || !fuse_vnode_cache_enable(vp);
+    directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp));
 
     switch (uio->uio_rw) {
     case UIO_READ:
@@ -246,13 +246,12 @@
 
         if ((err = uiomove(fdi.answ, MIN(fri->size, fdi.iosize), uio)))
             break;
-	if (fdi.iosize < fri->size)
-		break;
+        if (fdi.iosize < fri->size)
+            break;
     }
 
+out:
     fdisp_destroy(&fdi);
-
-out:
     return (err);
 }
 
@@ -594,7 +593,10 @@
         uiop->uio_offset = ((off_t)bp->b_blkno) * biosize;
         error = fuse_read_directbackend(vp, uiop, cred, fufh);
 
-        if (!error && uiop->uio_resid) {
+        if ((!error && uiop->uio_resid) ||
+            (fsess_opt_brokenio(vnode_mount(vp)) && error == EIO &&
+            uiop->uio_offset < fvdat->filesize && fvdat->filesize > 0 &&
+            uiop->uio_offset >= fvdat->cached_attrs.va_size)) {
             /*
              * If we had a short read with no error, we must have
              * hit a file hole.  We should zero-fill the remainder.
@@ -606,6 +608,14 @@
             int nread = bp->b_bcount - uiop->uio_resid;
             int left  = uiop->uio_resid;
 
+            if (error != 0) {
+                printf("FUSE: Fix broken io: offset %ju, resid %zd, "
+                    "file size %ju/%ju\n", (uintmax_t)uiop->uio_offset,
+                    uiop->uio_resid, fvdat->filesize,
+                    fvdat->cached_attrs.va_size);
+                error = 0;
+            }
+
             if (left > 0)
                 bzero((char *)bp->b_data + nread, left);
             uiop->uio_resid = 0;

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_ipc.h#3 (text+ko) ====

@@ -151,25 +151,28 @@
     struct selinfo ks_rsel;
 
     int                        daemon_timeout;
+    uint64_t                   notimpl;
 };
 
 #define FSESS_DEAD                0x0001 // session is to be closed
 #define FSESS_OPENED              0x0002 // session device has been opened
-#define FSESS_NOFSYNC             0x0004 // daemon doesn't implement fsync
-#define FSESS_NOFSYNCDIR          0x0008 // daemon doesn't implement fsyncdir
-#define FSESS_NOACCESS            0x0010 // daemon doesn't implement access
-#define FSESS_NOCREATE            0x0020 // daemon doesn't implement create
-#define FSESS_INITED              0x0040 // session has been inited
-#define FSESS_DAEMON_CAN_SPY      0x0080 // let non-owners access this fs
+#define FSESS_INITED              0x0004 // session has been inited
+#define FSESS_DAEMON_CAN_SPY      0x0010 // let non-owners access this fs
                                          // (and being observed by the daemon)
-#define FSESS_NEGLECT_SHARES      0x0100 // presence of secondary mount is not
-                                         // considered as "fs is busy"
-#define FSESS_PRIVATE             0x0200 // don't allow secondary mounts
-#define FSESS_PUSH_SYMLINKS_IN    0x0400 // prefix absolute symlinks with mp
-#define FSESS_DEFAULT_PERMISSIONS 0x0800 // kernel does permission checking
-#define FSESS_NO_ATTRCACHE        0x1000 // no attribute caching
-#define FSESS_NO_READAHEAD        0x2000 // no readaheads
-#define FSESS_NO_UBC              0x4000 // no caching
+#define FSESS_PUSH_SYMLINKS_IN    0x0020 // prefix absolute symlinks with mp
+#define FSESS_DEFAULT_PERMISSIONS 0x0040 // kernel does permission checking
+#define FSESS_NO_ATTRCACHE        0x0080 // no attribute caching
+#define FSESS_NO_READAHEAD        0x0100 // no readaheads
+#define FSESS_NO_DATACACHE        0x0200 // disable buffer cache
+#define FSESS_NO_NAMECACHE        0x0400 // disable name cache
+#define FSESS_NO_MMAP             0x0800 // disable mmap
+#define FSESS_BROKENIO            0x1000 // fix broken io
+
+extern int fuse_data_cache_enable;
+extern int fuse_data_cache_invalidate;
+extern int fuse_mmap_enable;
+extern int fuse_sync_resize;
+extern int fuse_fix_broken_io;
 
 static __inline__
 struct fuse_data *
@@ -185,6 +188,49 @@
     return mp->mnt_data;
 }
 
+static __inline int
+fsess_isimpl(struct mount *mp, int opcode)
+{
+    struct fuse_data *data = fuse_get_mpdata(mp);
+
+    return (data->notimpl & (1ULL << opcode)) == 0;
+
+}
+static __inline void
+fsess_set_notimpl(struct mount *mp, int opcode)
+{
+    struct fuse_data *data = fuse_get_mpdata(mp);
+
+    data->notimpl |= (1ULL << opcode);
+}
+
+static __inline int
+fsess_opt_datacache(struct mount *mp)
+{
+    struct fuse_data *data = fuse_get_mpdata(mp);
+
+    return (fuse_data_cache_enable ||
+        (data->dataflags & FSESS_NO_DATACACHE) == 0);
+}
+
+static __inline int
+fsess_opt_mmap(struct mount *mp)
+{
+    struct fuse_data *data = fuse_get_mpdata(mp);
+
+    if (!(fuse_mmap_enable && fuse_data_cache_enable))
+        return 0;
+    return ((data->dataflags & (FSESS_NO_DATACACHE | FSESS_NO_MMAP)) == 0);
+}
+
+static __inline int
+fsess_opt_brokenio(struct mount *mp)
+{
+    struct fuse_data *data = fuse_get_mpdata(mp);
+
+    return (fuse_fix_broken_io || (data->dataflags & FSESS_BROKENIO));
+}
+
 static __inline__
 void
 fuse_ms_push(struct fuse_ticket *ftick)

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_node.c#3 (text+ko) ====

@@ -63,6 +63,10 @@
 SYSCTL_INT(_vfs_fuse, OID_AUTO, sync_resize, CTLFLAG_RW,
            &fuse_sync_resize, 0, "");
 
+int fuse_fix_broken_io = 0;
+SYSCTL_INT(_vfs_fuse, OID_AUTO, fix_broken_io, CTLFLAG_RW,
+           &fuse_fix_broken_io, 0, "");
+
 static void
 fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat,
     uint64_t nodeid, enum vtype vtyp)

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_node.h#3 (text+ko) ====

@@ -47,10 +47,6 @@
 #define FUSE_NULL_ID 0
 
 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
@@ -61,18 +57,6 @@
     }
 }
 
-static __inline int
-fuse_vnode_cache_enable(struct vnode *vp)
-{
-    return (fuse_data_cache_enable);
-}
-
-static __inline int
-fuse_vnode_mmap_enable(struct vnode *vp)
-{
-    return (fuse_mmap_enable && fuse_data_cache_enable);
-}
-
 static __inline void
 fuse_vnode_setparent(struct vnode *vp, struct vnode *dvp)
 {

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_version.h#3 (text+ko) ====

@@ -1,3 +1,3 @@
 #ifndef FUSE_FREEBSD_VERSION
-#define FUSE_FREEBSD_VERSION	"0.4.3"
+#define FUSE_FREEBSD_VERSION	"0.4.4"
 #endif

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_vfsops.c#2 (text+ko) ====

@@ -193,16 +193,15 @@
      * With the help of underscored options the mount program
      * can inform us from the flags it sets by default
      */
-    FUSE_FLAGOPT(private, FSESS_PRIVATE);
-    FUSE_FLAGOPT(neglect_shares, FSESS_NEGLECT_SHARES);
     FUSE_FLAGOPT(allow_other, FSESS_DAEMON_CAN_SPY);
     FUSE_FLAGOPT(push_symlinks_in, FSESS_PUSH_SYMLINKS_IN);
     FUSE_FLAGOPT(default_permissions, FSESS_DEFAULT_PERMISSIONS);
-#ifdef XXXIP
-#if FUSE_HAS_DESTROY
-    FUSE_FLAGOPT(sync_unmount, FSESS_SYNC_UNMOUNT);
-#endif
-#endif
+    FUSE_FLAGOPT(no_attrcache, FSESS_NO_ATTRCACHE);
+    FUSE_FLAGOPT(no_readahed, FSESS_NO_READAHEAD);
+    FUSE_FLAGOPT(no_datacache, FSESS_NO_DATACACHE);
+    FUSE_FLAGOPT(no_namecache, FSESS_NO_NAMECACHE);
+    FUSE_FLAGOPT(no_mmap, FSESS_NO_MMAP);
+    FUSE_FLAGOPT(brokenio, FSESS_BROKENIO);
 
     if (vfs_scanopt(opts, "max_read=", "%u", &max_read) == 1)
     max_read_set = 1;

==== //depot/projects/soc2011/ilya_fuse/fuse/fuse_vnops.c#4 (text+ko) ====

@@ -208,7 +208,6 @@
     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;
 
     fuse_trace_printf_vnop();
@@ -217,15 +216,18 @@
         return 0;
     }
 
+    if (vnode_isdir(vp)) {
+        if (fuse_filehandle_valid(vp, FUFH_RDONLY)) {
+            fuse_filehandle_close(vp, FUFH_RDONLY, NULL, cred);
+        }
+        return 0;
+    }
+
     if (fflag & IO_NDELAY) {
         return 0;
     }
 
-    if (isdir) {
-        fufh_type = FUFH_RDONLY;
-    } else {
-        fufh_type = fuse_filehandle_xlate_from_fflags(fflag);
-    }
+    fufh_type = fuse_filehandle_xlate_from_fflags(fflag);
 
     if (!fuse_filehandle_valid(vp, fufh_type)) {
         int i;
@@ -284,15 +286,14 @@
     bzero(&fdi, sizeof(fdi));
 
     // XXX: Will we ever want devices?
-    if ((vap->va_type != VREG) ||
-        fuse_get_mpdata(mp)->dataflags & FSESS_NOCREATE) {
+    if ((vap->va_type != VREG) || !fsess_isimpl(mp, FUSE_CREATE)) {
         goto good_old;
     }
 
     debug_printf("parent nid = %ju, mode = %x\n", (uintmax_t)parentnid, mode);
 
     fdisp_init(fdip, sizeof(*foi) + cnp->cn_namelen + 1);
-    if (fuse_get_mpdata(vnode_mount(dvp))->dataflags & FSESS_NOCREATE) {
+    if (!fsess_isimpl(mp, FUSE_CREATE)) {
         debug_printf("eh, daemon doesn't implement create?\n");
         goto good_old;
     }
@@ -311,7 +312,7 @@
 
     if (err == ENOSYS) {
         debug_printf("create: got ENOSYS from daemon\n");
-        fuse_get_mpdata(vnode_mount(dvp))->dataflags |= FSESS_NOCREATE;
+        fsess_set_notimpl(mp, FUSE_CREATE);
         fdisp_destroy(fdip);
         goto good_old;
     } else if (err) {
@@ -421,8 +422,8 @@
     if ((err = vop_stdfsync(ap)))
         return err;
 
-    if (!(fuse_get_mpdata(vnode_mount(vp))->dataflags &
-        (vnode_vtype(vp) == VDIR ? FSESS_NOFSYNCDIR : FSESS_NOFSYNC))) {
+    if (!fsess_isimpl(vnode_mount(vp),
+        (vnode_vtype(vp) == VDIR ? FUSE_FSYNCDIR : FUSE_FSYNC))) {
         goto out;
     }
 
@@ -1830,7 +1831,7 @@
 	pages = ap->a_m;
 	count = ap->a_count;
 
-	if (!fuse_vnode_mmap_enable(vp)) {
+	if (!fsess_opt_mmap(vnode_mount(vp))) {
 		DEBUG("called on non-cacheable vnode??\n");
 		return (VM_PAGER_ERROR);
 	}
@@ -2014,7 +2015,7 @@
 	npages = btoc(count);
 	offset = IDX_TO_OFF(pages[0]->pindex);
 
-	if (!fuse_vnode_mmap_enable(vp)) {
+	if (!fsess_opt_mmap(vnode_mount(vp))) {
 		DEBUG("called on non-cacheable vnode??\n");
 	}
 

==== //depot/projects/soc2011/ilya_fuse/mount_fusefs/mount_fusefs.c#3 (text+ko) ====

@@ -77,6 +77,13 @@
 	{ "large_read",          0, 0x00, 1 },
 	/* "nonempty", just the first two chars are stripped off during parsing */
 	{ "nempty",              0, 0x00, 1 },
+	{ "no_attrcache",        0, 0x00, 1 },
+	{ "no_readahed",         0, 0x00, 1 },
+	{ "no_datacache",        0, 0x00, 1 },
+	{ "no_namecache",        0, 0x00, 1 },
+	{ "no_mmap",             0, 0x00, 1 },
+	{ "brokenio",            0, 0x00, 1 },
+
 	MOPT_STDOPTS,
 	MOPT_END
 };


More information about the p4-projects mailing list