nfs_node.c revision 211531
1139823Simp/*- 21541Srgrimes * Copyright (c) 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software contributed to Berkeley by 61541Srgrimes * Rick Macklem at The University of Guelph. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 4. Neither the name of the University nor the names of its contributors 171541Srgrimes * may be used to endorse or promote products derived from this software 181541Srgrimes * without specific prior written permission. 191541Srgrimes * 201541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301541Srgrimes * SUCH DAMAGE. 311541Srgrimes * 3222521Sdyson * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 331541Srgrimes */ 341541Srgrimes 3583651Speter#include <sys/cdefs.h> 3683651Speter__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_node.c 211531 2010-08-20 19:46:50Z jhb $"); 3722521Sdyson 381541Srgrimes#include <sys/param.h> 391541Srgrimes#include <sys/systm.h> 4076166Smarkm#include <sys/fnv_hash.h> 4176166Smarkm#include <sys/lock.h> 4276166Smarkm#include <sys/malloc.h> 43192578Srwatson#include <sys/mbuf.h> 441541Srgrimes#include <sys/mount.h> 451541Srgrimes#include <sys/namei.h> 4676166Smarkm#include <sys/proc.h> 4776166Smarkm#include <sys/socket.h> 4876166Smarkm#include <sys/sysctl.h> 491541Srgrimes#include <sys/vnode.h> 501541Srgrimes 5192783Sjeff#include <vm/uma.h> 5232011Sbde 539336Sdfr#include <nfs/nfsproto.h> 5483651Speter#include <nfsclient/nfs.h> 5583651Speter#include <nfsclient/nfsnode.h> 5683651Speter#include <nfsclient/nfsmount.h> 571541Srgrimes 5892783Sjeffstatic uma_zone_t nfsnode_zone; 591541Srgrimes 601541Srgrimes#define TRUE 1 611541Srgrimes#define FALSE 0 621541Srgrimes 631549Srgrimesvoid 6483651Speternfs_nhinit(void) 651541Srgrimes{ 6683651Speter 6792783Sjeff nfsnode_zone = uma_zcreate("NFSNODE", sizeof(struct nfsnode), NULL, 6892783Sjeff NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 691541Srgrimes} 701541Srgrimes 71128111Speadarvoid 72128111Speadarnfs_nhuninit(void) 73128111Speadar{ 74128111Speadar uma_zdestroy(nfsnode_zone); 75128111Speadar} 76128111Speadar 77143693Sphkstruct nfs_vncmp { 78143693Sphk int fhsize; 79143693Sphk void *fh; 80143693Sphk}; 81143693Sphk 82143693Sphkstatic int 83143693Sphknfs_vncmpf(struct vnode *vp, void *arg) 84143693Sphk{ 85143693Sphk struct nfs_vncmp *a; 86143693Sphk struct nfsnode *np; 87143693Sphk 88143693Sphk a = arg; 89143693Sphk np = VTONFS(vp); 90143693Sphk return (bcmp(a->fh, np->n_fhp, a->fhsize)); 91143693Sphk} 92143693Sphk 93128111Speadar/* 941541Srgrimes * Look up a vnode/nfsnode by file handle. 951541Srgrimes * Callers must check for mount points!! 961541Srgrimes * In all cases, a pointer to a 971541Srgrimes * nfsnode structure is returned. 981541Srgrimes */ 991549Srgrimesint 100162288Smohansnfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp, int flags) 1011541Srgrimes{ 10283366Sjulian struct thread *td = curthread; /* XXX */ 103143693Sphk struct nfsnode *np; 10483651Speter struct vnode *vp; 1051541Srgrimes struct vnode *nvp; 1061541Srgrimes int error; 107143693Sphk u_int hash; 10855431Sdillon struct nfsmount *nmp; 109143693Sphk struct nfs_vncmp ncmp; 1101541Srgrimes 11155431Sdillon nmp = VFSTONFS(mntp); 112143693Sphk *npp = NULL; 113143693Sphk 114143693Sphk hash = fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT); 115143693Sphk ncmp.fhsize = fhsize; 116143693Sphk ncmp.fh = fhp; 117143693Sphk 118162288Smohans error = vfs_hash_get(mntp, hash, flags, 119143693Sphk td, &nvp, nfs_vncmpf, &ncmp); 120143693Sphk if (error) 121143693Sphk return (error); 122143693Sphk if (nvp != NULL) { 123143693Sphk *npp = VTONFS(nvp); 124143693Sphk return (0); 1251541Srgrimes } 12616312Sdg 12716312Sdg /* 12836329Speter * Allocate before getnewvnode since doing so afterward 12916312Sdg * might cause a bogus v_data pointer to get dereferenced 13036329Speter * elsewhere if zalloc should block. 13116312Sdg */ 132143693Sphk np = uma_zalloc(nfsnode_zone, M_WAITOK | M_ZERO); 13383651Speter 134192578Srwatson error = getnewvnode("nfs", mntp, &nfs_vnodeops, &nvp); 1353305Sphk if (error) { 13692783Sjeff uma_zfree(nfsnode_zone, np); 1371541Srgrimes return (error); 1381541Srgrimes } 1391541Srgrimes vp = nvp; 140192578Srwatson vp->v_bufobj.bo_ops = &buf_ops_nfs; 1411541Srgrimes vp->v_data = np; 1421541Srgrimes np->n_vnode = vp; 143164684Smohans /* 144164684Smohans * Initialize the mutex even if the vnode is going to be a loser. 145164684Smohans * This simplifies the logic in reclaim, which can then unconditionally 146164684Smohans * destroy the mutex (in the case of the loser, or if hash_insert happened 147164684Smohans * to return an error no special casing is needed). 148164684Smohans */ 149164684Smohans mtx_init(&np->n_mtx, "NFSnode lock", NULL, MTX_DEF); 150158855Smohans /* 151158855Smohans * NFS supports recursive and shared locking. 152158855Smohans */ 153211531Sjhb lockmgr(vp->v_vnlock, LK_EXCLUSIVE | LK_NOWITNESS, NULL); 154176519Sattilio VN_LOCK_AREC(vp); 155176519Sattilio VN_LOCK_ASHARE(vp); 156164735Smohans if (fhsize > NFS_SMALLFH) { 157184205Sdes np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK); 158164735Smohans } else 159164735Smohans np->n_fhp = &np->n_fh; 160164735Smohans bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 161164735Smohans np->n_fhsize = fhsize; 162167497Stegge error = insmntque(vp, mntp); 163167497Stegge if (error != 0) { 164167497Stegge *npp = NULL; 165167497Stegge if (np->n_fhsize > NFS_SMALLFH) { 166184205Sdes free((caddr_t)np->n_fhp, M_NFSBIGFH); 167167497Stegge } 168167497Stegge mtx_destroy(&np->n_mtx); 169167497Stegge uma_zfree(nfsnode_zone, np); 170167497Stegge return (error); 171167497Stegge } 172162288Smohans error = vfs_hash_insert(vp, hash, flags, 173143693Sphk td, &nvp, nfs_vncmpf, &ncmp); 174143693Sphk if (error) 175143693Sphk return (error); 176143693Sphk if (nvp != NULL) { 177143693Sphk *npp = VTONFS(nvp); 178164346Smohans /* vfs_hash_insert() vput()'s the losing vnode */ 179143693Sphk return (0); 18047750Speter } 1811541Srgrimes *npp = np; 1829336Sdfr 1831541Srgrimes return (0); 1841541Srgrimes} 1851541Srgrimes 1861549Srgrimesint 18783651Speternfs_inactive(struct vop_inactive_args *ap) 1881541Srgrimes{ 18983651Speter struct nfsnode *np; 19083651Speter struct sillyrename *sp; 19183366Sjulian struct thread *td = curthread; /* XXX */ 1921541Srgrimes 1931541Srgrimes np = VTONFS(ap->a_vp); 194103939Sjeff if (prtactive && vrefcnt(ap->a_vp) != 0) 1951541Srgrimes vprint("nfs_inactive: pushing active", ap->a_vp); 196210834Srmacklem mtx_lock(&np->n_mtx); 19725610Sdfr if (ap->a_vp->v_type != VDIR) { 1989336Sdfr sp = np->n_sillyrename; 19999797Sdillon np->n_sillyrename = NULL; 20025610Sdfr } else 20199797Sdillon sp = NULL; 2021541Srgrimes if (sp) { 203210834Srmacklem mtx_unlock(&np->n_mtx); 204140731Sphk (void)nfs_vinvalbuf(ap->a_vp, 0, td, 1); 2051541Srgrimes /* 2061541Srgrimes * Remove the silly file that was rename'd earlier 2071541Srgrimes */ 208122698Salfred (sp->s_removeit)(sp); 2091541Srgrimes crfree(sp->s_cred); 2101541Srgrimes vrele(sp->s_dvp); 211184205Sdes free((caddr_t)sp, M_NFSREQ); 212210834Srmacklem mtx_lock(&np->n_mtx); 2131541Srgrimes } 214138469Sps np->n_flag &= NMODIFIED; 215210834Srmacklem mtx_unlock(&np->n_mtx); 2161541Srgrimes return (0); 2171541Srgrimes} 2181541Srgrimes 2191541Srgrimes/* 2201541Srgrimes * Reclaim an nfsnode so that it can be used for other purposes. 2211541Srgrimes */ 2221549Srgrimesint 22383651Speternfs_reclaim(struct vop_reclaim_args *ap) 2241541Srgrimes{ 22583651Speter struct vnode *vp = ap->a_vp; 22683651Speter struct nfsnode *np = VTONFS(vp); 22783651Speter struct nfsdmap *dp, *dp2; 2281541Srgrimes 229103939Sjeff if (prtactive && vrefcnt(vp) != 0) 2301541Srgrimes vprint("nfs_reclaim: pushing active", vp); 2311541Srgrimes 232154487Salfred /* 233180025Sdfr * If the NLM is running, give it a chance to abort pending 234180025Sdfr * locks. 235180025Sdfr */ 236180025Sdfr if (nfs_reclaim_p) 237180025Sdfr nfs_reclaim_p(ap); 238180025Sdfr 239180025Sdfr /* 240154487Salfred * Destroy the vm object and flush associated pages. 241154487Salfred */ 242154487Salfred vnode_destroy_vobject(vp); 243154487Salfred 244143693Sphk vfs_hash_remove(vp); 2453664Sphk 2461541Srgrimes /* 2479336Sdfr * Free up any directory cookie structures and 2489336Sdfr * large file handle structures that might be associated with 2499336Sdfr * this nfs node. 2509336Sdfr */ 2519336Sdfr if (vp->v_type == VDIR) { 25283651Speter dp = LIST_FIRST(&np->n_cookies); 2539336Sdfr while (dp) { 2549336Sdfr dp2 = dp; 25583651Speter dp = LIST_NEXT(dp, ndm_list); 256184205Sdes free((caddr_t)dp2, M_NFSDIROFF); 2579336Sdfr } 2589336Sdfr } 2599336Sdfr if (np->n_fhsize > NFS_SMALLFH) { 260184205Sdes free((caddr_t)np->n_fhp, M_NFSBIGFH); 2619336Sdfr } 262158739Smohans mtx_destroy(&np->n_mtx); 26392783Sjeff uma_zfree(nfsnode_zone, vp->v_data); 26499797Sdillon vp->v_data = NULL; 2651541Srgrimes return (0); 2661541Srgrimes} 267