Date: Tue, 7 Jun 2011 10:57:21 GMT From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 194384 for review Message-ID: <201106071057.p57AvLg2053201@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@194384?ac=10 Change 194384 by ilya@ilya_triton2011 on 2011/06/07 10:56:33 fuse_vnops.c reduce diffs Affected files ... .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#9 edit Differences ... ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#9 (text+ko) ==== @@ -348,18 +348,22 @@ static int fuse_vnop_access(struct vop_access_args *ap) { - struct vnode *vp = ap->a_vp; - struct fuse_access_param facp; - struct fuse_vnode_data *fvdat = VTOFUD(vp); + struct vnode *vp = ap->a_vp; + struct fuse_access_param facp; + struct fuse_vnode_data *fvdat = VTOFUD(vp); + + fuse_trace_printf_vnop(); + + bzero(&facp, sizeof(facp)); - bzero(&facp, sizeof(facp)); - if (fvdat->flags & FVP_ACCESS_NOOP) - fvdat->flags &= ~FVP_ACCESS_NOOP; - else - facp.facc_flags |= FACCESS_DO_ACCESS; + if (fvdat->flags & FVP_ACCESS_NOOP) { + fvdat->flags &= ~FVP_ACCESS_NOOP; + } else { + facp.facc_flags |= FACCESS_DO_ACCESS; + } - return fuse_internal_access(vp, ap->a_accmode, - ap->a_cred, ap->a_td, &facp); + return fuse_internal_access(vp, ap->a_accmode, + ap->a_cred, ap->a_td, &facp); } /* @@ -373,20 +377,20 @@ static int fuse_vnop_close(struct vop_close_args *ap) { - struct fuse_release_param frp; + struct fuse_release_param frp; - DEBUG2G("vnode #%llu\n", VTOILLU(ap->a_vp)); - frp.err = 0; + DEBUG2G("vnode #%llu\n", VTOILLU(ap->a_vp)); + frp.err = 0; #if FUSE_HAS_FLUSH_RELEASE - frp.fg = 1; - frp.flush = 1; + frp.fg = 1; + frp.flush = 1; #else - frp.fg = 0; - frp.flush = 0; + frp.fg = 0; + frp.flush = 0; #endif - fuse_filehandle_gc(ap->a_vp, ap->a_td, ap->a_cred, &frp); + fuse_filehandle_gc(ap->a_vp, ap->a_td, ap->a_cred, &frp); - return (frp.err); + return (frp.err); } /* @@ -400,57 +404,57 @@ static int fuse_vnop_create(struct vop_create_args *ap) { - struct vnode *dvp = ap->a_dvp; - struct vnode **vpp = ap->a_vpp; - struct vattr *vap = ap->a_vap; + struct vnode *dvp = ap->a_dvp; + struct vnode **vpp = ap->a_vpp; + struct vattr *vap = ap->a_vap; #if FUSE_HAS_CREATE - struct fuse_vnode_data *fvdat; - int err; + struct fuse_vnode_data *fvdat; + int err; - if (vap->va_type != VREG || - fusefs_get_data(dvp->v_mount)->dataflag & FSESS_NOCREATE) - goto good_old; + if (vap->va_type != VREG || + fusefs_get_data(dvp->v_mount)->dataflag & FSESS_NOCREATE) + goto good_old; - /* - * We cobble together here a new vnode as the caller expects that, - * but we don't yet fully initialize it (that will happen when it - * will be opened). We keep it in a "germic" state. - */ - if ((err = getnewvnode("fuse", dvp->v_mount, &fuse_vnops, vpp))) - return (err); + /* + * We cobble together here a new vnode as the caller expects that, + * but we don't yet fully initialize it (that will happen when it + * will be opened). We keep it in a "germic" state. + */ + if ((err = getnewvnode("fuse", dvp->v_mount, &fuse_vnops, vpp))) + return (err); - if ((err = vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY))) { - printf("fuse4bsd: leaking vnode %p\n", *vpp); - return (err); - } + if ((err = vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY))) { + printf("fuse4bsd: leaking vnode %p\n", *vpp); + return (err); + } - fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO); + fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO); - fvdat->parent_nid = VTOI(dvp); - /* - * We overload some fields of the vnode data to carry the information - * which will be needed to make the proper CREATE query in open. - * germcnp is a dedicated field for this purpose though. - */ - fvdat->flags = MAKEIMODE(vap->va_type, vap->va_mode); - fvdat->germcnp = ap->a_cnp; + fvdat->parent_nid = VTOI(dvp); + /* + * We overload some fields of the vnode data to carry the information + * which will be needed to make the proper CREATE query in open. + * germcnp is a dedicated field for this purpose though. + */ + fvdat->flags = MAKEIMODE(vap->va_type, vap->va_mode); + fvdat->germcnp = ap->a_cnp; - /* - * Stub vnops, almost the same as "dead", with the exception of the - * critical ones which will let the vnode get fully emerged. - */ - (*vpp)->v_op = &fuse_germ_vnops; - (*vpp)->v_data = fvdat; - (*vpp)->v_mount = dvp->v_mount; + /* + * Stub vnops, almost the same as "dead", with the exception of the + * critical ones which will let the vnode get fully emerged. + */ + (*vpp)->v_op = &fuse_germ_vnops; + (*vpp)->v_data = fvdat; + (*vpp)->v_mount = dvp->v_mount; - fuse_invalidate_attr(dvp); + fuse_invalidate_attr(dvp); - return (0); + return (0); good_old: #endif - vap->va_rdev = 0; - return (VOP_MKNOD(dvp, vpp, ap->a_cnp, vap)); + vap->va_rdev = 0; + return (VOP_MKNOD(dvp, vpp, ap->a_cnp, vap)); } /* @@ -477,84 +481,85 @@ static int fuse_vnop_fsync(struct vop_fsync_args *ap) { - struct vnode *vp = ap->a_vp; - struct thread *td = ap->a_td; + struct vnode *vp = ap->a_vp; + struct thread *td = ap->a_td; + struct fuse_dispatcher fdi; - int err = 0; - struct fuse_dispatcher fdi; + int err = 0; - DEBUG("got flag %d\n", ap->a_waitfor); + DEBUG("got flag %d\n", ap->a_waitfor); - /* - * Usually, the call to vop_stdfsync is expected to do nothing, as we - * tend to leave no dirty buffers behind. However, they might show up, - * eg., after an interrupted write. - * To be able to release the kernel's cleanup-dirty-buffers machinery - * this is advised to be inserted here. - */ + /* + * Usually, the call to vop_stdfsync is expected to do nothing, as we + * tend to leave no dirty buffers behind. However, they might show up, + * eg., after an interrupted write. + * To be able to release the kernel's cleanup-dirty-buffers machinery + * this is advised to be inserted here. + */ - if ((err = vop_stdfsync(ap))) - return (err); + if ((err = vop_stdfsync(ap))) + return (err); - /* - * In Linux, the fsync syscall handler is file based. - * Hence in fuse too -- and this approach does make sense, - * for exapmle, when it comes to implementing things like - * sshfs: the sshfs userspace fsync handler flushes data - * associated with the given filehandle, ie. sftp - * messaging thread. - * - * On the other hand, BSD fsync is inherently not file - * but vnode based: even fsync(2), to which one passes - * a file descriptor, the corresponding file is used for - * nothing but looking up the vnode behind (see fsync() - * in kern/vfs_syscalls.c). - * - * We have thus two choices here: either grab the first - * open file and use that for the fsync message or run - * through all files (at least, the ones we have acces to, - * ie., those belonging to the current process). The first - * is bad: as we mentioned concerning sshfs, dirty data can belong - * to each ssh messaging thread, being associated to file - * handles independently. - * - * So we wanna sync all our open files. "Nowait" sync is easy, - * just walk over all the files, and send FUSE_FSYNC(DIR) with - * a null callback, and leave. "Wait" sync is harder: syncing - * the files linearly, one after the other would be very easy - * indeed but would be far more than a lethal dose of the KISS - * principle. So sending of the messages and waiting for them - * should be done synchronously. The messaging backend is flexible - * enough for making the implementation of this not too hard, - * but now I don't wanna go mucking with the proper handling of - * interrupts, and other issues; and I don't wanna break the nice - * hi-level messaging API which serves us well otherwise. So - * currently I just say no here... - * - * Just to note: even the "nowait" type fsync could be optimized - * if we went beyond the api, and lock/unlock all mutexes (tickets', - * messages', callbacks') only once, and take out/put in stuff for all - * files together, with one big breath. But doing not so is not as much - * overhead as it would be worth for the trouble. - */ + /* + * In Linux, the fsync syscall handler is file based. + * Hence in fuse too -- and this approach does make sense, + * for exapmle, when it comes to implementing things like + * sshfs: the sshfs userspace fsync handler flushes data + * associated with the given filehandle, ie. sftp + * messaging thread. + * + * On the other hand, BSD fsync is inherently not file + * but vnode based: even fsync(2), to which one passes + * a file descriptor, the corresponding file is used for + * nothing but looking up the vnode behind (see fsync() + * in kern/vfs_syscalls.c). + * + * We have thus two choices here: either grab the first + * open file and use that for the fsync message or run + * through all files (at least, the ones we have acces to, + * ie., those belonging to the current process). The first + * is bad: as we mentioned concerning sshfs, dirty data can belong + * to each ssh messaging thread, being associated to file + * handles independently. + * + * So we wanna sync all our open files. "Nowait" sync is easy, + * just walk over all the files, and send FUSE_FSYNC(DIR) with + * a null callback, and leave. "Wait" sync is harder: syncing + * the files linearly, one after the other would be very easy + * indeed but would be far more than a lethal dose of the KISS + * principle. So sending of the messages and waiting for them + * should be done synchronously. The messaging backend is flexible + * enough for making the implementation of this not too hard, + * but now I don't wanna go mucking with the proper handling of + * interrupts, and other issues; and I don't wanna break the nice + * hi-level messaging API which serves us well otherwise. So + * currently I just say no here... + * + * Just to note: even the "nowait" type fsync could be optimized + * if we went beyond the api, and lock/unlock all mutexes (tickets', + * messages', callbacks') only once, and take out/put in stuff for all + * files together, with one big breath. But doing not so is not as much + * overhead as it would be worth for the trouble. + */ - /* - * It seemed to be a good idea to lock the filehandle lock only before - * doing iterate_filehandle but that configuration is suspected to cause - * LOR alerts, so now we get the filehandle lock before the fuse_data - * lock. - */ - ASSERT_VOP_LOCKED__FH(vp); + /* + * It seemed to be a good idea to lock the filehandle lock only before + * doing iterate_filehandle but that configuration is suspected to cause + * LOR alerts, so now we get the filehandle lock before the fuse_data + * lock. + */ + ASSERT_VOP_LOCKED__FH(vp); - if (fusefs_get_data(vp->v_mount)->dataflag & - (vp->v_type == VDIR ? FSESS_NOFSYNCDIR : FSESS_NOFSYNC)) - goto out; + if (fusefs_get_data(vp->v_mount)->dataflag & + (vp->v_type == VDIR ? FSESS_NOFSYNCDIR : FSESS_NOFSYNC)) { + goto out; + } - fdisp_init(&fdi, 0); - iterate_filehandles(vp, td, NULL, fuse_fsync_filehandle, &fdi); + fdisp_init(&fdi, 0); + iterate_filehandles(vp, td, NULL, fuse_fsync_filehandle, &fdi); out: - return (err); + return (err); } /* @@ -717,58 +722,62 @@ static int fuse_vnop_link(struct vop_link_args *ap) { - struct vnode *dvp = ap->a_tdvp; - struct vnode *vp = ap->a_vp; - struct componentname *cnp = ap->a_cnp; + struct vnode *vp = ap->a_vp; + struct vnode *tdvp = ap->a_tdvp; + struct componentname *cnp = ap->a_cnp; + + int err = 0; + struct fuse_dispatcher fdi; + struct fuse_entry_out *feo; + struct fuse_link_in fli; + + fuse_trace_printf_vnop(); - struct fuse_dispatcher fdi; - struct fuse_link_in fli; - struct fuse_entry_out *feo; - int err = 0; + if (tdvp->v_mount != vp->v_mount) { + return (EXDEV); + } - if (dvp->v_mount != vp->v_mount) - return (EXDEV); + fli.oldnodeid = VTOI(vp); - fli.oldnodeid = VTOI(vp); + /* + * Unlike Linux, we proceed here lazily: here we do nothing on + * the kernel side for registering the new, hardlinked entry. + * (That will just happen when the hardlinked entry is looked up + * first time). We just send the request to the daemon. + * This suits better for the BSD VFS. + */ - /* - * Unlike Linux, we proceed here lazily: here we do nothing on - * the kernel side for registering the new, hardlinked entry. - * (That will just happen when the hardlinked entry is looked up - * first time). We just send the request to the daemon. - * This suits better for the BSD VFS. - */ + fdisp_init(&fdi, 0); + fuse_internal_newentry_makerequest(tdvp->v_mount, VTOI(tdvp), cnp, + FUSE_LINK, &fli, sizeof(fli), &fdi); + if ((err = fdisp_wait_answ(&fdi))) { + return (err); + } - fdisp_init(&fdi, 0); - fuse_internal_newentry_makerequest(dvp->v_mount, VTOI(dvp), cnp, FUSE_LINK, &fli, - sizeof(fli), &fdi); - if ((err = fdisp_wait_answ(&fdi))) - return (err); - - feo = fdi.answ; + feo = fdi.answ; - err = fuse_internal_checkentry(feo, vp->v_type); + err = fuse_internal_checkentry(feo, vp->v_type); - fuse_ticket_drop(fdi.tick); - fuse_invalidate_attr(dvp); - /* - * It depends on userspace if the hardlinked entry is really the - * same vnode or not. Sort of unconventionally, the latter happens - * if linking is managed by the hi-level FUSE library (in which case - * syncing between the two nodes is up to the actual fs code). - * Therefore we can't just cache the attrs we got for the hardlink node, - * -- that regards to the hardlinked node and not the original. - * What we do instead is invalidating cached attrs of the original so - * the fs gets a chance to pass on updated attributes also for the - * original node. - * - * See also remark at the similar place in the Linux kernel code. - */ - fuse_invalidate_attr(vp); + fuse_ticket_drop(fdi.tick); + fuse_invalidate_attr(tdvp); + /* + * It depends on userspace if the hardlinked entry is really the + * same vnode or not. Sort of unconventionally, the latter happens + * if linking is managed by the hi-level FUSE library (in which case + * syncing between the two nodes is up to the actual fs code). + * Therefore we can't just cache the attrs we got for the hardlink node, + * -- that regards to the hardlinked node and not the original. + * What we do instead is invalidating cached attrs of the original so + * the fs gets a chance to pass on updated attributes also for the + * original node. + * + * See also remark at the similar place in the Linux kernel code. + */ + fuse_invalidate_attr(vp); - VTOFUD(vp)->nlookup++; + VTOFUD(vp)->nlookup++; - return (err); + return (err); } /* @@ -782,412 +791,419 @@ int fuse_vnop_lookup(struct vop_lookup_args *ap) { - struct vnode *dvp = ap->a_dvp; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - int nameiop = cnp->cn_nameiop; - struct thread *td = cnp->cn_thread; - struct ucred *cred = cnp->cn_cred; - int flags = cnp->cn_flags; - int wantparent = flags & WANTPARENT; - int islastcn = flags & ISLASTCN; + struct componentname *cnp = ap->a_cnp; + int nameiop = cnp->cn_nameiop; + int flags = cnp->cn_flags; + int wantparent = flags & WANTPARENT; + int islastcn = flags & ISLASTCN; + struct vnode *dvp = ap->a_dvp; + struct vnode **vpp = ap->a_vpp; + struct thread *td = cnp->cn_thread; + struct ucred *cred = cnp->cn_cred; + + fuse_trace_printf_vnop(); - int err = 0; - int lookup_err = 0; - struct vnode *vp = NULL; - struct fuse_dispatcher fdi; - struct fuse_attr *fattr = NULL; - enum fuse_opcode op; - uint64_t nid; - uint64_t parentid; - struct fuse_access_param facp; + int err = 0; + int lookup_err = 0; + struct vnode *vp = NULL; + struct fuse_attr *fattr = NULL; + struct fuse_dispatcher fdi; + enum fuse_opcode op; + uint64_t nid, parentid; + struct fuse_access_param facp; #ifdef INVARIANTS - int cache_attrs_hit = 0; + int cache_attrs_hit = 0; #endif - /* general stuff, based on vfs_cache_lookup */ + /* general stuff, based on vfs_cache_lookup */ #if _DEBUG - DEBUG2G("root node:\n"); - vn_printf(fusefs_get_data(dvp->v_mount)->rvp, " * "); + DEBUG2G("root node:\n"); + vn_printf(fusefs_get_data(dvp->v_mount)->rvp, " * "); #endif - if (dvp->v_type != VDIR) { - DEBUG("vnode #%llu of vtype %d is not a dir\n", VTOILLU(dvp), - dvp->v_type); - return (ENOTDIR); - } + if (dvp->v_type != VDIR) { + return ENOTDIR; + } - if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) && - (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) - return (EROFS); + if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) && + (nameiop == DELETE || nameiop == RENAME)) { + return (EROFS); + } - /* - * We do access check prior to doing anything else only in the case - * when we are at fs root (we'd like to say, "we are at the first - * component", but that's not exactly the same... nevermind). - * See further comments at further access checks. - */ + /* + * We do access check prior to doing anything else only in the case + * when we are at fs root (we'd like to say, "we are at the first + * component", but that's not exactly the same... nevermind). + * See further comments at further access checks. + */ - bzero(&facp, sizeof(facp)); - if ( + bzero(&facp, sizeof(facp)); + if ( #ifdef NO_EARLY_PERM_CHECK_HACK - 1 + 1 #else - dvp->v_vflag & VV_ROOT + dvp->v_vflag & VV_ROOT #endif - ) { - if ((err = fuse_internal_access(dvp, VEXEC, cred, td, &facp))) - return (err); - } + ) { + if ((err = fuse_internal_access(dvp, VEXEC, cred, td, &facp))) + return err; + } - DEBUG2G("lookup in #%llu, nameiop %lu, with flags %#x\n", - VTOILLU(dvp), cnp->cn_nameiop, flags); + DEBUG2G("lookup in #%llu, nameiop %lu, with flags %#x\n", + VTOILLU(dvp), cnp->cn_nameiop, flags); - /* fetching data from "storage" */ + /* fetching data from "storage" */ - if (flags & ISDOTDOT) { - DEBUG2G("dotdot lookup!\n"); - nid = VTOFUD(dvp)->parent_nid; - parentid = FUSE_NULL_ID; - fdisp_init(&fdi, 0); - op = FUSE_GETATTR; - } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') { - DEBUG2G("dot lookup!\n"); - nid = VTOI(dvp); - parentid = VTOFUD(dvp)->parent_nid; /* irrelevant */ - fdisp_init(&fdi, 0); - op = FUSE_GETATTR; - } else { - nid = VTOI(dvp); - parentid = VTOI(dvp); - fdisp_init(&fdi, cnp->cn_namelen + 1); - op = FUSE_LOOKUP; - } + if (flags & ISDOTDOT) { + DEBUG2G("dotdot lookup!\n"); + nid = VTOFUD(dvp)->parent_nid; + parentid = FUSE_NULL_ID; + fdisp_init(&fdi, 0); + op = FUSE_GETATTR; + } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') { + DEBUG2G("dot lookup!\n"); + nid = VTOI(dvp); + parentid = VTOFUD(dvp)->parent_nid; /* irrelevant */ + fdisp_init(&fdi, 0); + op = FUSE_GETATTR; + } else { + nid = VTOI(dvp); + parentid = VTOI(dvp); + fdisp_init(&fdi, cnp->cn_namelen + 1); + op = FUSE_LOOKUP; + } - fdisp_make(&fdi, dvp->v_mount, op, nid, td, cred); + fdisp_make(&fdi, dvp->v_mount, op, nid, td, cred); - if (op == FUSE_LOOKUP) { - memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); - ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; - DEBUG2G("standard lookup, looking up %s\n", (char *)fdi.indata); - } + if (op == FUSE_LOOKUP) { + memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); + ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; + DEBUG2G("standard lookup, looking up %s\n", (char *)fdi.indata); + } - lookup_err = fdisp_wait_answ(&fdi); + lookup_err = fdisp_wait_answ(&fdi); - if (op == FUSE_LOOKUP && ! lookup_err) { - nid = ((struct fuse_entry_out *)fdi.answ)->nodeid; - if (! nid) { - /* - * zero nodeid is the same as "not found", - * but it's also cacheable (which we keep - * keep on doing not as of writing this) - */ - DEBUG2G("zero nid, ie ENOENT\n"); - lookup_err = ENOENT; - } else if (nid == FUSE_ROOT_ID) { - DEBUG2G("root inode found on lookup?!!\n"); - lookup_err = EINVAL; - } - } + if (op == FUSE_LOOKUP && !lookup_err) { + nid = ((struct fuse_entry_out *)fdi.answ)->nodeid; + if (!nid) { + /* + * zero nodeid is the same as "not found", + * but it's also cacheable (which we keep + * keep on doing not as of writing this) + */ + DEBUG2G("zero nid, ie ENOENT\n"); + lookup_err = ENOENT; + } else if (nid == FUSE_ROOT_ID) { + DEBUG2G("root inode found on lookup?!!\n"); + lookup_err = EINVAL; + } + } - if (lookup_err && ( - (! fdi.answ_stat) || /* this means messaging error */ - lookup_err != ENOENT || /* daemon reported other error than "legal" ENOENT */ - op != FUSE_LOOKUP /* we tolerate ENOENT only when we sent a LOOKUP */ - )) { - /* - * There is error but not lookup related actually - * (messaging error) - */ - DEBUG("lookup failed b/c messaging crap\n"); - return (lookup_err); - } + if (lookup_err && ( + (!fdi.answ_stat) || /* this means messaging error */ + lookup_err != ENOENT || /* daemon reported other error than "legal" ENOENT */ + op != FUSE_LOOKUP /* we tolerate ENOENT only when we sent a LOOKUP */ + )) { + /* + * There is error but not lookup related actually + * (messaging error) + */ + DEBUG("lookup failed b/c messaging crap\n"); + return (lookup_err); + } - /* analyzing answer */ + /* analyzing answer */ - /* - * Now we got the answer and filtered out the crap, too, so we know that - * "found" iff lookup_err == 0 - */ + /* + * Now we got the answer and filtered out the crap, too, so we know that + * "found" iff lookup_err == 0 + */ - if (lookup_err) { - DEBUG("looked up thingy not found\n"); - if ((nameiop == CREATE || nameiop == RENAME) - && islastcn - /* && directory dvp has not been removed */) { + if (lookup_err) { + DEBUG("looked up thingy not found\n"); + if ((nameiop == CREATE || nameiop == RENAME) + && islastcn + /* && directory dvp has not been removed */) { - if (dvp->v_mount->mnt_flag & MNT_RDONLY) { - err = EROFS; - goto out; - } + if (dvp->v_mount->mnt_flag & MNT_RDONLY) { + err = EROFS; + goto out; + } - DEBUG("create/rename -- we have to make it\n"); - /* - * Check for write access on directory. - */ - - if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) - goto out; + DEBUG("create/rename -- we have to make it\n"); + /* + * Check for write access on directory. + */ + + if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) + goto out; - /* - * Possibly record the position of a slot in the - * directory large enough for the new component name. - * This can be recorded in the vnode private data for - * dvp. Set the SAVENAME flag to hold onto the - * pathname for use later in VOP_CREATE or VOP_RENAME. - */ - cnp->cn_flags |= SAVENAME; - - err = EJUSTRETURN; - goto out; - } + /* + * Possibly record the position of a slot in the + * directory large enough for the new component name. + * This can be recorded in the vnode private data for + * dvp. Set the SAVENAME flag to hold onto the + * pathname for use later in VOP_CREATE or VOP_RENAME. + */ + cnp->cn_flags |= SAVENAME; + + err = EJUSTRETURN; + goto out; + } - /* - * Consider inserting name into cache. - */ + /* + * Consider inserting name into cache. + */ - /* - * No we can't use negative caching, as the fs - * changes are out of our control. - * False positives' falseness turns out just as things - * go by, but false negatives' falseness doesn't. - * (and aiding the caching mechanism with extra control - * mechanisms comes quite close to beating the whole purpose - * caching...) - */ + /* + * No we can't use negative caching, as the fs + * changes are out of our control. + * False positives' falseness turns out just as things + * go by, but false negatives' falseness doesn't. + * (and aiding the caching mechanism with extra control + * mechanisms comes quite close to beating the whole purpose + * caching...) + */ #if 0 - if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) { - DEBUG("inserting NULL into cache\n"); - cache_enter(dvp, NULL, cnp); - } + if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) { + DEBUG("inserting NULL into cache\n"); + cache_enter(dvp, NULL, cnp); + } #endif - err = ENOENT; - goto out; - } else { - if (op == FUSE_GETATTR) - fattr = &((struct fuse_attr_out *)fdi.answ)->attr; - else - fattr = &((struct fuse_entry_out *)fdi.answ)->attr; + err = ENOENT; + goto out; + + } else { + if (op == FUSE_GETATTR) { + fattr = &((struct fuse_attr_out *)fdi.answ)->attr; + } else { + fattr = &((struct fuse_entry_out *)fdi.answ)->attr; + } - DEBUG("we found something...\n"); - /* - * If deleting, and at end of pathname, return parameters - * which can be used to remove file. If the wantparent flag - * isn't set, we return only the directory, otherwise we go on - * and lock the inode, being careful with ".". - */ - if (nameiop == DELETE && islastcn) { - DEBUG("something to delete\n"); - /* - * Check for write access on directory. - */ + DEBUG("we found something...\n"); + /* + * If deleting, and at end of pathname, return parameters + * which can be used to remove file. If the wantparent flag + * isn't set, we return only the directory, otherwise we go on + * and lock the inode, being careful with ".". + */ + if (nameiop == DELETE && islastcn) { + DEBUG("something to delete\n"); + /* + * Check for write access on directory. + */ - facp.xuid = fattr->uid; - facp.facc_flags |= FACCESS_STICKY; - err = fuse_internal_access(dvp, VWRITE, cred, td, &facp); - facp.facc_flags &= ~FACCESS_XQUERIES; + facp.xuid = fattr->uid; + facp.facc_flags |= FACCESS_STICKY; + err = fuse_internal_access(dvp, VWRITE, cred, td, &facp); + facp.facc_flags &= ~FACCESS_XQUERIES; - if (err) - goto out; + if (err) { + goto out; + } - if (nid == VTOI(dvp)) { - VREF(dvp); - *vpp = dvp; - goto out; - } + if (nid == VTOI(dvp)) { + VREF(dvp); + *vpp = dvp; + goto out; + } - err = fuse_vget_i(dvp->v_mount, td, nid, - IFTOVT(fattr->mode), &vp, VG_NORMAL, - parentid); - if (err) - goto out; - *vpp = vp; + if ((err = fuse_vget_i(dvp->v_mount, td, + nid, + IFTOVT(fattr->mode), + &vp, + VG_NORMAL, + parentid))) { + goto out; + } - goto out; - } + *vpp = vp; + + goto out; + } - /* - * If rewriting (RENAME), return the inode and the - * information required to rewrite the present directory - * Must get inode of directory entry to verify it's a - * regular file, or empty directory. - */ - if (nameiop == RENAME && wantparent && islastcn) { - DEBUG("something to rename...\n"); + /* + * If rewriting (RENAME), return the inode and the + * information required to rewrite the present directory + * Must get inode of directory entry to verify it's a + * regular file, or empty directory. + */ + if (nameiop == RENAME && wantparent && islastcn) { + DEBUG("something to rename...\n"); - facp.xuid = fattr->uid; - facp.facc_flags |= FACCESS_STICKY; - err = fuse_internal_access(dvp, VWRITE, cred, td, &facp); - facp.facc_flags &= ~FACCESS_XQUERIES; + facp.xuid = fattr->uid; + facp.facc_flags |= FACCESS_STICKY; + err = fuse_internal_access(dvp, VWRITE, cred, td, &facp); + facp.facc_flags &= ~FACCESS_XQUERIES; - if (err) - goto out; + if (err) + goto out; - /* - * Check for "." - */ - if (nid == VTOI(dvp)) { - err = EISDIR; - goto out; - } + /* + * Check for "." + */ + if (nid == VTOI(dvp)) { + err = EISDIR; + goto out; + } - err = fuse_vget_i(dvp->v_mount, td, nid, - IFTOVT(fattr->mode), &vp, VG_NORMAL, - parentid); - if (err) - goto out; - *vpp = vp; - /* - * Save the name for use in VOP_RENAME later. - */ - cnp->cn_flags |= SAVENAME; + err = fuse_vget_i(dvp->v_mount, td, nid, + IFTOVT(fattr->mode), &vp, VG_NORMAL, + parentid); + if (err) + goto out; + *vpp = vp; + /* + * Save the name for use in VOP_RENAME later. + */ + cnp->cn_flags |= SAVENAME; - goto out; - } + goto out; + } - DEBUG("we peacefully found that file\n"); + DEBUG("we peacefully found that file\n"); - if (nid == VTOI(dvp)) { - VREF(dvp); /* We want ourself, ie "." */ - *vpp = dvp; - } else { - if (flags & ISDOTDOT) - /* - * If doing dotdot, we unlock dvp for vget time - * to conform lock order regulations. - */ - VOP_UNLOCK(dvp, 0); - err = fuse_vget_i(dvp->v_mount, td, nid, - IFTOVT(fattr->mode), &vp, VG_NORMAL, - parentid); - if (flags & ISDOTDOT) - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); - if (err) - goto out; - *vpp = vp; - } + if (nid == VTOI(dvp)) { + VREF(dvp); /* We want ourself, ie "." */ + *vpp = dvp; + } else { + if (flags & ISDOTDOT) + /* + * If doing dotdot, we unlock dvp for vget time + * to conform lock order regulations. + */ + VOP_UNLOCK(dvp, 0); + err = fuse_vget_i(dvp->v_mount, td, nid, + IFTOVT(fattr->mode), &vp, VG_NORMAL, + parentid); + if (flags & ISDOTDOT) + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); + if (err) + goto out; + *vpp = vp; + } - if (op == FUSE_GETATTR) - cache_attrs(*vpp, (struct fuse_attr_out *)fdi.answ); - else - cache_attrs(*vpp, (struct fuse_entry_out *)fdi.answ); + if (op == FUSE_GETATTR) + cache_attrs(*vpp, (struct fuse_attr_out *)fdi.answ); + else + cache_attrs(*vpp, (struct fuse_entry_out *)fdi.answ); #ifdef INVARIANTS - cache_attrs_hit = 1; + cache_attrs_hit = 1; #endif - /* Insert name into cache if appropriate. */ + /* Insert name into cache if appropriate. */ - /* - * Nooo, caching is evil. With caching, we can't avoid stale - * information taking over the playground (cached info is not - * just positive/negative, it does have qualitative aspects, - * too). And a (VOP/FUSE)_GETATTR is always thrown anyway, when - * walking down along cached path components, and that's not - * any cheaper than FUSE_LOOKUP. This might change with - * implementing kernel side attr caching, but... In Linux, - * lookup results are not cached, and the daemon is bombarded - * with FUSE_LOOKUPS on and on. This shows that by design, the - * daemon is expected to handle frequent lookup queries - * efficiently, do its caching in userspace, and so on. - * - * So just leave the name cache alone. - */ >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106071057.p57AvLg2053201>