Date: Mon, 8 Aug 2011 13:02:00 GMT From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 197356 for review Message-ID: <201108081302.p78D20Wc026083@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@197356?ac=10 Change 197356 by ilya@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 };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108081302.p78D20Wc026083>