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.5 (Berkeley) 05/14/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 } */ *ap; 132 { 133 register struct nfsnode *np; 134 register struct sillyrename *sp; 135 struct proc *p = curproc; /* XXX */ 136 extern int prtactive; 137 138 np = VTONFS(ap->a_vp); 139 if (prtactive && ap->a_vp->v_usecount != 0) 140 vprint("nfs_inactive: pushing active", ap->a_vp); 141 if (ap->a_vp->v_type != VDIR) 142 sp = np->n_sillyrename; 143 else 144 sp = (struct sillyrename *)0; 145 np->n_sillyrename = (struct sillyrename *)0; 146 if (sp) { 147 /* 148 * Remove the silly file that was rename'd earlier 149 */ 150 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 151 nfs_removeit(sp); 152 crfree(sp->s_cred); 153 vrele(sp->s_dvp); 154 FREE((caddr_t)sp, M_NFSREQ); 155 } 156 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 157 NQNFSNONCACHE | NQNFSWRITE); 158 return (0); 159 } 160 161 /* 162 * Reclaim an nfsnode so that it can be used for other purposes. 163 */ 164 int 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 nfsdmap *dp, *dp2; 174 extern int prtactive; 175 176 if (prtactive && vp->v_usecount != 0) 177 vprint("nfs_reclaim: pushing active", vp); 178 179 LIST_REMOVE(np, n_hash); 180 181 /* 182 * For nqnfs, take it off the timer queue as required. 183 */ 184 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) { 185 CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 186 } 187 188 /* 189 * Free up any directory cookie structures and 190 * large file handle structures that might be associated with 191 * this nfs node. 192 */ 193 if (vp->v_type == VDIR) { 194 dp = np->n_cookies.lh_first; 195 while (dp) { 196 dp2 = dp; 197 dp = dp->ndm_list.le_next; 198 FREE((caddr_t)dp2, M_NFSDIROFF); 199 } 200 } 201 if (np->n_fhsize > NFS_SMALLFH) { 202 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 203 } 204 205 cache_purge(vp); 206 FREE(vp->v_data, M_NFSNODE); 207 vp->v_data = (void *)0; 208 return (0); 209 } 210 211 /* 212 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 213 * done. Currently nothing to do. 214 */ 215 /* ARGSUSED */ 216 int 217 nfs_abortop(ap) 218 struct vop_abortop_args /* { 219 struct vnode *a_dvp; 220 struct componentname *a_cnp; 221 } */ *ap; 222 { 223 224 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 225 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 226 return (0); 227 } 228