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