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.39 (Berkeley) 05/15/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 { 146 register struct nfsnode *np; 147 register struct sillyrename *sp; 148 extern int prtactive; 149 150 np = VTONFS(ap->a_vp); 151 if (prtactive && ap->a_vp->v_usecount != 0) 152 vprint("nfs_inactive: pushing active", ap->a_vp); 153 sp = np->n_sillyrename; 154 np->n_sillyrename = (struct sillyrename *)0; 155 if (sp) { 156 /* 157 * Remove the silly file that was rename'd earlier 158 */ 159 nfs_removeit(sp, ap->a_p); 160 crfree(sp->s_cred); 161 vrele(sp->s_dvp); 162 #ifdef SILLYSEPARATE 163 free((caddr_t)sp, M_NFSREQ); 164 #endif 165 } 166 np->n_flag &= NMODIFIED; 167 return (0); 168 } 169 170 /* 171 * Reclaim an nfsnode so that it can be used for other purposes. 172 */ 173 nfs_reclaim (ap) 174 struct vop_reclaim_args *ap; 175 { 176 register struct nfsnode *np = VTONFS(ap->a_vp); 177 register struct nfsmount *nmp = VFSTONFS(ap->a_vp->v_mount); 178 extern int prtactive; 179 180 if (prtactive && ap->a_vp->v_usecount != 0) 181 vprint("nfs_reclaim: pushing active", ap->a_vp); 182 /* 183 * Remove the nfsnode from its hash chain. 184 */ 185 remque(np); 186 187 /* 188 * For nqnfs, take it off the timer queue as required. 189 */ 190 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) { 191 if (np->n_tnext == (struct nfsnode *)nmp) 192 nmp->nm_tprev = np->n_tprev; 193 else 194 np->n_tnext->n_tprev = np->n_tprev; 195 if (np->n_tprev == (struct nfsnode *)nmp) 196 nmp->nm_tnext = np->n_tnext; 197 else 198 np->n_tprev->n_tnext = np->n_tnext; 199 } 200 cache_purge(ap->a_vp); 201 FREE(ap->a_vp->v_data, M_NFSNODE); 202 ap->a_vp->v_data = (void *)0; 203 return (0); 204 } 205 206 /* 207 * Lock an nfsnode 208 */ 209 nfs_lock (ap) 210 struct vop_lock_args *ap; 211 { 212 213 return (0); 214 } 215 216 /* 217 * Unlock an nfsnode 218 */ 219 nfs_unlock (ap) 220 struct vop_unlock_args *ap; 221 { 222 223 return (0); 224 } 225 226 /* 227 * Check for a locked nfsnode 228 */ 229 nfs_islocked (ap) 230 struct vop_islocked_args *ap; 231 { 232 233 return (0); 234 } 235 236 /* 237 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 238 * done. Currently nothing to do. 239 */ 240 /* ARGSUSED */ 241 int 242 nfs_abortop (ap) 243 struct vop_abortop_args *ap; 244 { 245 246 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 247 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 248 return (0); 249 } 250