/* $NetBSD$ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Taylor R Campbell. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * XXX NOTE NOTE NOTE XXX * * This code does not actually work. It is a draft of an idea. It * probably won't even compile, even if you make it include the right * header files. */ int nfs_nget(struct mount *mp, nfsfh_t *fhp, int fhsize, struct nfsnode *npp, int flags) { struct vnode *vp = NULL, *vp0 = NULL; static const struct nfsnode zero_nfsnode; struct nfsnode *np; int error; /* * Try to get an existing vnode for this file handle. */ error = vinotab_get(nmp->nm_vinotab, fhp, fhsize, VWAIT_INTR, &vp); KASSERT((error == 0) == (vp != NULL)); if (error != ENOENT) goto out; /* * Create a new vnode for it instead. */ error = getnewvnode(VT_NFS, mp, nfsv2_vnodeop_p, NULL, &vp); KASSERT((error == 0) == (vp != NULL)); if (error) goto out; /* * Create an nfsnode structure for it and fill it in just * enough for a lookup. */ np = pool_get(&nfs_node_pool, PR_WAITOK); KASSERT(np != NULL); *np = zero_nfsnode; if (fhsize > NFS_SMALLFH) np->n_fhp = kmem_alloc(fhsize, KM_SLEEP); else np->n_fhp = &np->n_fh; (void)memcpy(np->n_fhp, fhp, fhsize); np->n_fhsize = fhsize; /* * Try to put this vnode in the table for the file handle. If * someone else beat us to it, release ours and use theirs * instead. */ error = vinotab_intern(nmp->nm_vinotab, &np->n_vinoent, np->n_fhp, np->n_fhsize, vp, VWAIT_INTR, &vp0); KASSERT((error == 0) == (vp0 != NULL)); if (vp0 != vp) { if (fhsize > NFS_SMALLFH) kmem_free(np->n_fhp, np->n_fhsize); pool_put(&nfs_node_pool, np); ungetnewvnode(vp); vp = vp0; goto out; } /* * Initialize the new vnode and nfsnode. */ vp->v_data = np; genfs_node_init(vp, &nfs_genfsops); np->n_accstamp = -1; np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK); np->n_rcred = curlwp->l_cred; kauth_cred_hold(np->n_rcred); np->n_wcred = curlwp->l_cred; kauth_cred_hold(np->n_wcred); /* * Invalidate the attribute cache so that anyone trying to get * the size will caues it to be filled in. Pretend the size is * zero for now (XXX why?). */ NFS_INVALIDATE_ATTRCACHE(np); uvm_vnp_setsize(vp, 0); /* * All set. Mark it ready to go and wake anyone waiting. */ vready(vp); error = 0; out: *npp = (vp == NULL? NULL : vp->v_data); return error; } int nfs_reclaim(void *v) { struct vop_destroy_args /* { struct vnode *a_vp; } */ *ap = v; struct vnode *vp = ap->a_vp; struct nfsnode *np = VTONFS(vp); struct nfsmount *nmp = VFSTONFS(vp->v_mount); vinotab_remove(nmp->nm_vinotab, &np->n_vinoent); switch (vp->v_type) { case VREG: mutex_destroy(&np->n_commitlock); break; case VDIR: if (np->n_dircache == NULL) break; nfs_invaldircache(vp, NFS_INVALDIRCACHE_FORCE); hashdone(np->n_dircache, HASH_LIST, nfsdirhashmask); break; } KASSERT(np->n_dirgens == NULL); if (np->n_wcred) kauth_cred_free(np->n_wcred); if (np->n_rcred) kauth_cred_free(np->n_rcred); pool_put(&nfs_vattr_pool, np->n_vattr); genfs_node_destroy(vp); vp->v_data = NULL; if (np->n_fhsize > NFS_SMALLFH) kmem_free(np->n_fhp, np->n_fhsize); pool_put(&nfs_node_pool, np); return 0; }