diff options
Diffstat (limited to 'sys/nfs/nfs_node.c')
-rw-r--r-- | sys/nfs/nfs_node.c | 468 |
1 files changed, 0 insertions, 468 deletions
diff --git a/sys/nfs/nfs_node.c b/sys/nfs/nfs_node.c deleted file mode 100644 index 5fe3abc..0000000 --- a/sys/nfs/nfs_node.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 - * $FreeBSD$ - */ - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/fnv_hash.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/proc.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/vnode.h> - -#include <vm/vm_zone.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfs/nfs.h> -#include <nfs/nfsnode.h> -#include <nfs/nfsmount.h> - -static vm_zone_t nfsnode_zone; -static LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; -static u_long nfsnodehash; - -#define TRUE 1 -#define FALSE 0 - -/* - * Grab an atomic snapshot of the nfsnode hash chain lengths - */ -SYSCTL_DECL(_debug_hashstat); -static int -sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS) -{ - int error; - struct nfsnodehashhead *nnpp; - struct nfsnode *nnp; - int n_nfsnode; - int count; - - n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */ - if (!req->oldptr) - return SYSCTL_OUT(req, 0, n_nfsnode * sizeof(int)); - - /* Scan hash tables for applicable entries */ - for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) { - count = 0; - LIST_FOREACH(nnp, nnpp, n_hash) { - count++; - } - error = SYSCTL_OUT(req, (caddr_t)&count, sizeof(count)); - if (error) - return (error); - } - return (0); -} -SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD, - 0, 0, sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths"); - -static int -sysctl_debug_hashstat_nfsnode(SYSCTL_HANDLER_ARGS) -{ - int error; - struct nfsnodehashhead *nnpp; - struct nfsnode *nnp; - int n_nfsnode; - int count, maxlength, used, pct; - - if (!req->oldptr) - return SYSCTL_OUT(req, 0, 4 * sizeof(int)); - - n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */ - used = 0; - maxlength = 0; - - /* Scan hash tables for applicable entries */ - for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) { - count = 0; - LIST_FOREACH(nnp, nnpp, n_hash) { - count++; - } - if (count) - used++; - if (maxlength < count) - maxlength = count; - } - n_nfsnode = nfsnodehash + 1; - pct = (used * 100 * 100) / n_nfsnode; - error = SYSCTL_OUT(req, (caddr_t)&n_nfsnode, sizeof(n_nfsnode)); - if (error) - return (error); - error = SYSCTL_OUT(req, (caddr_t)&used, sizeof(used)); - if (error) - return (error); - error = SYSCTL_OUT(req, (caddr_t)&maxlength, sizeof(maxlength)); - if (error) - return (error); - error = SYSCTL_OUT(req, (caddr_t)&pct, sizeof(pct)); - if (error) - return (error); - return (0); -} -SYSCTL_PROC(_debug_hashstat, OID_AUTO, nfsnode, CTLTYPE_INT|CTLFLAG_RD, - 0, 0, sysctl_debug_hashstat_nfsnode, "I", "nfsnode chain lengths"); - -/* - * Initialize hash links for nfsnodes - * and build nfsnode free list. - */ -void -nfs_nhinit() -{ - nfsnode_zone = zinit("NFSNODE", sizeof(struct nfsnode), 0, 0, 1); - nfsnodehashtbl = hashinit(desiredvnodes, M_NFSHASH, &nfsnodehash); -} - -/* - * Look up a vnode/nfsnode by file handle. - * Callers must check for mount points!! - * In all cases, a pointer to a - * nfsnode structure is returned. - */ -static int nfs_node_hash_lock; - -int -nfs_nget(mntp, fhp, fhsize, npp) - struct mount *mntp; - register nfsfh_t *fhp; - int fhsize; - struct nfsnode **npp; -{ - struct thread *td = curthread; /* XXX */ - struct nfsnode *np, *np2; - struct nfsnodehashhead *nhpp; - register struct vnode *vp; - struct vnode *nvp; - int error; - int rsflags; - struct nfsmount *nmp; - - /* - * Calculate nfs mount point and figure out whether the rslock should - * be interruptable or not. - */ - nmp = VFSTONFS(mntp); - if (nmp->nm_flag & NFSMNT_INT) - rsflags = PCATCH; - else - rsflags = 0; - -retry: - nhpp = NFSNOHASH(fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT)); -loop: - for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { - if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || - bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) - continue; - vp = NFSTOV(np); - if (vget(vp, LK_EXCLUSIVE, td)) - goto loop; - *npp = np; - return(0); - } - /* - * Obtain a lock to prevent a race condition if the getnewvnode() - * or MALLOC() below happens to block. - */ - if (nfs_node_hash_lock) { - while (nfs_node_hash_lock) { - nfs_node_hash_lock = -1; - tsleep(&nfs_node_hash_lock, PVM, "nfsngt", 0); - } - goto loop; - } - nfs_node_hash_lock = 1; - - /* - * Allocate before getnewvnode since doing so afterward - * might cause a bogus v_data pointer to get dereferenced - * elsewhere if zalloc should block. - */ - np = zalloc(nfsnode_zone); - - error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); - if (error) { - if (nfs_node_hash_lock < 0) - wakeup(&nfs_node_hash_lock); - nfs_node_hash_lock = 0; - *npp = 0; - zfree(nfsnode_zone, np); - return (error); - } - vp = nvp; - bzero((caddr_t)np, sizeof *np); - vp->v_data = np; - np->n_vnode = vp; - /* - * Insert the nfsnode in the hash queue for its new file handle - */ - for (np2 = nhpp->lh_first; np2 != 0; np2 = np2->n_hash.le_next) { - if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize || - bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize)) - continue; - vrele(vp); - if (nfs_node_hash_lock < 0) - wakeup(&nfs_node_hash_lock); - nfs_node_hash_lock = 0; - zfree(nfsnode_zone, np); - goto retry; - } - LIST_INSERT_HEAD(nhpp, np, n_hash); - if (fhsize > NFS_SMALLFH) { - MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); - } else - np->n_fhp = &np->n_fh; - bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); - np->n_fhsize = fhsize; - lockinit(&np->n_rslock, PVFS | rsflags, "nfrslk", 0, LK_NOPAUSE); - lockinit(&vp->v_lock, PVFS, "nfsnlk", 0, LK_NOPAUSE); - *npp = np; - - if (nfs_node_hash_lock < 0) - wakeup(&nfs_node_hash_lock); - nfs_node_hash_lock = 0; - - /* - * Lock the new nfsnode. - */ - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - - return (0); -} - -int -nfs_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - struct thread *a_td; - } */ *ap; -{ - register struct nfsnode *np; - register struct sillyrename *sp; - struct thread *td = curthread; /* XXX */ - - np = VTONFS(ap->a_vp); - if (prtactive && ap->a_vp->v_usecount != 0) - vprint("nfs_inactive: pushing active", ap->a_vp); - if (ap->a_vp->v_type != VDIR) { - sp = np->n_sillyrename; - np->n_sillyrename = (struct sillyrename *)0; - } else - sp = (struct sillyrename *)0; - if (sp) { - /* - * We need a reference to keep the vnode from being - * recycled by getnewvnode while we do the I/O - * associated with discarding the buffers unless we - * are being forcibly unmounted in which case we already - * have our own reference. - */ - if (ap->a_vp->v_usecount > 0) - (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, td, 1); - else if (vget(ap->a_vp, 0, td)) - panic("nfs_inactive: lost vnode"); - else { - (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, td, 1); - vrele(ap->a_vp); - } - /* - * Remove the silly file that was rename'd earlier - */ - nfs_removeit(sp); - crfree(sp->s_cred); - vrele(sp->s_dvp); - FREE((caddr_t)sp, M_NFSREQ); - } - np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | - NQNFSNONCACHE | NQNFSWRITE); - VOP_UNLOCK(ap->a_vp, 0, ap->a_td); - return (0); -} - -/* - * Reclaim an nfsnode so that it can be used for other purposes. - */ -int -nfs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct nfsnode *np = VTONFS(vp); - register struct nfsmount *nmp = VFSTONFS(vp->v_mount); - register struct nfsdmap *dp, *dp2; - - if (prtactive && vp->v_usecount != 0) - vprint("nfs_reclaim: pushing active", vp); - - if (np->n_hash.le_prev != NULL) - LIST_REMOVE(np, n_hash); - - /* - * For nqnfs, take it off the timer queue as required. - */ - if ((nmp->nm_flag & NFSMNT_NQNFS) && TAILQ_NEXT(np, n_timer) != 0) { - TAILQ_REMOVE(&nmp->nm_timerhead, np, n_timer); - } - - /* - * Free up any directory cookie structures and - * large file handle structures that might be associated with - * this nfs node. - */ - if (vp->v_type == VDIR) { - dp = np->n_cookies.lh_first; - while (dp) { - dp2 = dp; - dp = dp->ndm_list.le_next; - FREE((caddr_t)dp2, M_NFSDIROFF); - } - } - if (np->n_fhsize > NFS_SMALLFH) { - FREE((caddr_t)np->n_fhp, M_NFSBIGFH); - } - - lockdestroy(&np->n_rslock); - - cache_purge(vp); - zfree(nfsnode_zone, vp->v_data); - vp->v_data = (void *)0; - return (0); -} - -#if 0 -/* - * Lock an nfsnode - */ -int -nfs_lock(ap) - struct vop_lock_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - - /* - * Ugh, another place where interruptible mounts will get hung. - * If you make this sleep interruptible, then you have to fix all - * the VOP_LOCK() calls to expect interruptibility. - */ - while (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - (void) tsleep((caddr_t)vp, PINOD, "nfslck", 0); - } - if (vp->v_tag == VT_NON) - return (ENOENT); - -#if 0 - /* - * Only lock regular files. If a server crashed while we were - * holding a directory lock, we could easily end up sleeping - * until the server rebooted while holding a lock on the root. - * Locks are only needed for protecting critical sections in - * VMIO at the moment. - * New vnodes will have type VNON but they should be locked - * since they may become VREG. This is checked in loadattrcache - * and unwanted locks are released there. - */ - if (vp->v_type == VREG || vp->v_type == VNON) { - while (np->n_flag & NLOCKED) { - np->n_flag |= NWANTED; - (void) tsleep((caddr_t) np, PINOD, "nfslck2", 0); - /* - * If the vnode has transmuted into a VDIR while we - * were asleep, then skip the lock. - */ - if (vp->v_type != VREG && vp->v_type != VNON) - return (0); - } - np->n_flag |= NLOCKED; - } -#endif - - return (0); -} - -/* - * Unlock an nfsnode - */ -int -nfs_unlock(ap) - struct vop_unlock_args /* { - struct vnode *a_vp; - } */ *ap; -{ -#if 0 - struct vnode* vp = ap->a_vp; - struct nfsnode* np = VTONFS(vp); - - if (vp->v_type == VREG || vp->v_type == VNON) { - if (!(np->n_flag & NLOCKED)) - panic("nfs_unlock: nfsnode not locked"); - np->n_flag &= ~NLOCKED; - if (np->n_flag & NWANTED) { - np->n_flag &= ~NWANTED; - wakeup((caddr_t) np); - } - } -#endif - - return (0); -} - -/* - * Check for a locked nfsnode - */ -int -nfs_islocked(ap) - struct vop_islocked_args /* { - struct vnode *a_vp; - struct thread *a_td; - } */ *ap; -{ - return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0; -} -#endif - |