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 * %sccs.include.redist.c% 9 * 10 * @(#)nfs_node.c 7.42 (Berkeley) 07/22/92 11 */ 12 13 #include "param.h" 14 #include "systm.h" 15 #include "proc.h" 16 #include "mount.h" 17 #include "namei.h" 18 #include "vnode.h" 19 #include "kernel.h" 20 #include "malloc.h" 21 22 #include "rpcv2.h" 23 #include "nfsv2.h" 24 #include "nfs.h" 25 #include "nfsnode.h" 26 #include "nfsmount.h" 27 #include "nqnfs.h" 28 29 struct nfsnode **nheadhashtbl; 30 u_long nheadhash; 31 #define NFSNOHASH(fhsum) ((fhsum)&nheadhash) 32 33 #define TRUE 1 34 #define FALSE 0 35 36 /* 37 * Initialize hash links for nfsnodes 38 * and build nfsnode free list. 39 */ 40 nfs_nhinit() 41 { 42 43 #ifndef lint 44 if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode)) 45 printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode)); 46 #endif /* not lint */ 47 nheadhashtbl = hashinit(desiredvnodes, M_NFSNODE, &nheadhash); 48 } 49 50 /* 51 * Compute an entry in the NFS hash table structure 52 */ 53 struct nfsnode ** 54 nfs_hash(fhp) 55 register nfsv2fh_t *fhp; 56 { 57 register u_char *fhpp; 58 register u_long fhsum; 59 int i; 60 61 fhpp = &fhp->fh_bytes[0]; 62 fhsum = 0; 63 for (i = 0; i < NFSX_FH; i++) 64 fhsum += *fhpp++; 65 return (&nheadhashtbl[NFSNOHASH(fhsum)]); 66 } 67 68 /* 69 * Look up a vnode/nfsnode by file handle. 70 * Callers must check for mount points!! 71 * In all cases, a pointer to a 72 * nfsnode structure is returned. 73 */ 74 nfs_nget(mntp, fhp, npp) 75 struct mount *mntp; 76 register nfsv2fh_t *fhp; 77 struct nfsnode **npp; 78 { 79 register struct nfsnode *np, *nq, **nhpp; 80 register struct vnode *vp; 81 extern int (**nfsv2_vnodeop_p)(); 82 struct vnode *nvp; 83 int error; 84 85 nhpp = nfs_hash(fhp); 86 loop: 87 for (np = *nhpp; np; np = np->n_forw) { 88 if (mntp != NFSTOV(np)->v_mount || 89 bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH)) 90 continue; 91 vp = NFSTOV(np); 92 if (vget(vp)) 93 goto loop; 94 *npp = np; 95 return(0); 96 } 97 if (error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp)) { 98 *npp = 0; 99 return (error); 100 } 101 vp = nvp; 102 MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK); 103 vp->v_data = np; 104 np->n_vnode = vp; 105 /* 106 * Insert the nfsnode in the hash queue for its new file handle 107 */ 108 np->n_flag = 0; 109 if (nq = *nhpp) 110 nq->n_back = &np->n_forw; 111 np->n_forw = nq; 112 np->n_back = nhpp; 113 *nhpp = np; 114 bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH); 115 np->n_attrstamp = 0; 116 np->n_direofoffset = 0; 117 np->n_sillyrename = (struct sillyrename *)0; 118 np->n_size = 0; 119 if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) { 120 np->n_brev = 0; 121 np->n_lrev = 0; 122 np->n_expiry = (time_t)0; 123 np->n_tnext = (struct nfsnode *)0; 124 } else 125 np->n_mtime = 0; 126 *npp = np; 127 return (0); 128 } 129 130 nfs_inactive(ap) 131 struct vop_inactive_args /* { 132 struct vnode *a_vp; 133 } */ *ap; 134 { 135 register struct nfsnode *np; 136 register struct sillyrename *sp; 137 extern int prtactive; 138 139 np = VTONFS(ap->a_vp); 140 if (prtactive && ap->a_vp->v_usecount != 0) 141 vprint("nfs_inactive: pushing active", ap->a_vp); 142 sp = np->n_sillyrename; 143 np->n_sillyrename = (struct sillyrename *)0; 144 if (sp) { 145 /* 146 * Remove the silly file that was rename'd earlier 147 */ 148 nfs_removeit(sp); 149 crfree(sp->s_cred); 150 vrele(sp->s_dvp); 151 #ifdef SILLYSEPARATE 152 free((caddr_t)sp, M_NFSREQ); 153 #endif 154 } 155 np->n_flag &= NMODIFIED; 156 return (0); 157 } 158 159 /* 160 * Reclaim an nfsnode so that it can be used for other purposes. 161 */ 162 nfs_reclaim(ap) 163 struct vop_reclaim_args /* { 164 struct vnode *a_vp; 165 } */ *ap; 166 { 167 register struct vnode *vp = ap->a_vp; 168 register struct nfsnode *np = VTONFS(vp); 169 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 170 register struct nfsnode *nq; 171 extern int prtactive; 172 173 if (prtactive && vp->v_usecount != 0) 174 vprint("nfs_reclaim: pushing active", vp); 175 /* 176 * Remove the nfsnode from its hash chain. 177 */ 178 if (nq = np->n_forw) 179 nq->n_back = np->n_back; 180 *np->n_back = nq; 181 182 /* 183 * For nqnfs, take it off the timer queue as required. 184 */ 185 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) { 186 if (np->n_tnext == (struct nfsnode *)nmp) 187 nmp->nm_tprev = np->n_tprev; 188 else 189 np->n_tnext->n_tprev = np->n_tprev; 190 if (np->n_tprev == (struct nfsnode *)nmp) 191 nmp->nm_tnext = np->n_tnext; 192 else 193 np->n_tprev->n_tnext = np->n_tnext; 194 } 195 cache_purge(vp); 196 FREE(vp->v_data, M_NFSNODE); 197 vp->v_data = (void *)0; 198 return (0); 199 } 200 201 /* 202 * Lock an nfsnode 203 */ 204 nfs_lock(ap) 205 struct vop_lock_args /* { 206 struct vnode *a_vp; 207 } */ *ap; 208 { 209 210 return (0); 211 } 212 213 /* 214 * Unlock an nfsnode 215 */ 216 nfs_unlock(ap) 217 struct vop_unlock_args /* { 218 struct vnode *a_vp; 219 } */ *ap; 220 { 221 222 return (0); 223 } 224 225 /* 226 * Check for a locked nfsnode 227 */ 228 nfs_islocked(ap) 229 struct vop_islocked_args /* { 230 struct vnode *a_vp; 231 } */ *ap; 232 { 233 234 return (0); 235 } 236 237 /* 238 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 239 * done. Currently nothing to do. 240 */ 241 /* ARGSUSED */ 242 int 243 nfs_abortop(ap) 244 struct vop_abortop_args /* { 245 struct vnode *a_dvp; 246 struct componentname *a_cnp; 247 } */ *ap; 248 { 249 250 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 251 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 252 return (0); 253 } 254