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*54447Smckusick * @(#)nfs_node.c 7.40 (Berkeley) 06/25/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; 9753550Sheideman 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 } 11453550Sheideman 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) { 133*54447Smckusick np->n_brev = 0; 134*54447Smckusick np->n_lrev = 0; 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 14353550Sheideman nfs_inactive (ap) 14453550Sheideman struct vop_inactive_args *ap; 14538415Smckusick { 14638415Smckusick register struct nfsnode *np; 14738415Smckusick register struct sillyrename *sp; 14839575Smckusick extern int prtactive; 14938415Smckusick 15053599Sheideman np = VTONFS(ap->a_vp); 15153599Sheideman if (prtactive && ap->a_vp->v_usecount != 0) 15253599Sheideman vprint("nfs_inactive: pushing active", ap->a_vp); 15339395Smckusick sp = np->n_sillyrename; 15439395Smckusick np->n_sillyrename = (struct sillyrename *)0; 15539395Smckusick if (sp) { 15638415Smckusick /* 15739395Smckusick * Remove the silly file that was rename'd earlier 15838415Smckusick */ 159*54447Smckusick nfs_removeit(sp); 16048364Smckusick crfree(sp->s_cred); 16148364Smckusick vrele(sp->s_dvp); 16251985Smckusick #ifdef SILLYSEPARATE 16348364Smckusick free((caddr_t)sp, M_NFSREQ); 16451985Smckusick #endif 16539395Smckusick } 16641898Smckusick np->n_flag &= NMODIFIED; 16739395Smckusick return (0); 16839395Smckusick } 16939395Smckusick 17039395Smckusick /* 17139395Smckusick * Reclaim an nfsnode so that it can be used for other purposes. 17239395Smckusick */ 17353550Sheideman nfs_reclaim (ap) 17453550Sheideman struct vop_reclaim_args *ap; 17539395Smckusick { 17653599Sheideman register struct nfsnode *np = VTONFS(ap->a_vp); 17753599Sheideman register struct nfsmount *nmp = VFSTONFS(ap->a_vp->v_mount); 17839575Smckusick extern int prtactive; 17939395Smckusick 18053599Sheideman if (prtactive && ap->a_vp->v_usecount != 0) 18153599Sheideman vprint("nfs_reclaim: pushing active", ap->a_vp); 18239395Smckusick /* 18339395Smckusick * Remove the nfsnode from its hash chain. 18439395Smckusick */ 18539395Smckusick remque(np); 18652196Smckusick 18752196Smckusick /* 18852196Smckusick * For nqnfs, take it off the timer queue as required. 18952196Smckusick */ 19052196Smckusick if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) { 19152196Smckusick if (np->n_tnext == (struct nfsnode *)nmp) 19252196Smckusick nmp->nm_tprev = np->n_tprev; 19352196Smckusick else 19452196Smckusick np->n_tnext->n_tprev = np->n_tprev; 19552196Smckusick if (np->n_tprev == (struct nfsnode *)nmp) 19652196Smckusick nmp->nm_tnext = np->n_tnext; 19752196Smckusick else 19852196Smckusick np->n_tprev->n_tnext = np->n_tnext; 19952196Smckusick } 20053599Sheideman cache_purge(ap->a_vp); 20153599Sheideman FREE(ap->a_vp->v_data, M_NFSNODE); 20253599Sheideman ap->a_vp->v_data = (void *)0; 20338415Smckusick return (0); 20438415Smckusick } 20538415Smckusick 20638415Smckusick /* 20738415Smckusick * Lock an nfsnode 20838415Smckusick */ 20953550Sheideman nfs_lock (ap) 21053550Sheideman struct vop_lock_args *ap; 21138415Smckusick { 21238415Smckusick 21352196Smckusick return (0); 21438415Smckusick } 21538415Smckusick 21638415Smckusick /* 21738415Smckusick * Unlock an nfsnode 21838415Smckusick */ 21953550Sheideman nfs_unlock (ap) 22053550Sheideman struct vop_unlock_args *ap; 22138415Smckusick { 22238415Smckusick 22352196Smckusick return (0); 22438415Smckusick } 22538415Smckusick 22638415Smckusick /* 22739908Smckusick * Check for a locked nfsnode 22839908Smckusick */ 22953550Sheideman nfs_islocked (ap) 23053550Sheideman struct vop_islocked_args *ap; 23139908Smckusick { 23239908Smckusick 23339908Smckusick return (0); 23439908Smckusick } 23539908Smckusick 23639908Smckusick /* 23742467Smckusick * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually 23842467Smckusick * done. Currently nothing to do. 23942467Smckusick */ 24042467Smckusick /* ARGSUSED */ 24152234Sheideman int 24253550Sheideman nfs_abortop (ap) 24353550Sheideman struct vop_abortop_args *ap; 24438415Smckusick { 24538415Smckusick 24653599Sheideman if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 24753599Sheideman FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 24842467Smckusick return (0); 24938415Smckusick } 250