Date: Mon, 13 Jun 2011 15:38:06 GMT From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 194685 for review Message-ID: <201106131538.p5DFc6Lc074644@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@194685?ac=10 Change 194685 by ilya@ilya_triton2011 on 2011/06/13 15:37:47 Simplify fuse_vfs_root, root vnode is handed by fuse_vnode_get Simplify fuse_vfs_statfs, merge macfuse Remove VFS hash comparators Affected files ... .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vfsops.c#10 edit Differences ... ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vfsops.c#10 (text+ko) ==== @@ -40,9 +40,6 @@ #define PRIV_VFS_FUSE_SYNC_UNMOUNT PRIV_VFS_MOUNT_NONUSER #endif - -static vfs_hash_cmp_t fuse_vnode_bgdrop_cmp; - static vfs_mount_t fuse_vfs_mount; static vfs_unmount_t fuse_vfs_unmount; static vfs_root_t fuse_vfs_root; @@ -69,57 +66,6 @@ extern struct vop_vector fuse_vnops; -/****************** - * - * >>> VFS hash comparators - * - ******************/ - -int -fuse_vnode_cmp(struct vnode *vp, void *nidp) -{ - return (VTOI(vp) != *((uint64_t *)nidp)); -} - -/* - * This comparator is used for safely setting the parent_nid. - */ - -int -fuse_vnode_setparent_cmp(struct vnode *vp, void *param) -{ - struct parentmanager_param *pmp = param; - - if (VTOI(vp) == pmp->nodeid) { - KASSERT(! pmp->valid, - ("more than one vnode seems to match #%llu", - (unsigned long long)pmp->nodeid)); - VTOFUD(vp)->parent_nid = pmp->parent_nid; - pmp->valid = 1; - } - - return (1); -} - -/* - * Vnode comparison function which expicitly marks - * clashing vnodes as unhashed (via setting id to 0) - * before dropping them. So at gc time we'll know if - * we have to remove the node from the hash. - */ - -static int -fuse_vnode_bgdrop_cmp(struct vnode *vp, void *param) -{ - struct fuse_vnode_data *fvdat = param; - - if (VTOI(vp) != fvdat->nid) - return (1); - - fvdat->nid = FUSE_NULL_ID; - return (0); -} - /************* * * >>> VFS ops @@ -541,309 +487,68 @@ return (0); } -/* stolen from portalfs */ static int -fuse_vfs_root(struct mount *mp, int flags, struct vnode **vpp) +fuse_vfs_root(struct mount *mp, int lkflags, struct vnode **vpp) { - /* - * Return locked reference to root. - */ - struct thread *td = curthread; - struct fuse_data *data = fusefs_get_data(mp); - struct vnode *vp; + int err; - DEBUG2G("mp %p: %s\n", mp, mp->mnt_stat.f_mntfromname); - - if (! data) { - struct fuse_secondary_data *fsdat = fusefs_get_secdata(mp); - int err; - - data = fsdat->master; - sx_slock(&data->mhierlock); - if (data->mpri == FM_PRIMARY) - err = fuse_vfs_root(data->mp, flags, vpp); - else - err = ENXIO; - sx_sunlock(&data->mhierlock); - return (err); - } - - vp = data->rvp; - vref(vp); - vn_lock(vp, flags | LK_RETRY); - if (vp->v_type == VNON) { - struct vattr va; - - (void)VOP_GETATTR(vp, &va, td->td_ucred); - } - *vpp = vp; -#if _DEBUG2G - DEBUG2G("root node:\n"); - vn_printf(vp, " * "); -#endif - return (0); + err = fuse_vnode_get(mp, FUSE_ROOT_ID, NULL, vpp, NULL, VDIR, 0); + return (err); } static int fuse_vfs_statfs(struct mount *mp, struct statfs *sbp) { - struct thread *td = curthread; - struct fuse_dispatcher fdi; - struct fuse_statfs_out *fsfo; - struct fuse_data *data; - int err = 0; + struct fuse_dispatcher fdi; + struct fuse_statfs_out *fsfo; + struct fuse_data *data; + int err = 0; - DEBUG2G("mp %p: %s\n", mp, mp->mnt_stat.f_mntfromname); - data = fusefs_get_data(mp); + DEBUG2G("mp %p: %s\n", mp, mp->mnt_stat.f_mntfromname); + data = fusefs_get_data(mp); - if (! data) { - struct fuse_secondary_data *fsdat; + if (!(data->dataflag & FSESS_INITED)) + goto fake; - fsdat = fusefs_get_secdata(mp); - data = fsdat->master; + if ((err = fdisp_simple_vfs_statfs(&fdi, mp))) { + if (err == ENOTCONN) { + /* + * We want to seem a legitimate fs even if the daemon + * is stiff dead... (so that, eg., we can still do path + * based unmounting after the daemon dies). + */ + goto fake; + } + return (err); + } - sx_slock(&data->mhierlock); - if (data->mpri == FM_PRIMARY) - err = fuse_vfs_statfs(data->mp, sbp); - else - err = ENXIO; - sx_sunlock(&data->mhierlock); - return (err); - } + fsfo = fdi.answ; - if (! (data->dataflag & FSESS_INITED)) - goto fake; + sbp->f_blocks = fsfo->st.blocks; + sbp->f_bfree = fsfo->st.bfree; + sbp->f_bavail = fsfo->st.bavail; + sbp->f_files = fsfo->st.files; + sbp->f_ffree = fsfo->st.ffree; /* cast from uint64_t to int64_t */ + sbp->f_namemax = fsfo->st.namelen; + sbp->f_bsize = fsfo->st.frsize; /* cast from uint32_t to uint64_t */ - if ((err = fdisp_simple_putget(&fdi, FUSE_STATFS, data->rvp, td, - NULL))) { - if (err == ENOTCONN) - /* - * We want to seem a legitimate fs even if the daemon - * is stiff dead... (so that, eg., we can still do path - * based unmounting after the daemon dies). - */ - goto fake; + DEBUG("fuse_statfs_out -- blocks: %llu, bfree: %llu, bavail: %llu, " + "files: %llu, ffree: %llu, bsize: %i, namelen: %i\n", + (unsigned long long)fsfo->st.blocks, (unsigned long long)fsfo->st.bfree, + (unsigned long long)fsfo->st.bavail, (unsigned long long)fsfo->st.files, + (unsigned long long)fsfo->st.ffree, fsfo->st.bsize, fsfo->st.namelen); - return (err); - } + fuse_ticket_drop(fdi.tick); - fsfo = fdi.answ; - - sbp->f_blocks = fsfo->st.blocks; - sbp->f_bfree = fsfo->st.bfree; - sbp->f_bavail = fsfo->st.bavail; - sbp->f_files = fsfo->st.files; - sbp->f_ffree = fsfo->st.ffree; /* cast from uint64_t to int64_t */ - sbp->f_namemax = fsfo->st.namelen; - if (fuse_libabi_geq(fusefs_get_data(mp), 7, 3)) { - /* - * fuse_kstatfs is created from a struct statvfs, we can fill - * the statfs struct by inverting sfs2svfs() of lib/libc/gen/statvfs.c - */ -#if 0 - /* - * This would pretty much **ck up buffered IO, - * since this would overwrite mnt_stat.f_iosize - */ - sbp->f_iosize = fsfo->st.bsize; /* cast from uint32_t to uint64_t */ -#endif - sbp->f_bsize = 0; /* userspace data is broken ... */ -#if FUSE_KERNELABI_GEQ(7, 4) - if (fuse_libabi_geq(fusefs_get_data(mp), 7, 4)) - /* ... unless both kernel and userspace speak 7.4 */ - sbp->f_bsize = fsfo->st.frsize; /* cast from uint32_t to uint64_t */ -#endif - } else - /* - * fuse_kstatfs is also created from a struct statfs, - * conversion is direct - */ - sbp->f_bsize = fsfo->st.bsize; /* cast from uint32_t to uint64_t */ - - DEBUG("fuse_statfs_out -- blocks: %llu, bfree: %llu, bavail: %llu, files: %llu, ffree: %llu, bsize: %i, namelen: %i\n", - (unsigned long long)fsfo->st.blocks, (unsigned long long)fsfo->st.bfree, (unsigned long long)fsfo->st.bavail, (unsigned long long)fsfo->st.files, (unsigned long long)fsfo->st.ffree, fsfo->st.bsize, fsfo->st.namelen); - - fuse_ticket_drop(fdi.tick); - - return (0); + return (0); fake: - sbp->f_blocks = 0; - sbp->f_bfree = 0; - sbp->f_bavail = 0; - sbp->f_files = 0; - sbp->f_ffree = 0; - sbp->f_namemax = 0; - sbp->f_bsize = 0; + sbp->f_blocks = 0; + sbp->f_bfree = 0; + sbp->f_bavail = 0; + sbp->f_files = 0; + sbp->f_ffree = 0; + sbp->f_namemax = 0; + sbp->f_bsize = 0; - return (0); -} - -/* - * ..._i, as "internal" -- we don't need to register it as a VFS op, - * so we might alter from the VFS_VGET signature - */ - -int -fuse_vget_i(struct mount *mp, struct thread *td, uint64_t nodeid, - enum vtype vtyp, struct vnode **vpp, enum vget_mode vmod, - uint64_t parentid) -{ -#define myflags LK_EXCLUSIVE | LK_RETRY - int err = 0; - struct fuse_vnode_data *fvdat; - struct vnode *vp2; - - DEBUG("been asked for vno #%llu, parent #%llu\n", - (long long unsigned)nodeid, (long long unsigned)parentid); - - if (vtyp == VNON) - return (EINVAL); - - if (nodeid == FUSE_ROOT_ID) { - if (parentid != FUSE_NULL_ID) - return (ENOENT); - err = VFS_ROOT(mp, myflags, vpp); - if (err) - return (err); - KASSERT(*vpp, ("we neither err'd nor found the root node")); - goto found; - } - - /* - * With vmod == VG_WANTNEW, caller wants to get a vnode for the id - * only if it's a new one. Hence, no use of trying to get - * to get one with the given id. - */ - if (vmod == VG_WANTNEW) - *vpp = NULL; - else if ((err = vfs_hash_get(mp, nodeid, /*flags*/ myflags, td, vpp, - fuse_vnode_cmp, &nodeid))) - return (err); - - /* - * If vmod == VG_FORCENEW, we also want a new vnode, but instead of - * just bitching when there is an old one with the given id, we - * go and search & destroy those ones... - */ - if (*vpp && vmod == VG_FORCENEW) { - fuse_vnode_teardown(*vpp, td, NULL, vtyp); - *vpp = NULL; - } - -audit: - if (*vpp) { - DEBUG("vnode taken from hash\n"); - if ((*vpp)->v_type == vtyp) { - if (vtyp == VDIR && parentid != FUSE_NULL_ID && - VTOFUD(*vpp)->parent_nid != parentid) { - DEBUG("parent mismatch\n"); - if (VTOFUD(*vpp)->parent_nid == FUSE_NULL_ID) { - /* - * Deleted directory is to be reused. - * We adjust the nodeid to the new scenario. - */ - struct parentmanager_param pmp; - struct vnode *xvp; - - DEBUG("dir has no parent, pushing in required\n"); - pmp.nodeid = nodeid; - pmp.parent_nid = parentid; - pmp.valid = 0; - err = vfs_hash_get(mp, pmp.nodeid, 0, - td, &xvp, - fuse_vnode_setparent_cmp, - &pmp); - KASSERT(xvp == NULL, - ("findparent routine has fetched a vnode")); - } else - /* parent mismatch for a directory */ - err = EIO; - - if (err) { - vput(*vpp); - *vpp = NULL; - return (err); - } - } - goto found; - } else if ((*vpp)->v_type == VNON) { - DEBUG2G("vnode #%llu with no type\n", VTOILLU(*vpp)); - (*vpp)->v_type = vtyp; - goto found; - } else { - fuse_vnode_ditch(*vpp, td); - vput(*vpp); - } - } else if (parentid == FUSE_NULL_ID) { - DEBUG("no vpp, no parentid => ENOENT\n"); - *vpp = NULL; - return (ENOENT); - } - - /* as the big guys say, malloc for your data before getnewvnode() */ - - fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO); - err = getnewvnode("fuse", mp, &fuse_vnops, vpp); -#if _DEBUG - DEBUG2G("allocated new vnode:\n"); - vn_printf(*vpp, " * "); -#endif - - if (err) { - free(fvdat, M_FUSEVN); - VNASSERT(! *vpp, *vpp, - ("Maybe I misunderstood how getnewvnode() works...")); - return (err); - } - - err = vn_lock(*vpp, myflags); - if (err) - printf("fuse4bsd: leaking vnode %p\n", *vpp); - else - err = insmntque(*vpp, mp); - if (err) { - free(fvdat, M_FUSEVN); - return (err); - } - - /* - * There is no harm in fully initializing the vnode before trying - * at insertion, because vnodes are gc-d anyway. For the same reason, - * they _do_ have to be fully initialized here -- the gc routines should - * get the node in an as much predictable state as it's possible. - */ - fuse_vnode_init(*vpp, fvdat, nodeid, vtyp, parentid); - err = vfs_hash_insert(*vpp, nodeid, /*flags*/ myflags, td, &vp2, - fuse_vnode_bgdrop_cmp, fvdat); - - if (err) { - free(fvdat, M_FUSEVN); - /* XXX do something to tear down allocated inode? - * (other fss' code doesn't, so neither I...) - */ - return (err); - } - - if (vp2) { - DEBUG("gee, vfs hash collision for node #%llu\n", (unsigned long long)nodeid); - if (vmod == VG_WANTNEW) { - vput(vp2); - *vpp = NULL; - return (EEXIST); - } else if (vmod == VG_FORCENEW) { - fuse_vnode_teardown(vp2, td, NULL, vtyp); - *vpp = NULL; - goto audit; - } - vpp = &vp2; - goto audit; - } - -found: -#if _DEBUG - DEBUG2G("\n"); - vn_printf(*vpp, " * "); -#endif - return (0); -#undef myflags + return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106131538.p5DFc6Lc074644>