1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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 8.1 (Berkeley) 06/10/93 11 */ 12 13 #include <sys/param.h> 14 #include <sys/systm.h> 15 #include <sys/proc.h> 16 #include <sys/mount.h> 17 #include <sys/namei.h> 18 #include <sys/vnode.h> 19 #include <sys/kernel.h> 20 #include <sys/malloc.h> 21 22 #include <nfs/rpcv2.h> 23 #include <nfs/nfsv2.h> 24 #include <nfs/nfs.h> 25 #include <nfs/nfsnode.h> 26 #include <nfs/nfsmount.h> 27 #include <nfs/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 np->n_mtime = 0; 120 if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) { 121 np->n_brev = 0; 122 np->n_lrev = 0; 123 np->n_expiry = (time_t)0; 124 np->n_tnext = (struct nfsnode *)0; 125 } 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 struct proc *p = curproc; /* XXX */ 138 extern int prtactive; 139 140 np = VTONFS(ap->a_vp); 141 if (prtactive && ap->a_vp->v_usecount != 0) 142 vprint("nfs_inactive: pushing active", ap->a_vp); 143 sp = np->n_sillyrename; 144 np->n_sillyrename = (struct sillyrename *)0; 145 if (sp) { 146 /* 147 * Remove the silly file that was rename'd earlier 148 */ 149 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 150 nfs_removeit(sp); 151 crfree(sp->s_cred); 152 vrele(sp->s_dvp); 153 #ifdef SILLYSEPARATE 154 free((caddr_t)sp, M_NFSREQ); 155 #endif 156 } 157 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 158 NQNFSNONCACHE | NQNFSWRITE); 159 return (0); 160 } 161 162 /* 163 * Reclaim an nfsnode so that it can be used for other purposes. 164 */ 165 nfs_reclaim(ap) 166 struct vop_reclaim_args /* { 167 struct vnode *a_vp; 168 } */ *ap; 169 { 170 register struct vnode *vp = ap->a_vp; 171 register struct nfsnode *np = VTONFS(vp); 172 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 173 register struct nfsnode *nq; 174 extern int prtactive; 175 176 if (prtactive && vp->v_usecount != 0) 177 vprint("nfs_reclaim: pushing active", vp); 178 /* 179 * Remove the nfsnode from its hash chain. 180 */ 181 if (nq = np->n_forw) 182 nq->n_back = np->n_back; 183 *np->n_back = nq; 184 185 /* 186 * For nqnfs, take it off the timer queue as required. 187 */ 188 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) { 189 if (np->n_tnext == (struct nfsnode *)nmp) 190 nmp->nm_tprev = np->n_tprev; 191 else 192 np->n_tnext->n_tprev = np->n_tprev; 193 if (np->n_tprev == (struct nfsnode *)nmp) 194 nmp->nm_tnext = np->n_tnext; 195 else 196 np->n_tprev->n_tnext = np->n_tnext; 197 } 198 cache_purge(vp); 199 FREE(vp->v_data, M_NFSNODE); 200 vp->v_data = (void *)0; 201 return (0); 202 } 203 204 /* 205 * Lock an nfsnode 206 */ 207 nfs_lock(ap) 208 struct vop_lock_args /* { 209 struct vnode *a_vp; 210 } */ *ap; 211 { 212 register struct vnode *vp = ap->a_vp; 213 214 /* 215 * Ugh, another place where interruptible mounts will get hung. 216 * If you make this sleep interruptible, then you have to fix all 217 * the VOP_LOCK() calls to expect interruptibility. 218 */ 219 while (vp->v_flag & VXLOCK) { 220 vp->v_flag |= VXWANT; 221 sleep((caddr_t)vp, PINOD); 222 } 223 if (vp->v_tag == VT_NON) 224 return (ENOENT); 225 return (0); 226 } 227 228 /* 229 * Unlock an nfsnode 230 */ 231 nfs_unlock(ap) 232 struct vop_unlock_args /* { 233 struct vnode *a_vp; 234 } */ *ap; 235 { 236 237 return (0); 238 } 239 240 /* 241 * Check for a locked nfsnode 242 */ 243 nfs_islocked(ap) 244 struct vop_islocked_args /* { 245 struct vnode *a_vp; 246 } */ *ap; 247 { 248 249 return (0); 250 } 251 252 /* 253 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 254 * done. Currently nothing to do. 255 */ 256 /* ARGSUSED */ 257 int 258 nfs_abortop(ap) 259 struct vop_abortop_args /* { 260 struct vnode *a_dvp; 261 struct componentname *a_cnp; 262 } */ *ap; 263 { 264 265 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 266 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 267 return (0); 268 } 269