Module Name: src Committed By: hannken Date: Thu Aug 28 08:29:50 UTC 2014
Modified Files: src/sys/fs/puffs: puffs_msgif.c puffs_node.c puffs_sys.h puffs_vfsops.c puffs_vnops.c Log Message: Change puffs from hashlist to vcache. - field "pa_nhashbuckets" of struct "puffs_kargs" becomes a no-op. and should be removed on the next protocol version bump. To generate a diff of this commit: cvs rdiff -u -r1.94 -r1.95 src/sys/fs/puffs/puffs_msgif.c cvs rdiff -u -r1.31 -r1.32 src/sys/fs/puffs/puffs_node.c cvs rdiff -u -r1.85 -r1.86 src/sys/fs/puffs/puffs_sys.h cvs rdiff -u -r1.113 -r1.114 src/sys/fs/puffs/puffs_vfsops.c cvs rdiff -u -r1.183 -r1.184 src/sys/fs/puffs/puffs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/fs/puffs/puffs_msgif.c diff -u src/sys/fs/puffs/puffs_msgif.c:1.94 src/sys/fs/puffs/puffs_msgif.c:1.95 --- src/sys/fs/puffs/puffs_msgif.c:1.94 Thu Oct 17 21:03:27 2013 +++ src/sys/fs/puffs/puffs_msgif.c Thu Aug 28 08:29:50 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_msgif.c,v 1.94 2013/10/17 21:03:27 christos Exp $ */ +/* $NetBSD: puffs_msgif.c,v 1.95 2014/08/28 08:29:50 hannken Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.94 2013/10/17 21:03:27 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.95 2014/08/28 08:29:50 hannken Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -856,7 +856,7 @@ puffsop_expire(struct puffs_mount *pmp, * vrele should cause it to be reclaimed. * Otherwise, we have nothing to do. */ - if (puffs_cookie2vnode(pmp, cookie, 0, 0, &vp) == 0) { + if (puffs_cookie2vnode(pmp, cookie, &vp) == 0) { VPTOPP(vp)->pn_stat &= ~PNODE_SOPEXP; vrele(vp); } @@ -889,7 +889,7 @@ puffsop_flush(struct puffs_mount *pmp, s * reason we need to eventually bump locking to userspace, as we * will need to lock the node if we wish to do flushes. */ - rv = puffs_cookie2vnode(pmp, pf->pf_cookie, 0, 0, &vp); + rv = puffs_cookie2vnode(pmp, pf->pf_cookie, &vp); if (rv) { if (rv == PUFFS_NOSUCHCOOKIE) rv = ENOENT; Index: src/sys/fs/puffs/puffs_node.c diff -u src/sys/fs/puffs/puffs_node.c:1.31 src/sys/fs/puffs/puffs_node.c:1.32 --- src/sys/fs/puffs/puffs_node.c:1.31 Thu Jan 23 10:13:56 2014 +++ src/sys/fs/puffs/puffs_node.c Thu Aug 28 08:29:50 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_node.c,v 1.31 2014/01/23 10:13:56 hannken Exp $ */ +/* $NetBSD: puffs_node.c,v 1.32 2014/08/28 08:29:50 hannken Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.31 2014/01/23 10:13:56 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.32 2014/08/28 08:29:50 hannken Exp $"); #include <sys/param.h> #include <sys/hash.h> @@ -48,148 +48,96 @@ __KERNEL_RCSID(0, "$NetBSD: puffs_node.c #include <miscfs/genfs/genfs_node.h> #include <miscfs/specfs/specdev.h> -static const struct genfs_ops puffs_genfsops = { - .gop_size = puffs_gop_size, - .gop_write = genfs_gop_write, - .gop_markupdate = puffs_gop_markupdate, -#if 0 - .gop_alloc, should ask userspace -#endif -}; - -static __inline struct puffs_node_hashlist - *puffs_cookie2hashlist(struct puffs_mount *, puffs_cookie_t); -static struct puffs_node *puffs_cookie2pnode(struct puffs_mount *, - puffs_cookie_t); - struct pool puffs_pnpool; struct pool puffs_vapool; /* * Grab a vnode, intialize all the puffs-dependent stuff. */ -int -puffs_getvnode(struct mount *mp, puffs_cookie_t ck, enum vtype type, - voff_t vsize, dev_t rdev, struct vnode **vpp) +static int +puffs_getvnode1(struct mount *mp, puffs_cookie_t ck, enum vtype type, + voff_t vsize, dev_t rdev, bool may_exist, struct vnode **vpp) { struct puffs_mount *pmp; - struct puffs_newcookie *pnc; struct vnode *vp; struct puffs_node *pnode; - struct puffs_node_hashlist *plist; int error; pmp = MPTOPUFFSMP(mp); - error = EPROTO; if (type <= VNON || type >= VBAD) { puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EINVAL, "bad node type", ck); - goto bad; + return EPROTO; } if (vsize == VSIZENOTSET) { puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EINVAL, "VSIZENOTSET is not a valid size", ck); - goto bad; + return EPROTO; } - error = getnewvnode(VT_PUFFS, mp, puffs_vnodeop_p, NULL, &vp); - if (error) { - goto bad; + for (;;) { + error = vcache_get(mp, &ck, sizeof(ck), &vp); + if (error) + return error; + mutex_enter(vp->v_interlock); + pnode = VPTOPP(vp); + if (pnode != NULL) + break; + mutex_exit(vp->v_interlock); + vrele(vp); } - vp->v_type = type; + mutex_enter(&pnode->pn_mtx); + mutex_exit(vp->v_interlock); /* - * Creation should not fail after this point. Or if it does, - * care must be taken so that VOP_INACTIVE() isn't called. + * Release and error out if caller wants a fresh vnode. */ + if (vp->v_type != VNON && ! may_exist) { + mutex_exit(&pnode->pn_mtx); + vrele(vp); + return EEXIST; + } - /* default size */ - uvm_vnp_setsize(vp, 0); + *vpp = vp; - /* dances based on vnode type. almost ufs_vinit(), but not quite */ - switch (type) { - case VCHR: - case VBLK: - /* - * replace vnode operation vector with the specops vector. - * our user server has very little control over the node - * if it decides its a character or block special file - */ + /* + * If fully initialized were done. + */ + if (vp->v_type != VNON) { + mutex_exit(&pnode->pn_mtx); + return 0; + } + + /* + * Set type and finalize the initialisation. + */ + vp->v_type = type; + if (type == VCHR || type == VBLK) { vp->v_op = puffs_specop_p; spec_node_init(vp, rdev); - break; - - case VFIFO: + } else if (type == VFIFO) { vp->v_op = puffs_fifoop_p; - break; - - case VREG: + } else if (vp->v_type == VREG) { uvm_vnp_setsize(vp, vsize); - break; - - case VDIR: - case VLNK: - case VSOCK: - break; - default: - panic("puffs_getvnode: invalid vtype %d", type); - } - - pnode = pool_get(&puffs_pnpool, PR_WAITOK); - memset(pnode, 0, sizeof(struct puffs_node)); - - pnode->pn_cookie = ck; - pnode->pn_refcount = 1; - - /* insert cookie on list, take off of interlock list */ - mutex_init(&pnode->pn_mtx, MUTEX_DEFAULT, IPL_NONE); - selinit(&pnode->pn_sel); - plist = puffs_cookie2hashlist(pmp, ck); - mutex_enter(&pmp->pmp_lock); - LIST_INSERT_HEAD(plist, pnode, pn_hashent); - if (ck != pmp->pmp_root_cookie) { - LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) { - if (pnc->pnc_cookie == ck) { - LIST_REMOVE(pnc, pnc_entries); - kmem_free(pnc, sizeof(struct puffs_newcookie)); - break; - } - } - KASSERT(pnc != NULL); } - mutex_init(&pnode->pn_sizemtx, MUTEX_DEFAULT, IPL_NONE); - mutex_exit(&pmp->pmp_lock); - vp->v_data = pnode; - vp->v_type = type; - pnode->pn_vp = vp; pnode->pn_serversize = vsize; - genfs_node_init(vp, &puffs_genfsops); - *vpp = vp; - DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp, pnode, pnode->pn_cookie)); + mutex_exit(&pnode->pn_mtx); + return 0; +} - bad: - /* remove staging cookie from list */ - if (ck != pmp->pmp_root_cookie) { - mutex_enter(&pmp->pmp_lock); - LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) { - if (pnc->pnc_cookie == ck) { - LIST_REMOVE(pnc, pnc_entries); - kmem_free(pnc, sizeof(struct puffs_newcookie)); - break; - } - } - KASSERT(pnc != NULL); - mutex_exit(&pmp->pmp_lock); - } +int +puffs_getvnode(struct mount *mp, puffs_cookie_t ck, enum vtype type, + voff_t vsize, dev_t rdev, struct vnode **vpp) +{ - return error; + return puffs_getvnode1(mp, ck, type, vsize, rdev, true, vpp); } /* new node creating for creative vop ops (create, symlink, mkdir, mknod) */ @@ -199,54 +147,37 @@ puffs_newnode(struct mount *mp, struct v enum vtype type, dev_t rdev) { struct puffs_mount *pmp = MPTOPUFFSMP(mp); - struct puffs_newcookie *pnc; - struct vnode *vp; int error; /* userspace probably has this as a NULL op */ - if (ck == NULL) { - error = EOPNOTSUPP; - return error; - } + if (ck == NULL) + return EOPNOTSUPP; /* * Check for previous node with the same designation. * Explicitly check the root node cookie, since it might be * reclaimed from the kernel when this check is made. */ - mutex_enter(&pmp->pmp_lock); - if (ck == pmp->pmp_root_cookie - || puffs_cookie2pnode(pmp, ck) != NULL) { - mutex_exit(&pmp->pmp_lock); + if (ck == pmp->pmp_root_cookie) { puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EEXIST, "cookie exists", ck); return EPROTO; } - LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) { - if (pnc->pnc_cookie == ck) { - mutex_exit(&pmp->pmp_lock); - puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EEXIST, - "newcookie exists", ck); - return EPROTO; - } - } - KASSERT(curlwp != uvm.pagedaemon_lwp); - pnc = kmem_alloc(sizeof(struct puffs_newcookie), KM_SLEEP); - pnc->pnc_cookie = ck; - LIST_INSERT_HEAD(&pmp->pmp_newcookie, pnc, pnc_entries); - mutex_exit(&pmp->pmp_lock); - error = puffs_getvnode(dvp->v_mount, ck, type, 0, rdev, &vp); - if (error) + error = puffs_getvnode1(dvp->v_mount, ck, type, 0, rdev, false, vpp); + if (error) { + if (error == EEXIST) { + puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EEXIST, + "cookie exists", ck); + error = EPROTO; + } return error; - - vp->v_type = type; - *vpp = vp; + } if (PUFFS_USE_NAMECACHE(pmp)) - cache_enter(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen, + cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); return 0; @@ -259,44 +190,18 @@ puffs_putvnode(struct vnode *vp) pnode = VPTOPP(vp); -#ifdef DIAGNOSTIC - if (vp->v_tag != VT_PUFFS) - panic("puffs_putvnode: %p not a puffs vnode", vp); -#endif + KASSERT(vp->v_tag == VT_PUFFS); + vcache_remove(vp->v_mount, &pnode->pn_cookie, sizeof(pnode->pn_cookie)); genfs_node_destroy(vp); - puffs_releasenode(pnode); + + /* + * To interlock with puffs_getvnode1(). + */ + mutex_enter(vp->v_interlock); vp->v_data = NULL; - - return; -} - -static __inline struct puffs_node_hashlist * -puffs_cookie2hashlist(struct puffs_mount *pmp, puffs_cookie_t ck) -{ - uint32_t hash; - - hash = hash32_buf(&ck, sizeof(ck), HASH32_BUF_INIT); - return &pmp->pmp_pnodehash[hash % pmp->pmp_npnodehash]; -} - -/* - * Translate cookie to puffs_node. Caller must hold pmp_lock - * and it will be held upon return. - */ -static struct puffs_node * -puffs_cookie2pnode(struct puffs_mount *pmp, puffs_cookie_t ck) -{ - struct puffs_node_hashlist *plist; - struct puffs_node *pnode; - - plist = puffs_cookie2hashlist(pmp, ck); - LIST_FOREACH(pnode, plist, pn_hashent) { - if (pnode->pn_cookie == ck) - break; - } - - return pnode; + mutex_exit(vp->v_interlock); + puffs_releasenode(pnode); } /* @@ -314,48 +219,15 @@ puffs_makeroot(struct puffs_mount *pmp) * * pmp_root is set here and cleared in puffs_reclaim(). */ - retry: - mutex_enter(&pmp->pmp_lock); - vp = pmp->pmp_root; - if (vp) { - mutex_enter(vp->v_interlock); - mutex_exit(&pmp->pmp_lock); - switch (vget(vp, 0)) { - case ENOENT: - goto retry; - case 0: - return 0; - default: - break; - } - } else - mutex_exit(&pmp->pmp_lock); - /* - * So, didn't have the magic root vnode available. - * No matter, grab another and stuff it with the cookie. - */ - if ((rv = puffs_getvnode(pmp->pmp_mp, pmp->pmp_root_cookie, - pmp->pmp_root_vtype, pmp->pmp_root_vsize, pmp->pmp_root_rdev, &vp))) + rv = puffs_getvnode(pmp->pmp_mp, pmp->pmp_root_cookie, + pmp->pmp_root_vtype, pmp->pmp_root_vsize, pmp->pmp_root_rdev, &vp); + if (rv != 0) return rv; - /* - * Someone magically managed to race us into puffs_getvnode? - * Put our previous new vnode back and retry. - */ mutex_enter(&pmp->pmp_lock); - if (pmp->pmp_root) { - struct puffs_node *pnode = vp->v_data; - - LIST_REMOVE(pnode, pn_hashent); - mutex_exit(&pmp->pmp_lock); - puffs_putvnode(vp); - goto retry; - } - - /* store cache */ - vp->v_vflag |= VV_ROOT; - pmp->pmp_root = vp; + if (pmp->pmp_root == NULL) + pmp->pmp_root = vp; mutex_exit(&pmp->pmp_lock); return 0; @@ -364,26 +236,16 @@ puffs_makeroot(struct puffs_mount *pmp) /* * Locate the in-kernel vnode based on the cookie received given * from userspace. - * The parameter "lock" control whether to lock the possible or - * not. Locking always might cause us to lock against ourselves - * in situations where we want the vnode but don't care for the - * vnode lock, e.g. file server issued putpages. * * returns 0 on success. otherwise returns an errno or PUFFS_NOSUCHCOOKIE. * * returns PUFFS_NOSUCHCOOKIE if no vnode for the cookie is found. - * in that case, if willcreate=true, the pmp_newcookie list is populated with - * the given cookie. it's the caller's responsibility to consume the entry - * with calling puffs_getvnode. */ int -puffs_cookie2vnode(struct puffs_mount *pmp, puffs_cookie_t ck, int lock, - int willcreate, struct vnode **vpp) +puffs_cookie2vnode(struct puffs_mount *pmp, puffs_cookie_t ck, + struct vnode **vpp) { - struct puffs_node *pnode; - struct puffs_newcookie *pnc; - struct vnode *vp; - int vgetflags, rv; + int rv; /* * Handle root in a special manner, since we want to make sure @@ -392,43 +254,21 @@ puffs_cookie2vnode(struct puffs_mount *p if (ck == pmp->pmp_root_cookie) { if ((rv = puffs_makeroot(pmp))) return rv; - if (lock) - vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY); - *vpp = pmp->pmp_root; return 0; } - retry: - mutex_enter(&pmp->pmp_lock); - pnode = puffs_cookie2pnode(pmp, ck); - if (pnode == NULL) { - if (willcreate) { - pnc = kmem_alloc(sizeof(struct puffs_newcookie), - KM_SLEEP); - pnc->pnc_cookie = ck; - LIST_INSERT_HEAD(&pmp->pmp_newcookie, pnc, pnc_entries); - } - mutex_exit(&pmp->pmp_lock); - return PUFFS_NOSUCHCOOKIE; - } - vp = pnode->pn_vp; - mutex_enter(vp->v_interlock); - mutex_exit(&pmp->pmp_lock); - - vgetflags = 0; - if (lock) - vgetflags |= LK_EXCLUSIVE; - switch (rv = vget(vp, vgetflags)) { - case ENOENT: - goto retry; - case 0: - break; - default: + rv = vcache_get(PMPTOMP(pmp), ck, sizeof(ck), vpp); + if (rv != 0) return rv; + mutex_enter((*vpp)->v_interlock); + if ((*vpp)->v_type == VNON) { + mutex_exit((*vpp)->v_interlock); + vrele(*vpp); + *vpp = NULL; + return PUFFS_NOSUCHCOOKIE; } - *vpp = vp; return 0; } Index: src/sys/fs/puffs/puffs_sys.h diff -u src/sys/fs/puffs/puffs_sys.h:1.85 src/sys/fs/puffs/puffs_sys.h:1.86 --- src/sys/fs/puffs/puffs_sys.h:1.85 Sat Aug 16 16:19:41 2014 +++ src/sys/fs/puffs/puffs_sys.h Thu Aug 28 08:29:50 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_sys.h,v 1.85 2014/08/16 16:19:41 manu Exp $ */ +/* $NetBSD: puffs_sys.h,v 1.86 2014/08/28 08:29:50 hannken Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. @@ -144,15 +144,6 @@ struct puffs_mount { struct puffs_wq pmp_msg_replywait; - struct puffs_node_hashlist *pmp_pnodehash; - int pmp_npnodehash; - - /* - * a list of cookies which is going to be puffs_getvnode'd. - * this is merely a loose attempt to prevent races. - */ - LIST_HEAD(, puffs_newcookie) pmp_newcookie; - struct mount *pmp_mp; struct vnode *pmp_root; @@ -237,8 +228,6 @@ struct puffs_node { int pn_va_timeout; /* attribute cache */ struct vattr * pn_va_cache; /* attribute cache */ struct vnode * pn_parent; /* parent cache */ - - LIST_ENTRY(puffs_node) pn_hashent; }; typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *); @@ -274,7 +263,7 @@ void puffs_releasenode(struct puffs_node void puffs_referencenode(struct puffs_node *); #define PUFFS_NOSUCHCOOKIE (-1) -int puffs_cookie2vnode(struct puffs_mount *, puffs_cookie_t, int, int, +int puffs_cookie2vnode(struct puffs_mount *, puffs_cookie_t, struct vnode **); void puffs_makecn(struct puffs_kcn *, struct puffs_kcred *, const struct componentname *, int); Index: src/sys/fs/puffs/puffs_vfsops.c diff -u src/sys/fs/puffs/puffs_vfsops.c:1.113 src/sys/fs/puffs/puffs_vfsops.c:1.114 --- src/sys/fs/puffs/puffs_vfsops.c:1.113 Sun May 25 19:32:36 2014 +++ src/sys/fs/puffs/puffs_vfsops.c Thu Aug 28 08:29:50 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vfsops.c,v 1.113 2014/05/25 19:32:36 christos Exp $ */ +/* $NetBSD: puffs_vfsops.c,v 1.114 2014/08/28 08:29:50 hannken Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.113 2014/05/25 19:32:36 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.114 2014/08/28 08:29:50 hannken Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -62,17 +62,6 @@ MODULE(MODULE_CLASS_VFS, puffs, "putter" VFS_PROTOS(puffs_vfsop); -#ifndef PUFFS_PNODEBUCKETS -#define PUFFS_PNODEBUCKETS 256 -#endif -#ifndef PUFFS_MAXPNODEBUCKETS -#define PUFFS_MAXPNODEBUCKETS 8192 -#endif -int puffs_pnodebuckets_default = PUFFS_PNODEBUCKETS; -int puffs_maxpnodebuckets = PUFFS_MAXPNODEBUCKETS; - -#define BUCKETALLOC(a) (sizeof(struct puffs_pnode_hashlist *) * (a)) - static struct putter_ops puffs_putter = { .pop_getout = puffs_msgif_getout, .pop_releaseout = puffs_msgif_releaseout, @@ -81,6 +70,15 @@ static struct putter_ops puffs_putter = .pop_close = puffs_msgif_close, }; +static const struct genfs_ops puffs_genfsops = { + .gop_size = puffs_gop_size, + .gop_write = genfs_gop_write, + .gop_markupdate = puffs_gop_markupdate, +#if 0 + .gop_alloc, should ask userspace +#endif +}; + /* * Try to ensure data structures used by the puffs protocol * do not unexpectedly change. @@ -206,17 +204,6 @@ puffs_vfsop_mount(struct mount *mp, cons (void)strlcpy(args->pa_typename, fstype, sizeof(args->pa_typename)); - if (args->pa_nhashbuckets == 0) - args->pa_nhashbuckets = puffs_pnodebuckets_default; - if (args->pa_nhashbuckets < 1) - args->pa_nhashbuckets = 1; - if (args->pa_nhashbuckets > PUFFS_MAXPNODEBUCKETS) { - args->pa_nhashbuckets = puffs_maxpnodebuckets; - printf("puffs_mount: using %d hash buckets. " - "adjust puffs_maxpnodebuckets for more\n", - puffs_maxpnodebuckets); - } - error = set_statvfs_info(path, UIO_USERSPACE, args->pa_mntfromname, UIO_SYSSPACE, fstype, mp, curlwp); if (error) @@ -270,13 +257,6 @@ puffs_vfsop_mount(struct mount *mp, cons pmp->pmp_msg_maxsize = args->pa_maxmsglen; pmp->pmp_args = *args; - pmp->pmp_npnodehash = args->pa_nhashbuckets; - pmp->pmp_pnodehash = kmem_alloc(BUCKETALLOC(pmp->pmp_npnodehash), - KM_SLEEP); - for (i = 0; i < pmp->pmp_npnodehash; i++) - LIST_INIT(&pmp->pmp_pnodehash[i]); - LIST_INIT(&pmp->pmp_newcookie); - /* * Inform the fileops processing code that we have a mountpoint. * If it doesn't know about anyone with our pid/fd having the @@ -319,8 +299,6 @@ puffs_vfsop_mount(struct mount *mp, cons out: if (error && pmp && pmp->pmp_pi) putter_detach(pmp->pmp_pi); - if (error && pmp && pmp->pmp_pnodehash) - kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash)); if (error && pmp) kmem_free(pmp, sizeof(struct puffs_mount)); return error; @@ -441,7 +419,6 @@ puffs_vfsop_unmount(struct mount *mp, in mutex_destroy(&pmp->pmp_lock); mutex_destroy(&pmp->pmp_sopmtx); - kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash)); kmem_free(pmp, sizeof(struct puffs_mount)); error = 0; } else { @@ -462,9 +439,17 @@ puffs_vfsop_root(struct mount *mp, struc struct puffs_mount *pmp = MPTOPUFFSMP(mp); int rv; - rv = puffs_cookie2vnode(pmp, pmp->pmp_root_cookie, 1, 1, vpp); + rv = puffs_cookie2vnode(pmp, pmp->pmp_root_cookie, vpp); KASSERT(rv != PUFFS_NOSUCHCOOKIE); - return rv; + if (rv != 0) + return rv; + rv = vn_lock(*vpp, LK_EXCLUSIVE); + if (rv != 0) { + vrele(*vpp); + *vpp = NULL; + return rv; + } + return 0; } int @@ -644,19 +629,12 @@ puffs_vfsop_fhtovp(struct mount *mp, str if (error) goto out; - error = puffs_cookie2vnode(pmp, fhtonode_msg->pvfsr_fhcookie, 1,1,&vp); - DPRINTF(("puffs_fhtovp: got cookie %p, existing vnode %p\n", - fhtonode_msg->pvfsr_fhcookie, vp)); - if (error == PUFFS_NOSUCHCOOKIE) { - error = puffs_getvnode(mp, fhtonode_msg->pvfsr_fhcookie, - fhtonode_msg->pvfsr_vtype, fhtonode_msg->pvfsr_size, - fhtonode_msg->pvfsr_rdev, &vp); - if (error) - goto out; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - } else if (error) { + error = puffs_getvnode(mp, fhtonode_msg->pvfsr_fhcookie, + fhtonode_msg->pvfsr_vtype, fhtonode_msg->pvfsr_size, + fhtonode_msg->pvfsr_rdev, &vp); + if (error) goto out; - } + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); *vpp = vp; out: @@ -739,6 +717,41 @@ puffs_vfsop_vptofh(struct vnode *vp, str return error; } +int +puffs_vfsop_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) +{ + struct puffs_mount *pmp; + struct puffs_node *pnode; + + KASSERT(key_len == sizeof(puffs_cookie_t)); + + pmp = MPTOPUFFSMP(mp); + + /* Allocate and initialize the pnode. */ + pnode = pool_get(&puffs_pnpool, PR_WAITOK); + memset(pnode, 0, sizeof(struct puffs_node)); + + pnode->pn_vp = vp; + memcpy(&pnode->pn_cookie, key, key_len); + pnode->pn_refcount = 1; + mutex_init(&pnode->pn_mtx, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&pnode->pn_sizemtx, MUTEX_DEFAULT, IPL_NONE); + selinit(&pnode->pn_sel); + vp->v_tag = VT_PUFFS; + vp->v_type = VNON; + vp->v_op = puffs_vnodeop_p; + if (pnode->pn_cookie == pmp->pmp_root_cookie) + vp->v_vflag |= VV_ROOT; + vp->v_data = pnode; + + genfs_node_init(vp, &puffs_genfsops); + uvm_vnp_setsize(vp, 0); + + *new_key = &pnode->pn_cookie; + return 0; +} + void puffs_vfsop_init(void) { @@ -838,6 +851,7 @@ struct vfsops puffs_vfsops = { .vfs_statvfs = puffs_vfsop_statvfs, .vfs_sync = puffs_vfsop_sync, .vfs_vget = (void *)eopnotsupp, + .vfs_loadvnode = puffs_vfsop_loadvnode, .vfs_fhtovp = puffs_vfsop_fhtovp, .vfs_vptofh = puffs_vfsop_vptofh, .vfs_init = puffs_vfsop_init, Index: src/sys/fs/puffs/puffs_vnops.c diff -u src/sys/fs/puffs/puffs_vnops.c:1.183 src/sys/fs/puffs/puffs_vnops.c:1.184 --- src/sys/fs/puffs/puffs_vnops.c:1.183 Sat Aug 16 16:19:41 2014 +++ src/sys/fs/puffs/puffs_vnops.c Thu Aug 28 08:29:50 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vnops.c,v 1.183 2014/08/16 16:19:41 manu Exp $ */ +/* $NetBSD: puffs_vnops.c,v 1.184 2014/08/28 08:29:50 hannken Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.183 2014/08/16 16:19:41 manu Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.184 2014/08/28 08:29:50 hannken Exp $"); #include <sys/param.h> #include <sys/buf.h> @@ -668,11 +668,6 @@ puffs_vnop_lookup(void *v) * match the userland cookie anymore: is the node known? */ if (vp == NULL) { - error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, - 1, 1, &vp); - } - - if (error == PUFFS_NOSUCHCOOKIE) { error = puffs_getvnode(dvp->v_mount, lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype, lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp); @@ -684,10 +679,6 @@ puffs_vnop_lookup(void *v) } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - } else if (error) { - puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), - lookup_msg->pvnr_newnode, ap->a_cnp); - goto out; } /* @@ -1401,7 +1392,6 @@ puffs_vnop_reclaim(void *v) } */ *ap = v; struct vnode *vp = ap->a_vp; struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - struct puffs_node *pnode = vp->v_data; bool notifyserver = true; /* @@ -1424,7 +1414,6 @@ puffs_vnop_reclaim(void *v) * that and someone might race us into node creation */ mutex_enter(&pmp->pmp_lock); - LIST_REMOVE(pnode, pn_hashent); if (PUFFS_USE_NAMECACHE(pmp)) cache_purge(vp); mutex_exit(&pmp->pmp_lock); @@ -1443,7 +1432,6 @@ puffs_vnop_reclaim(void *v) } puffs_putvnode(vp); - vp->v_data = NULL; return 0; }