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.37 (Berkeley) 01/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 /* 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 struct vnodeops nfsv2_vnodeops; 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_vnodeops, &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(vp, p) 144 struct vnode *vp; 145 struct proc *p; 146 { 147 register struct nfsnode *np; 148 register struct sillyrename *sp; 149 extern int prtactive; 150 151 np = VTONFS(vp); 152 if (prtactive && vp->v_usecount != 0) 153 vprint("nfs_inactive: pushing active", vp); 154 sp = np->n_sillyrename; 155 np->n_sillyrename = (struct sillyrename *)0; 156 if (sp) { 157 /* 158 * Remove the silly file that was rename'd earlier 159 */ 160 nfs_removeit(sp, p); 161 crfree(sp->s_cred); 162 vrele(sp->s_dvp); 163 #ifdef SILLYSEPARATE 164 free((caddr_t)sp, M_NFSREQ); 165 #endif 166 } 167 np->n_flag &= NMODIFIED; 168 return (0); 169 } 170 171 /* 172 * Reclaim an nfsnode so that it can be used for other purposes. 173 */ 174 nfs_reclaim(vp) 175 register struct vnode *vp; 176 { 177 register struct nfsnode *np = VTONFS(vp); 178 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 179 extern int prtactive; 180 181 if (prtactive && vp->v_usecount != 0) 182 vprint("nfs_reclaim: pushing active", vp); 183 /* 184 * Remove the nfsnode from its hash chain. 185 */ 186 remque(np); 187 188 /* 189 * For nqnfs, take it off the timer queue as required. 190 */ 191 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) { 192 if (np->n_tnext == (struct nfsnode *)nmp) 193 nmp->nm_tprev = np->n_tprev; 194 else 195 np->n_tnext->n_tprev = np->n_tprev; 196 if (np->n_tprev == (struct nfsnode *)nmp) 197 nmp->nm_tnext = np->n_tnext; 198 else 199 np->n_tprev->n_tnext = np->n_tnext; 200 } 201 cache_purge(vp); 202 FREE(vp->v_data, M_NFSNODE); 203 vp->v_data = (void *)0; 204 return (0); 205 } 206 207 /* 208 * Lock an nfsnode 209 */ 210 nfs_lock(vp) 211 struct vnode *vp; 212 { 213 214 return (0); 215 } 216 217 /* 218 * Unlock an nfsnode 219 */ 220 nfs_unlock(vp) 221 struct vnode *vp; 222 { 223 224 return (0); 225 } 226 227 /* 228 * Check for a locked nfsnode 229 */ 230 nfs_islocked(vp) 231 struct vnode *vp; 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(dvp, cnp) 244 struct vnode *dvp; 245 struct componentname *cnp; 246 { 247 248 if ((cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 249 FREE(cnp->cn_pnbuf, M_NAMEI); 250 return (0); 251 } 252