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.6 (Berkeley) 05/22/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 struct proc *p = curproc; /* XXX */ 84 struct nfsnode *np; 85 struct nfsnodehashhead *nhpp; 86 register struct vnode *vp; 87 extern int (**nfsv2_vnodeop_p)(); 88 struct vnode *nvp; 89 int error; 90 91 nhpp = NFSNOHASH(nfs_hash(fhp, fhsize)); 92 loop: 93 for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 94 if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 95 bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 96 continue; 97 vp = NFSTOV(np); 98 if (vget(vp, LK_EXCLUSIVE, p)) 99 goto loop; 100 *npp = np; 101 return(0); 102 } 103 error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 104 if (error) { 105 *npp = 0; 106 return (error); 107 } 108 vp = nvp; 109 MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK); 110 bzero((caddr_t)np, sizeof *np); 111 vp->v_data = np; 112 np->n_vnode = vp; 113 /* 114 * Insert the nfsnode in the hash queue for its new file handle 115 */ 116 LIST_INSERT_HEAD(nhpp, np, n_hash); 117 if (fhsize > NFS_SMALLFH) { 118 MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); 119 } else 120 np->n_fhp = &np->n_fh; 121 bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 122 np->n_fhsize = fhsize; 123 *npp = np; 124 return (0); 125 } 126 127 int 128 nfs_inactive(ap) 129 struct vop_inactive_args /* { 130 struct vnode *a_vp; 131 struct proc *a_p; 132 } */ *ap; 133 { 134 register struct nfsnode *np; 135 register struct sillyrename *sp; 136 struct proc *p = curproc; /* XXX */ 137 extern int prtactive; 138 139 np = VTONFS(ap->a_vp); 140 if (prtactive && ap->a_vp->v_usecount != 0) 141 vprint("nfs_inactive: pushing active", ap->a_vp); 142 if (ap->a_vp->v_type != VDIR) 143 sp = np->n_sillyrename; 144 else 145 sp = (struct sillyrename *)0; 146 np->n_sillyrename = (struct sillyrename *)0; 147 if (sp) { 148 /* 149 * Remove the silly file that was rename'd earlier 150 */ 151 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 152 nfs_removeit(sp); 153 crfree(sp->s_cred); 154 vrele(sp->s_dvp); 155 FREE((caddr_t)sp, M_NFSREQ); 156 } 157 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 158 NQNFSNONCACHE | NQNFSWRITE); 159 VOP_UNLOCK(ap->a_vp, 0, ap->a_p); 160 return (0); 161 } 162 163 /* 164 * Reclaim an nfsnode so that it can be used for other purposes. 165 */ 166 int 167 nfs_reclaim(ap) 168 struct vop_reclaim_args /* { 169 struct vnode *a_vp; 170 } */ *ap; 171 { 172 register struct vnode *vp = ap->a_vp; 173 register struct nfsnode *np = VTONFS(vp); 174 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 175 register struct nfsdmap *dp, *dp2; 176 extern int prtactive; 177 178 if (prtactive && vp->v_usecount != 0) 179 vprint("nfs_reclaim: pushing active", vp); 180 181 LIST_REMOVE(np, n_hash); 182 183 /* 184 * For nqnfs, take it off the timer queue as required. 185 */ 186 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) { 187 CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 188 } 189 190 /* 191 * Free up any directory cookie structures and 192 * large file handle structures that might be associated with 193 * this nfs node. 194 */ 195 if (vp->v_type == VDIR) { 196 dp = np->n_cookies.lh_first; 197 while (dp) { 198 dp2 = dp; 199 dp = dp->ndm_list.le_next; 200 FREE((caddr_t)dp2, M_NFSDIROFF); 201 } 202 } 203 if (np->n_fhsize > NFS_SMALLFH) { 204 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 205 } 206 207 cache_purge(vp); 208 FREE(vp->v_data, M_NFSNODE); 209 vp->v_data = (void *)0; 210 return (0); 211 } 212 213 /* 214 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 215 * done. Currently nothing to do. 216 */ 217 /* ARGSUSED */ 218 int 219 nfs_abortop(ap) 220 struct vop_abortop_args /* { 221 struct vnode *a_dvp; 222 struct componentname *a_cnp; 223 } */ *ap; 224 { 225 226 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 227 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 228 return (0); 229 } 230