1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)nfs_node.c 7.34 (Berkeley) 5/15/91 37 * $Id: nfs_node.c,v 1.8 1994/04/25 03:50:19 cgd Exp $ 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/proc.h> 43 #include <sys/mount.h> 44 #include <sys/namei.h> 45 #include <sys/vnode.h> 46 #include <sys/kernel.h> 47 #include <sys/malloc.h> 48 49 #include <nfs/nfsv2.h> 50 #include <nfs/nfs.h> 51 #include <nfs/nfsnode.h> 52 #include <nfs/nfsmount.h> 53 54 /* The request list head */ 55 extern struct nfsreq nfsreqh; 56 57 #define NFSNOHSZ 512 58 #if ((NFSNOHSZ&(NFSNOHSZ-1)) == 0) 59 #define NFSNOHASH(fhsum) ((fhsum)&(NFSNOHSZ-1)) 60 #else 61 #define NFSNOHASH(fhsum) (((unsigned)(fhsum))%NFSNOHSZ) 62 #endif 63 64 union nhead { 65 union nhead *nh_head[2]; 66 struct nfsnode *nh_chain[2]; 67 } nhead[NFSNOHSZ]; 68 69 #define TRUE 1 70 #define FALSE 0 71 72 /* 73 * Initialize hash links for nfsnodes 74 * and build nfsnode free list. 75 */ 76 nfs_nhinit() 77 { 78 register int i; 79 register union nhead *nh = nhead; 80 81 #ifndef lint 82 if (VN_MAXPRIVATE < sizeof(struct nfsnode)) 83 panic("nfs_nhinit: too small"); 84 #endif /* not lint */ 85 for (i = NFSNOHSZ; --i >= 0; nh++) { 86 nh->nh_head[0] = nh; 87 nh->nh_head[1] = nh; 88 } 89 } 90 91 /* 92 * Compute an entry in the NFS hash table structure 93 */ 94 union nhead * 95 nfs_hash(fhp) 96 register nfsv2fh_t *fhp; 97 { 98 register u_char *fhpp; 99 register u_long fhsum; 100 int i; 101 102 fhpp = &fhp->fh_bytes[0]; 103 fhsum = 0; 104 for (i = 0; i < NFSX_FH; i++) 105 fhsum += *fhpp++; 106 return (&nhead[NFSNOHASH(fhsum)]); 107 } 108 109 /* 110 * Look up a vnode/nfsnode by file handle. 111 * Callers must check for mount points!! 112 * In all cases, a pointer to a 113 * nfsnode structure is returned. 114 */ 115 nfs_nget(mntp, fhp, npp) 116 struct mount *mntp; 117 register nfsv2fh_t *fhp; 118 struct nfsnode **npp; 119 { 120 register struct nfsnode *np; 121 register struct vnode *vp; 122 extern struct vnodeops nfsv2_vnodeops; 123 struct vnode *nvp; 124 union nhead *nh; 125 int error; 126 127 nh = nfs_hash(fhp); 128 loop: 129 for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) { 130 if (mntp != NFSTOV(np)->v_mount || 131 bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH)) 132 continue; 133 vp = NFSTOV(np); 134 if (vget(vp, 1)) 135 goto loop; 136 *npp = np; 137 return(0); 138 } 139 if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) { 140 *npp = 0; 141 return (error); 142 } 143 vp = nvp; 144 np = VTONFS(vp); 145 np->n_vnode = vp; 146 /* 147 * Insert the nfsnode in the hash queue for its new file handle 148 */ 149 np->n_flag = 0; 150 insque(np, nh); 151 nfs_lock(vp); 152 bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH); 153 np->n_attrstamp = 0; 154 np->n_direofoffset = 0; 155 np->n_sillyrename = (struct sillyrename *)0; 156 np->n_size = 0; 157 np->n_mtime = 0; 158 np->n_lockf = 0; 159 np->n_delayed_mtime.ts_sec = VNOVAL; 160 np->n_delayed_mtime.ts_nsec = 0; /* XXX */ 161 np->n_delayed_atime.ts_sec = VNOVAL; 162 np->n_delayed_atime.ts_nsec = 0; /* XXX */ 163 *npp = np; 164 return (0); 165 } 166 167 nfs_inactive(vp, p) 168 struct vnode *vp; 169 struct proc *p; 170 { 171 register struct nfsnode *np; 172 register struct sillyrename *sp; 173 struct nfsnode *dnp; 174 extern int prtactive; 175 176 np = VTONFS(vp); 177 if (prtactive && vp->v_usecount != 0) 178 vprint("nfs_inactive: pushing active", vp); 179 nfs_lock(vp); 180 sp = np->n_sillyrename; 181 np->n_sillyrename = (struct sillyrename *)0; 182 if (sp) { 183 /* 184 * Remove the silly file that was rename'd earlier 185 */ 186 if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) { 187 sp->s_dvp = NFSTOV(dnp); 188 nfs_removeit(sp, p); 189 nfs_nput(sp->s_dvp); 190 } 191 crfree(sp->s_cred); 192 vrele(sp->s_dvp); 193 free((caddr_t)sp, M_NFSREQ); 194 } 195 nfs_unlock(vp); 196 np->n_flag &= NMODIFIED; 197 #ifdef notdef 198 /* 199 * Scan the request list for any requests left hanging about 200 */ 201 s = splnet(); 202 rep = nfsreqh.r_next; 203 while (rep && rep != &nfsreqh) { 204 if (rep->r_vp == vp) { 205 rep->r_prev->r_next = rep2 = rep->r_next; 206 rep->r_next->r_prev = rep->r_prev; 207 m_freem(rep->r_mreq); 208 if (rep->r_mrep != NULL) 209 m_freem(rep->r_mrep); 210 free((caddr_t)rep, M_NFSREQ); 211 rep = rep2; 212 } else 213 rep = rep->r_next; 214 } 215 splx(s); 216 #endif 217 return (0); 218 } 219 220 /* 221 * Reclaim an nfsnode so that it can be used for other purposes. 222 */ 223 nfs_reclaim(vp) 224 register struct vnode *vp; 225 { 226 register struct nfsnode *np = VTONFS(vp); 227 extern int prtactive; 228 229 if (prtactive && vp->v_usecount != 0) 230 vprint("nfs_reclaim: pushing active", vp); 231 /* 232 * Remove the nfsnode from its hash chain. 233 */ 234 remque(np); 235 np->n_forw = np; 236 np->n_back = np; 237 cache_purge(vp); 238 np->n_flag = 0; 239 np->n_direofoffset = 0; 240 return (0); 241 } 242 243 /* 244 * Lock an nfsnode 245 */ 246 247 nfs_lock(vp) 248 struct vnode *vp; 249 { 250 251 return (0); 252 } 253 254 /* 255 * Unlock an nfsnode 256 */ 257 nfs_unlock(vp) 258 struct vnode *vp; 259 { 260 261 return (0); 262 } 263 264 /* 265 * Check for a locked nfsnode 266 */ 267 nfs_islocked(vp) 268 struct vnode *vp; 269 { 270 271 return (0); 272 } 273 274 /* 275 * Unlock (i.e. do nothing) and vrele() 276 */ 277 nfs_nput(vp) 278 struct vnode *vp; 279 { 280 register struct nfsnode *np = VTONFS(vp); 281 282 vrele(vp); 283 } 284 285 /* 286 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 287 * done. Currently nothing to do. 288 */ 289 /* ARGSUSED */ 290 nfs_abortop(ndp) 291 struct nameidata *ndp; 292 { 293 294 if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF) 295 FREE(ndp->ni_pnbuf, M_NAMEI); 296 return (0); 297 } 298