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