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.4 (Berkeley) 03/30/95 11 */ 12 13 14 #include <sys/param.h> 15 #include <sys/systm.h> 16 #include <sys/proc.h> 17 #include <sys/mount.h> 18 #include <sys/namei.h> 19 #include <sys/vnode.h> 20 #include <sys/kernel.h> 21 #include <sys/malloc.h> 22 23 #include <nfs/rpcv2.h> 24 #include <nfs/nfsproto.h> 25 #include <nfs/nfs.h> 26 #include <nfs/nfsnode.h> 27 #include <nfs/nfsmount.h> 28 #include <nfs/nqnfs.h> 29 30 LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; 31 u_long nfsnodehash; 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 void 41 nfs_nhinit() 42 { 43 44 #ifndef lint 45 if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode)) 46 printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode)); 47 #endif /* not lint */ 48 nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, &nfsnodehash); 49 } 50 51 /* 52 * Compute an entry in the NFS hash table structure 53 */ 54 u_long 55 nfs_hash(fhp, fhsize) 56 register nfsfh_t *fhp; 57 int fhsize; 58 { 59 register u_char *fhpp; 60 register u_long fhsum; 61 register int i; 62 63 fhpp = &fhp->fh_bytes[0]; 64 fhsum = 0; 65 for (i = 0; i < fhsize; i++) 66 fhsum += *fhpp++; 67 return (fhsum); 68 } 69 70 /* 71 * Look up a vnode/nfsnode by file handle. 72 * Callers must check for mount points!! 73 * In all cases, a pointer to a 74 * nfsnode structure is returned. 75 */ 76 int 77 nfs_nget(mntp, fhp, fhsize, npp) 78 struct mount *mntp; 79 register nfsfh_t *fhp; 80 int fhsize; 81 struct nfsnode **npp; 82 { 83 register struct nfsnode *np; 84 struct nfsnodehashhead *nhpp; 85 register struct vnode *vp; 86 extern int (**nfsv2_vnodeop_p)(); 87 struct vnode *nvp; 88 int error; 89 90 nhpp = NFSNOHASH(nfs_hash(fhp, fhsize)); 91 loop: 92 for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 93 if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 94 bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 95 continue; 96 vp = NFSTOV(np); 97 if (vget(vp, 1)) 98 goto loop; 99 *npp = np; 100 return(0); 101 } 102 error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 103 if (error) { 104 *npp = 0; 105 return (error); 106 } 107 vp = nvp; 108 MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK); 109 bzero((caddr_t)np, sizeof *np); 110 vp->v_data = np; 111 np->n_vnode = vp; 112 /* 113 * Insert the nfsnode in the hash queue for its new file handle 114 */ 115 LIST_INSERT_HEAD(nhpp, np, n_hash); 116 if (fhsize > NFS_SMALLFH) { 117 MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); 118 } else 119 np->n_fhp = &np->n_fh; 120 bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 121 np->n_fhsize = fhsize; 122 *npp = np; 123 return (0); 124 } 125 126 int 127 nfs_inactive(ap) 128 struct vop_inactive_args /* { 129 struct vnode *a_vp; 130 } */ *ap; 131 { 132 register struct nfsnode *np; 133 register struct sillyrename *sp; 134 struct proc *p = curproc; /* XXX */ 135 extern int prtactive; 136 137 np = VTONFS(ap->a_vp); 138 if (prtactive && ap->a_vp->v_usecount != 0) 139 vprint("nfs_inactive: pushing active", ap->a_vp); 140 if (ap->a_vp->v_type != VDIR) 141 sp = np->n_sillyrename; 142 else 143 sp = (struct sillyrename *)0; 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 FREE((caddr_t)sp, M_NFSREQ); 154 } 155 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 156 NQNFSNONCACHE | NQNFSWRITE); 157 return (0); 158 } 159 160 /* 161 * Reclaim an nfsnode so that it can be used for other purposes. 162 */ 163 int 164 nfs_reclaim(ap) 165 struct vop_reclaim_args /* { 166 struct vnode *a_vp; 167 } */ *ap; 168 { 169 register struct vnode *vp = ap->a_vp; 170 register struct nfsnode *np = VTONFS(vp); 171 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 172 register struct nfsdmap *dp, *dp2; 173 extern int prtactive; 174 175 if (prtactive && vp->v_usecount != 0) 176 vprint("nfs_reclaim: pushing active", vp); 177 178 LIST_REMOVE(np, n_hash); 179 180 /* 181 * For nqnfs, take it off the timer queue as required. 182 */ 183 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) { 184 CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 185 } 186 187 /* 188 * Free up any directory cookie structures and 189 * large file handle structures that might be associated with 190 * this nfs node. 191 */ 192 if (vp->v_type == VDIR) { 193 dp = np->n_cookies.lh_first; 194 while (dp) { 195 dp2 = dp; 196 dp = dp->ndm_list.le_next; 197 FREE((caddr_t)dp2, M_NFSDIROFF); 198 } 199 } 200 if (np->n_fhsize > NFS_SMALLFH) { 201 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 202 } 203 204 cache_purge(vp); 205 FREE(vp->v_data, M_NFSNODE); 206 vp->v_data = (void *)0; 207 return (0); 208 } 209 210 /* 211 * Lock an nfsnode 212 */ 213 int 214 nfs_lock(ap) 215 struct vop_lock_args /* { 216 struct vnode *a_vp; 217 } */ *ap; 218 { 219 register struct vnode *vp = ap->a_vp; 220 221 /* 222 * Ugh, another place where interruptible mounts will get hung. 223 * If you make this sleep interruptible, then you have to fix all 224 * the VOP_LOCK() calls to expect interruptibility. 225 */ 226 while (vp->v_flag & VXLOCK) { 227 vp->v_flag |= VXWANT; 228 (void) tsleep((caddr_t)vp, PINOD, "nfslck", 0); 229 } 230 if (vp->v_tag == VT_NON) 231 return (ENOENT); 232 return (0); 233 } 234 235 /* 236 * Unlock an nfsnode 237 */ 238 int 239 nfs_unlock(ap) 240 struct vop_unlock_args /* { 241 struct vnode *a_vp; 242 } */ *ap; 243 { 244 245 return (0); 246 } 247 248 /* 249 * Check for a locked nfsnode 250 */ 251 int 252 nfs_islocked(ap) 253 struct vop_islocked_args /* { 254 struct vnode *a_vp; 255 } */ *ap; 256 { 257 258 return (0); 259 } 260 261 /* 262 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 263 * done. Currently nothing to do. 264 */ 265 /* ARGSUSED */ 266 int 267 nfs_abortop(ap) 268 struct vop_abortop_args /* { 269 struct vnode *a_dvp; 270 struct componentname *a_cnp; 271 } */ *ap; 272 { 273 274 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 275 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 276 return (0); 277 } 278