138415Smckusick /* 238415Smckusick * Copyright (c) 1989 The Regents of the University of California. 338415Smckusick * 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*53550Sheideman * @(#)nfs_node.c 7.38 (Berkeley) 05/14/92 1138415Smckusick */ 1238415Smckusick 1338415Smckusick #include "param.h" 1438415Smckusick #include "systm.h" 1538415Smckusick #include "proc.h" 1638415Smckusick #include "mount.h" 1748052Smckusick #include "namei.h" 1838415Smckusick #include "vnode.h" 1947573Skarels #include "kernel.h" 2047573Skarels #include "malloc.h" 2147573Skarels 2252196Smckusick #include "rpcv2.h" 2338415Smckusick #include "nfsv2.h" 2438415Smckusick #include "nfs.h" 2538415Smckusick #include "nfsnode.h" 2638415Smckusick #include "nfsmount.h" 2752196Smckusick #include "nqnfs.h" 2838415Smckusick 2938415Smckusick /* The request list head */ 3038415Smckusick extern struct nfsreq nfsreqh; 3138415Smckusick 3238415Smckusick #define NFSNOHSZ 512 3338415Smckusick #if ((NFSNOHSZ&(NFSNOHSZ-1)) == 0) 3438415Smckusick #define NFSNOHASH(fhsum) ((fhsum)&(NFSNOHSZ-1)) 3538415Smckusick #else 3638415Smckusick #define NFSNOHASH(fhsum) (((unsigned)(fhsum))%NFSNOHSZ) 3738415Smckusick #endif 3838415Smckusick 3939395Smckusick union nhead { 4038415Smckusick union nhead *nh_head[2]; 4138415Smckusick struct nfsnode *nh_chain[2]; 4238415Smckusick } nhead[NFSNOHSZ]; 4338415Smckusick 4438884Smacklem #define TRUE 1 4538884Smacklem #define FALSE 0 4638884Smacklem 4738415Smckusick /* 4838415Smckusick * Initialize hash links for nfsnodes 4938415Smckusick * and build nfsnode free list. 5038415Smckusick */ 5138415Smckusick nfs_nhinit() 5238415Smckusick { 5338415Smckusick register int i; 5438415Smckusick register union nhead *nh = nhead; 5538415Smckusick 5639494Smckusick #ifndef lint 5751985Smckusick if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode)) 5851985Smckusick printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode)); 5939494Smckusick #endif /* not lint */ 6038415Smckusick for (i = NFSNOHSZ; --i >= 0; nh++) { 6138415Smckusick nh->nh_head[0] = nh; 6238415Smckusick nh->nh_head[1] = nh; 6338415Smckusick } 6438415Smckusick } 6538415Smckusick 6638415Smckusick /* 6739445Smckusick * Compute an entry in the NFS hash table structure 6839445Smckusick */ 6939445Smckusick union nhead * 7039445Smckusick nfs_hash(fhp) 7139445Smckusick register nfsv2fh_t *fhp; 7239445Smckusick { 7339445Smckusick register u_char *fhpp; 7439445Smckusick register u_long fhsum; 7539445Smckusick int i; 7639445Smckusick 7739445Smckusick fhpp = &fhp->fh_bytes[0]; 7839445Smckusick fhsum = 0; 7939445Smckusick for (i = 0; i < NFSX_FH; i++) 8039445Smckusick fhsum += *fhpp++; 8139445Smckusick return (&nhead[NFSNOHASH(fhsum)]); 8239445Smckusick } 8339445Smckusick 8439445Smckusick /* 8539395Smckusick * Look up a vnode/nfsnode by file handle. 8638415Smckusick * Callers must check for mount points!! 8738415Smckusick * In all cases, a pointer to a 8838415Smckusick * nfsnode structure is returned. 8938415Smckusick */ 9038415Smckusick nfs_nget(mntp, fhp, npp) 9138415Smckusick struct mount *mntp; 9238415Smckusick register nfsv2fh_t *fhp; 9338415Smckusick struct nfsnode **npp; 9438415Smckusick { 9538415Smckusick register struct nfsnode *np; 9638415Smckusick register struct vnode *vp; 97*53550Sheideman extern int (**nfsv2_vnodeop_p)(); 9839395Smckusick struct vnode *nvp; 9939395Smckusick union nhead *nh; 10039445Smckusick int error; 10138415Smckusick 10239445Smckusick nh = nfs_hash(fhp); 10338415Smckusick loop: 10438884Smacklem for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) { 10539395Smckusick if (mntp != NFSTOV(np)->v_mount || 10639395Smckusick bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH)) 10739395Smckusick continue; 10839395Smckusick vp = NFSTOV(np); 10939445Smckusick if (vget(vp)) 11039445Smckusick goto loop; 11139395Smckusick *npp = np; 11239395Smckusick return(0); 11338884Smacklem } 114*53550Sheideman if (error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp)) { 11538415Smckusick *npp = 0; 11639395Smckusick return (error); 11738415Smckusick } 11839395Smckusick vp = nvp; 11951985Smckusick MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK); 12051985Smckusick vp->v_data = np; 12139395Smckusick np->n_vnode = vp; 12238415Smckusick /* 12338884Smacklem * Insert the nfsnode in the hash queue for its new file handle 12438884Smacklem */ 12539908Smckusick np->n_flag = 0; 12638415Smckusick insque(np, nh); 12738415Smckusick bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH); 12838415Smckusick np->n_attrstamp = 0; 12941898Smckusick np->n_direofoffset = 0; 13038415Smckusick np->n_sillyrename = (struct sillyrename *)0; 13138884Smacklem np->n_size = 0; 13252196Smckusick if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) { 13352196Smckusick ZEROQUAD(np->n_brev); 13452196Smckusick ZEROQUAD(np->n_lrev); 13552196Smckusick np->n_expiry = (time_t)0; 13652196Smckusick np->n_tnext = (struct nfsnode *)0; 13752196Smckusick } else 13852196Smckusick np->n_mtime = 0; 13938415Smckusick *npp = np; 14038415Smckusick return (0); 14138415Smckusick } 14238415Smckusick 143*53550Sheideman nfs_inactive (ap) 144*53550Sheideman struct vop_inactive_args *ap; 145*53550Sheideman #define vp (ap->a_vp) 146*53550Sheideman #define p (ap->a_p) 14738415Smckusick { 14838415Smckusick register struct nfsnode *np; 14938415Smckusick register struct sillyrename *sp; 15039575Smckusick extern int prtactive; 15138415Smckusick 15239395Smckusick np = VTONFS(vp); 15339810Smckusick if (prtactive && vp->v_usecount != 0) 15439671Smckusick vprint("nfs_inactive: pushing active", vp); 15539395Smckusick sp = np->n_sillyrename; 15639395Smckusick np->n_sillyrename = (struct sillyrename *)0; 15739395Smckusick if (sp) { 15838415Smckusick /* 15939395Smckusick * Remove the silly file that was rename'd earlier 16038415Smckusick */ 16152196Smckusick nfs_removeit(sp, p); 16248364Smckusick crfree(sp->s_cred); 16348364Smckusick vrele(sp->s_dvp); 16451985Smckusick #ifdef SILLYSEPARATE 16548364Smckusick free((caddr_t)sp, M_NFSREQ); 16651985Smckusick #endif 16739395Smckusick } 16841898Smckusick np->n_flag &= NMODIFIED; 16939395Smckusick return (0); 17039395Smckusick } 171*53550Sheideman #undef vp 172*53550Sheideman #undef p 17339395Smckusick 17439395Smckusick /* 17539395Smckusick * Reclaim an nfsnode so that it can be used for other purposes. 17639395Smckusick */ 177*53550Sheideman nfs_reclaim (ap) 178*53550Sheideman struct vop_reclaim_args *ap; 179*53550Sheideman #define vp (ap->a_vp) 18039395Smckusick { 18139395Smckusick register struct nfsnode *np = VTONFS(vp); 18252196Smckusick register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 18339575Smckusick extern int prtactive; 18439395Smckusick 18539810Smckusick if (prtactive && vp->v_usecount != 0) 18639671Smckusick vprint("nfs_reclaim: pushing active", vp); 18739395Smckusick /* 18839395Smckusick * Remove the nfsnode from its hash chain. 18939395Smckusick */ 19039395Smckusick remque(np); 19152196Smckusick 19252196Smckusick /* 19352196Smckusick * For nqnfs, take it off the timer queue as required. 19452196Smckusick */ 19552196Smckusick if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) { 19652196Smckusick if (np->n_tnext == (struct nfsnode *)nmp) 19752196Smckusick nmp->nm_tprev = np->n_tprev; 19852196Smckusick else 19952196Smckusick np->n_tnext->n_tprev = np->n_tprev; 20052196Smckusick if (np->n_tprev == (struct nfsnode *)nmp) 20152196Smckusick nmp->nm_tnext = np->n_tnext; 20252196Smckusick else 20352196Smckusick np->n_tprev->n_tnext = np->n_tnext; 20452196Smckusick } 20539395Smckusick cache_purge(vp); 20651985Smckusick FREE(vp->v_data, M_NFSNODE); 20752196Smckusick vp->v_data = (void *)0; 20838415Smckusick return (0); 20938415Smckusick } 210*53550Sheideman #undef vp 21138415Smckusick 21238415Smckusick /* 21338415Smckusick * Lock an nfsnode 21438415Smckusick */ 215*53550Sheideman nfs_lock (ap) 216*53550Sheideman struct vop_lock_args *ap; 217*53550Sheideman #define vp (ap->a_vp) 21838415Smckusick { 21938415Smckusick 22052196Smckusick return (0); 22138415Smckusick } 222*53550Sheideman #undef vp 22338415Smckusick 22438415Smckusick /* 22538415Smckusick * Unlock an nfsnode 22638415Smckusick */ 227*53550Sheideman nfs_unlock (ap) 228*53550Sheideman struct vop_unlock_args *ap; 229*53550Sheideman #define vp (ap->a_vp) 23038415Smckusick { 23138415Smckusick 23252196Smckusick return (0); 23338415Smckusick } 234*53550Sheideman #undef vp 23538415Smckusick 23638415Smckusick /* 23739908Smckusick * Check for a locked nfsnode 23839908Smckusick */ 239*53550Sheideman nfs_islocked (ap) 240*53550Sheideman struct vop_islocked_args *ap; 241*53550Sheideman #define vp (ap->a_vp) 24239908Smckusick { 24339908Smckusick 24439908Smckusick return (0); 24539908Smckusick } 246*53550Sheideman #undef vp 24739908Smckusick 24839908Smckusick /* 24942467Smckusick * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 25042467Smckusick * done. Currently nothing to do. 25142467Smckusick */ 25242467Smckusick /* ARGSUSED */ 25352234Sheideman int 254*53550Sheideman nfs_abortop (ap) 255*53550Sheideman struct vop_abortop_args *ap; 256*53550Sheideman #define dvp (ap->a_dvp) 257*53550Sheideman #define cnp (ap->a_cnp) 25838415Smckusick { 25938415Smckusick 26052234Sheideman if ((cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 26152234Sheideman FREE(cnp->cn_pnbuf, M_NAMEI); 26242467Smckusick return (0); 26338415Smckusick } 264*53550Sheideman #undef dvp 265*53550Sheideman #undef cnp 266