1 /* $OpenBSD: nfs_node.c,v 1.15 2001/06/25 03:28:06 csapuntz Exp $ */ 2 /* $NetBSD: nfs_node.c,v 1.16 1996/02/18 11:53:42 fvdl Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Rick Macklem at The University of Guelph. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 40 */ 41 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/proc.h> 46 #include <sys/mount.h> 47 #include <sys/namei.h> 48 #include <sys/vnode.h> 49 #include <sys/kernel.h> 50 #include <sys/malloc.h> 51 52 #include <nfs/rpcv2.h> 53 #include <nfs/nfsproto.h> 54 #include <nfs/nfs.h> 55 #include <nfs/nfsnode.h> 56 #include <nfs/nfsmount.h> 57 #include <nfs/nfs_var.h> 58 59 LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; 60 u_long nfsnodehash; 61 62 #define TRUE 1 63 #define FALSE 0 64 65 /* 66 * Initialize hash links for nfsnodes 67 * and build nfsnode free list. 68 */ 69 void 70 nfs_nhinit() 71 { 72 73 nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, M_WAITOK, &nfsnodehash); 74 } 75 76 /* 77 * Compute an entry in the NFS hash table structure 78 */ 79 u_long 80 nfs_hash(fhp, fhsize) 81 register nfsfh_t *fhp; 82 int fhsize; 83 { 84 register u_char *fhpp; 85 register u_long fhsum; 86 register int i; 87 88 fhpp = &fhp->fh_bytes[0]; 89 fhsum = 0; 90 for (i = 0; i < fhsize; i++) 91 fhsum += *fhpp++; 92 return (fhsum); 93 } 94 95 /* 96 * Look up a vnode/nfsnode by file handle. 97 * Callers must check for mount points!! 98 * In all cases, a pointer to a 99 * nfsnode structure is returned. 100 */ 101 int 102 nfs_nget(mntp, fhp, fhsize, npp) 103 struct mount *mntp; 104 register nfsfh_t *fhp; 105 int fhsize; 106 struct nfsnode **npp; 107 { 108 struct proc *p = curproc; /* XXX */ 109 register struct nfsnode *np, *np2; 110 struct nfsnodehashhead *nhpp; 111 register struct vnode *vp; 112 extern int (**nfsv2_vnodeop_p)__P((void *)); 113 struct vnode *nvp; 114 int error; 115 116 retry: 117 nhpp = NFSNOHASH(nfs_hash(fhp, fhsize)); 118 loop: 119 for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 120 if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 121 bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 122 continue; 123 vp = NFSTOV(np); 124 if (vget(vp, LK_EXCLUSIVE, p)) 125 goto loop; 126 *npp = np; 127 return(0); 128 } 129 error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 130 if (error) { 131 *npp = 0; 132 return (error); 133 } 134 vp = nvp; 135 MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK); 136 bzero((caddr_t)np, sizeof *np); 137 vp->v_data = np; 138 139 /* 140 * Are we getting the root? If so, make sure the vnode flags 141 * are correct 142 */ 143 { 144 struct nfsmount *nmp = VFSTONFS(mntp); 145 if ((fhsize == nmp->nm_fhsize) && 146 !bcmp(fhp, nmp->nm_fh, fhsize)) { 147 if (vp->v_type == VNON) 148 vp->v_type = VDIR; 149 vp->v_flag |= VROOT; 150 } 151 } 152 153 np->n_vnode = vp; 154 /* 155 * Insert the nfsnode in the hash queue for its new file handle 156 */ 157 for (np2 = nhpp->lh_first; np2 != 0; np2 = np2->n_hash.le_next) { 158 if (vp->v_mount != NFSTOV(np2)->v_mount || 159 fhsize != np2->n_fhsize || 160 bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize)) 161 continue; 162 163 vrele(vp); 164 goto retry; 165 } 166 167 LIST_INSERT_HEAD(nhpp, np, n_hash); 168 if (fhsize > NFS_SMALLFH) { 169 MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); 170 } else 171 np->n_fhp = &np->n_fh; 172 bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 173 np->n_fhsize = fhsize; 174 *npp = np; 175 return (0); 176 } 177 178 int 179 nfs_inactive(v) 180 void *v; 181 { 182 struct vop_inactive_args /* { 183 struct vnode *a_vp; 184 struct proc *a_p; 185 } */ *ap = v; 186 register struct nfsnode *np; 187 register struct sillyrename *sp; 188 struct proc *p = curproc; /* XXX */ 189 extern int prtactive; 190 191 np = VTONFS(ap->a_vp); 192 if (prtactive && ap->a_vp->v_usecount != 0) 193 vprint("nfs_inactive: pushing active", ap->a_vp); 194 if (ap->a_vp->v_type != VDIR) { 195 sp = np->n_sillyrename; 196 np->n_sillyrename = (struct sillyrename *)0; 197 } else 198 sp = (struct sillyrename *)0; 199 if (sp) { 200 /* 201 * Remove the silly file that was rename'd earlier 202 */ 203 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 204 nfs_removeit(sp); 205 crfree(sp->s_cred); 206 vrele(sp->s_dvp); 207 FREE((caddr_t)sp, M_NFSREQ); 208 } 209 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT); 210 211 VOP_UNLOCK(ap->a_vp, 0, ap->a_p); 212 return (0); 213 } 214 215 /* 216 * Reclaim an nfsnode so that it can be used for other purposes. 217 */ 218 int 219 nfs_reclaim(v) 220 void *v; 221 { 222 struct vop_reclaim_args /* { 223 struct vnode *a_vp; 224 } */ *ap = v; 225 register struct vnode *vp = ap->a_vp; 226 register struct nfsnode *np = VTONFS(vp); 227 register struct nfsdmap *dp, *dp2; 228 extern int prtactive; 229 230 if (prtactive && vp->v_usecount != 0) 231 vprint("nfs_reclaim: pushing active", vp); 232 233 if (np->n_hash.le_prev != NULL) 234 LIST_REMOVE(np, n_hash); 235 236 /* 237 * Free up any directory cookie structures and 238 * large file handle structures that might be associated with 239 * this nfs node. 240 */ 241 if (vp->v_type == VDIR) { 242 dp = np->n_cookies.lh_first; 243 while (dp) { 244 dp2 = dp; 245 dp = dp->ndm_list.le_next; 246 FREE((caddr_t)dp2, M_NFSDIROFF); 247 } 248 } 249 if (np->n_fhsize > NFS_SMALLFH) { 250 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 251 } 252 253 cache_purge(vp); 254 FREE(vp->v_data, M_NFSNODE); 255 vp->v_data = (void *)0; 256 return (0); 257 } 258 259