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*68653Smckusick * @(#)nfs_node.c 8.4 (Berkeley) 03/30/95 1138415Smckusick */ 1238415Smckusick 13*68653Smckusick 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> 24*68653Smckusick #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 */ 40*68653Smckusick 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 */ 54*68653Smckusick u_long 55*68653Smckusick nfs_hash(fhp, fhsize) 56*68653Smckusick register nfsfh_t *fhp; 57*68653Smckusick int fhsize; 5839445Smckusick { 5939445Smckusick register u_char *fhpp; 6039445Smckusick register u_long fhsum; 61*68653Smckusick register int i; 6239445Smckusick 6339445Smckusick fhpp = &fhp->fh_bytes[0]; 6439445Smckusick fhsum = 0; 65*68653Smckusick for (i = 0; i < fhsize; i++) 6639445Smckusick fhsum += *fhpp++; 67*68653Smckusick 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 */ 76*68653Smckusick int 77*68653Smckusick nfs_nget(mntp, fhp, fhsize, npp) 7838415Smckusick struct mount *mntp; 79*68653Smckusick register nfsfh_t *fhp; 80*68653Smckusick int fhsize; 8138415Smckusick struct nfsnode **npp; 8238415Smckusick { 8367708Smckusick register struct nfsnode *np; 8467708Smckusick struct nfsnodehashhead *nhpp; 8538415Smckusick register struct vnode *vp; 8653550Sheideman extern int (**nfsv2_vnodeop_p)(); 8739395Smckusick struct vnode *nvp; 8839445Smckusick int error; 8938415Smckusick 90*68653Smckusick nhpp = NFSNOHASH(nfs_hash(fhp, fhsize)); 9138415Smckusick loop: 9267708Smckusick for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 93*68653Smckusick if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 94*68653Smckusick bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 9539395Smckusick continue; 9639395Smckusick vp = NFSTOV(np); 9765249Smckusick if (vget(vp, 1)) 9839445Smckusick goto loop; 9939395Smckusick *npp = np; 10039395Smckusick return(0); 10138884Smacklem } 102*68653Smckusick error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 103*68653Smckusick if (error) { 10438415Smckusick *npp = 0; 10539395Smckusick return (error); 10638415Smckusick } 10739395Smckusick vp = nvp; 10851985Smckusick MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK); 109*68653Smckusick bzero((caddr_t)np, sizeof *np); 11051985Smckusick vp->v_data = np; 11139395Smckusick np->n_vnode = vp; 11238415Smckusick /* 11338884Smacklem * Insert the nfsnode in the hash queue for its new file handle 11438884Smacklem */ 11567708Smckusick LIST_INSERT_HEAD(nhpp, np, n_hash); 116*68653Smckusick if (fhsize > NFS_SMALLFH) { 117*68653Smckusick MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); 118*68653Smckusick } else 119*68653Smckusick np->n_fhp = &np->n_fh; 120*68653Smckusick bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 121*68653Smckusick np->n_fhsize = fhsize; 12238415Smckusick *npp = np; 12338415Smckusick return (0); 12438415Smckusick } 12538415Smckusick 126*68653Smckusick int 12754666Smckusick nfs_inactive(ap) 12854666Smckusick struct vop_inactive_args /* { 12954666Smckusick struct vnode *a_vp; 13054666Smckusick } */ *ap; 13138415Smckusick { 13238415Smckusick register struct nfsnode *np; 13338415Smckusick register struct sillyrename *sp; 13457784Smckusick struct proc *p = curproc; /* XXX */ 13539575Smckusick extern int prtactive; 13638415Smckusick 13753599Sheideman np = VTONFS(ap->a_vp); 13853599Sheideman if (prtactive && ap->a_vp->v_usecount != 0) 13953599Sheideman vprint("nfs_inactive: pushing active", ap->a_vp); 140*68653Smckusick if (ap->a_vp->v_type != VDIR) 141*68653Smckusick sp = np->n_sillyrename; 142*68653Smckusick else 143*68653Smckusick sp = (struct sillyrename *)0; 14439395Smckusick np->n_sillyrename = (struct sillyrename *)0; 14539395Smckusick if (sp) { 14638415Smckusick /* 14739395Smckusick * Remove the silly file that was rename'd earlier 14838415Smckusick */ 14957784Smckusick (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 15054447Smckusick nfs_removeit(sp); 15148364Smckusick crfree(sp->s_cred); 15248364Smckusick vrele(sp->s_dvp); 153*68653Smckusick FREE((caddr_t)sp, M_NFSREQ); 15439395Smckusick } 15559705Smckusick np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 15659705Smckusick NQNFSNONCACHE | NQNFSWRITE); 15739395Smckusick return (0); 15839395Smckusick } 15939395Smckusick 16039395Smckusick /* 16139395Smckusick * Reclaim an nfsnode so that it can be used for other purposes. 16239395Smckusick */ 163*68653Smckusick int 16454666Smckusick nfs_reclaim(ap) 16554666Smckusick struct vop_reclaim_args /* { 16654666Smckusick struct vnode *a_vp; 16754666Smckusick } */ *ap; 16839395Smckusick { 16954666Smckusick register struct vnode *vp = ap->a_vp; 17054666Smckusick register struct nfsnode *np = VTONFS(vp); 17154666Smckusick register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 172*68653Smckusick register struct nfsdmap *dp, *dp2; 17339575Smckusick extern int prtactive; 17439395Smckusick 17554666Smckusick if (prtactive && vp->v_usecount != 0) 17654666Smckusick vprint("nfs_reclaim: pushing active", vp); 177*68653Smckusick 17867708Smckusick LIST_REMOVE(np, n_hash); 17952196Smckusick 18052196Smckusick /* 18152196Smckusick * For nqnfs, take it off the timer queue as required. 18252196Smckusick */ 183*68653Smckusick if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) { 18467708Smckusick CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 185*68653Smckusick } 186*68653Smckusick 187*68653Smckusick /* 188*68653Smckusick * Free up any directory cookie structures and 189*68653Smckusick * large file handle structures that might be associated with 190*68653Smckusick * this nfs node. 191*68653Smckusick */ 192*68653Smckusick if (vp->v_type == VDIR) { 193*68653Smckusick dp = np->n_cookies.lh_first; 194*68653Smckusick while (dp) { 195*68653Smckusick dp2 = dp; 196*68653Smckusick dp = dp->ndm_list.le_next; 197*68653Smckusick FREE((caddr_t)dp2, M_NFSDIROFF); 198*68653Smckusick } 199*68653Smckusick } 200*68653Smckusick if (np->n_fhsize > NFS_SMALLFH) { 201*68653Smckusick FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 202*68653Smckusick } 203*68653Smckusick 20454666Smckusick cache_purge(vp); 20554666Smckusick FREE(vp->v_data, M_NFSNODE); 20654666Smckusick vp->v_data = (void *)0; 20738415Smckusick return (0); 20838415Smckusick } 20938415Smckusick 21038415Smckusick /* 21138415Smckusick * Lock an nfsnode 21238415Smckusick */ 213*68653Smckusick int 21454666Smckusick nfs_lock(ap) 21554666Smckusick struct vop_lock_args /* { 21654666Smckusick struct vnode *a_vp; 21754666Smckusick } */ *ap; 21838415Smckusick { 21956806Smckusick register struct vnode *vp = ap->a_vp; 22038415Smckusick 22157784Smckusick /* 22257784Smckusick * Ugh, another place where interruptible mounts will get hung. 22357784Smckusick * If you make this sleep interruptible, then you have to fix all 22457784Smckusick * the VOP_LOCK() calls to expect interruptibility. 22557784Smckusick */ 22656806Smckusick while (vp->v_flag & VXLOCK) { 22756806Smckusick vp->v_flag |= VXWANT; 228*68653Smckusick (void) tsleep((caddr_t)vp, PINOD, "nfslck", 0); 22956806Smckusick } 23056806Smckusick if (vp->v_tag == VT_NON) 23156806Smckusick return (ENOENT); 23252196Smckusick return (0); 23338415Smckusick } 23438415Smckusick 23538415Smckusick /* 23638415Smckusick * Unlock an nfsnode 23738415Smckusick */ 238*68653Smckusick int 23954666Smckusick nfs_unlock(ap) 24054666Smckusick struct vop_unlock_args /* { 24154666Smckusick struct vnode *a_vp; 24254666Smckusick } */ *ap; 24338415Smckusick { 24438415Smckusick 24552196Smckusick return (0); 24638415Smckusick } 24738415Smckusick 24838415Smckusick /* 24939908Smckusick * Check for a locked nfsnode 25039908Smckusick */ 251*68653Smckusick int 25254666Smckusick nfs_islocked(ap) 25354666Smckusick struct vop_islocked_args /* { 25454666Smckusick struct vnode *a_vp; 25554666Smckusick } */ *ap; 25639908Smckusick { 25739908Smckusick 25839908Smckusick return (0); 25939908Smckusick } 26039908Smckusick 26139908Smckusick /* 26242467Smckusick * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 26342467Smckusick * done. Currently nothing to do. 26442467Smckusick */ 26542467Smckusick /* ARGSUSED */ 26652234Sheideman int 26754666Smckusick nfs_abortop(ap) 26854666Smckusick struct vop_abortop_args /* { 26954666Smckusick struct vnode *a_dvp; 27054666Smckusick struct componentname *a_cnp; 27154666Smckusick } */ *ap; 27238415Smckusick { 27338415Smckusick 27453599Sheideman if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 27553599Sheideman FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 27642467Smckusick return (0); 27738415Smckusick } 278