138415Smckusick /* 263233Sbostic * Copyright (c) 1989, 1993 363233Sbostic * The Regents of the University of California. All rights reserved. 438415Smckusick * 538415Smckusick * This code is derived from software contributed to Berkeley by 638415Smckusick * Rick Macklem at The University of Guelph. 738415Smckusick * 844509Sbostic * %sccs.include.redist.c% 938415Smckusick * 10*69423Smckusick * @(#)nfs_node.c 8.5 (Berkeley) 05/14/95 1138415Smckusick */ 1238415Smckusick 1368653Smckusick 1456535Sbostic #include <sys/param.h> 1556535Sbostic #include <sys/systm.h> 1656535Sbostic #include <sys/proc.h> 1756535Sbostic #include <sys/mount.h> 1856535Sbostic #include <sys/namei.h> 1956535Sbostic #include <sys/vnode.h> 2056535Sbostic #include <sys/kernel.h> 2156535Sbostic #include <sys/malloc.h> 2247573Skarels 2356535Sbostic #include <nfs/rpcv2.h> 2468653Smckusick #include <nfs/nfsproto.h> 2556535Sbostic #include <nfs/nfs.h> 2656535Sbostic #include <nfs/nfsnode.h> 2756535Sbostic #include <nfs/nfsmount.h> 2856535Sbostic #include <nfs/nqnfs.h> 2938415Smckusick 3067708Smckusick LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; 3167708Smckusick u_long nfsnodehash; 3238415Smckusick 3338884Smacklem #define TRUE 1 3438884Smacklem #define FALSE 0 3538884Smacklem 3638415Smckusick /* 3738415Smckusick * Initialize hash links for nfsnodes 3838415Smckusick * and build nfsnode free list. 3938415Smckusick */ 4068653Smckusick void 4138415Smckusick nfs_nhinit() 4238415Smckusick { 4338415Smckusick 4439494Smckusick #ifndef lint 4551985Smckusick if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode)) 4651985Smckusick printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode)); 4739494Smckusick #endif /* not lint */ 4867708Smckusick nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, &nfsnodehash); 4938415Smckusick } 5038415Smckusick 5138415Smckusick /* 5239445Smckusick * Compute an entry in the NFS hash table structure 5339445Smckusick */ 5468653Smckusick u_long 5568653Smckusick nfs_hash(fhp, fhsize) 5668653Smckusick register nfsfh_t *fhp; 5768653Smckusick int fhsize; 5839445Smckusick { 5939445Smckusick register u_char *fhpp; 6039445Smckusick register u_long fhsum; 6168653Smckusick register int i; 6239445Smckusick 6339445Smckusick fhpp = &fhp->fh_bytes[0]; 6439445Smckusick fhsum = 0; 6568653Smckusick for (i = 0; i < fhsize; i++) 6639445Smckusick fhsum += *fhpp++; 6768653Smckusick return (fhsum); 6839445Smckusick } 6939445Smckusick 7039445Smckusick /* 7139395Smckusick * Look up a vnode/nfsnode by file handle. 7238415Smckusick * Callers must check for mount points!! 7338415Smckusick * In all cases, a pointer to a 7438415Smckusick * nfsnode structure is returned. 7538415Smckusick */ 7668653Smckusick int 7768653Smckusick nfs_nget(mntp, fhp, fhsize, npp) 7838415Smckusick struct mount *mntp; 7968653Smckusick register nfsfh_t *fhp; 8068653Smckusick int fhsize; 8138415Smckusick struct nfsnode **npp; 8238415Smckusick { 83*69423Smckusick struct proc *p = curproc; /* XXX */ 84*69423Smckusick struct nfsnode *np; 8567708Smckusick struct nfsnodehashhead *nhpp; 8638415Smckusick register struct vnode *vp; 8753550Sheideman extern int (**nfsv2_vnodeop_p)(); 8839395Smckusick struct vnode *nvp; 8939445Smckusick int error; 9038415Smckusick 9168653Smckusick nhpp = NFSNOHASH(nfs_hash(fhp, fhsize)); 9238415Smckusick loop: 9367708Smckusick for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 9468653Smckusick if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 9568653Smckusick bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 9639395Smckusick continue; 9739395Smckusick vp = NFSTOV(np); 98*69423Smckusick if (vget(vp, LK_EXCLUSIVE, p)) 9939445Smckusick goto loop; 10039395Smckusick *npp = np; 10139395Smckusick return(0); 10238884Smacklem } 10368653Smckusick error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 10468653Smckusick if (error) { 10538415Smckusick *npp = 0; 10639395Smckusick return (error); 10738415Smckusick } 10839395Smckusick vp = nvp; 10951985Smckusick MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK); 11068653Smckusick bzero((caddr_t)np, sizeof *np); 11151985Smckusick vp->v_data = np; 11239395Smckusick np->n_vnode = vp; 11338415Smckusick /* 11438884Smacklem * Insert the nfsnode in the hash queue for its new file handle 11538884Smacklem */ 11667708Smckusick LIST_INSERT_HEAD(nhpp, np, n_hash); 11768653Smckusick if (fhsize > NFS_SMALLFH) { 11868653Smckusick MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); 11968653Smckusick } else 12068653Smckusick np->n_fhp = &np->n_fh; 12168653Smckusick bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 12268653Smckusick np->n_fhsize = fhsize; 12338415Smckusick *npp = np; 12438415Smckusick return (0); 12538415Smckusick } 12638415Smckusick 12768653Smckusick int 12854666Smckusick nfs_inactive(ap) 12954666Smckusick struct vop_inactive_args /* { 13054666Smckusick struct vnode *a_vp; 13154666Smckusick } */ *ap; 13238415Smckusick { 13338415Smckusick register struct nfsnode *np; 13438415Smckusick register struct sillyrename *sp; 13557784Smckusick struct proc *p = curproc; /* XXX */ 13639575Smckusick extern int prtactive; 13738415Smckusick 13853599Sheideman np = VTONFS(ap->a_vp); 13953599Sheideman if (prtactive && ap->a_vp->v_usecount != 0) 14053599Sheideman vprint("nfs_inactive: pushing active", ap->a_vp); 14168653Smckusick if (ap->a_vp->v_type != VDIR) 14268653Smckusick sp = np->n_sillyrename; 14368653Smckusick else 14468653Smckusick sp = (struct sillyrename *)0; 14539395Smckusick np->n_sillyrename = (struct sillyrename *)0; 14639395Smckusick if (sp) { 14738415Smckusick /* 14839395Smckusick * Remove the silly file that was rename'd earlier 14938415Smckusick */ 15057784Smckusick (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 15154447Smckusick nfs_removeit(sp); 15248364Smckusick crfree(sp->s_cred); 15348364Smckusick vrele(sp->s_dvp); 15468653Smckusick FREE((caddr_t)sp, M_NFSREQ); 15539395Smckusick } 15659705Smckusick np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 15759705Smckusick NQNFSNONCACHE | NQNFSWRITE); 15839395Smckusick return (0); 15939395Smckusick } 16039395Smckusick 16139395Smckusick /* 16239395Smckusick * Reclaim an nfsnode so that it can be used for other purposes. 16339395Smckusick */ 16468653Smckusick int 16554666Smckusick nfs_reclaim(ap) 16654666Smckusick struct vop_reclaim_args /* { 16754666Smckusick struct vnode *a_vp; 16854666Smckusick } */ *ap; 16939395Smckusick { 17054666Smckusick register struct vnode *vp = ap->a_vp; 17154666Smckusick register struct nfsnode *np = VTONFS(vp); 17254666Smckusick register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 17368653Smckusick register struct nfsdmap *dp, *dp2; 17439575Smckusick extern int prtactive; 17539395Smckusick 17654666Smckusick if (prtactive && vp->v_usecount != 0) 17754666Smckusick vprint("nfs_reclaim: pushing active", vp); 17868653Smckusick 17967708Smckusick LIST_REMOVE(np, n_hash); 18052196Smckusick 18152196Smckusick /* 18252196Smckusick * For nqnfs, take it off the timer queue as required. 18352196Smckusick */ 18468653Smckusick if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) { 18567708Smckusick CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 18668653Smckusick } 18768653Smckusick 18868653Smckusick /* 18968653Smckusick * Free up any directory cookie structures and 19068653Smckusick * large file handle structures that might be associated with 19168653Smckusick * this nfs node. 19268653Smckusick */ 19368653Smckusick if (vp->v_type == VDIR) { 19468653Smckusick dp = np->n_cookies.lh_first; 19568653Smckusick while (dp) { 19668653Smckusick dp2 = dp; 19768653Smckusick dp = dp->ndm_list.le_next; 19868653Smckusick FREE((caddr_t)dp2, M_NFSDIROFF); 19968653Smckusick } 20068653Smckusick } 20168653Smckusick if (np->n_fhsize > NFS_SMALLFH) { 20268653Smckusick FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 20368653Smckusick } 20468653Smckusick 20554666Smckusick cache_purge(vp); 20654666Smckusick FREE(vp->v_data, M_NFSNODE); 20754666Smckusick vp->v_data = (void *)0; 20838415Smckusick return (0); 20938415Smckusick } 21038415Smckusick 21138415Smckusick /* 21242467Smckusick * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 21342467Smckusick * done. Currently nothing to do. 21442467Smckusick */ 21542467Smckusick /* ARGSUSED */ 21652234Sheideman int 21754666Smckusick nfs_abortop(ap) 21854666Smckusick struct vop_abortop_args /* { 21954666Smckusick struct vnode *a_dvp; 22054666Smckusick struct componentname *a_cnp; 22154666Smckusick } */ *ap; 22238415Smckusick { 22338415Smckusick 22453599Sheideman if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 22553599Sheideman FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 22642467Smckusick return (0); 22738415Smckusick } 228