xref: /csrg-svn/sys/nfs/nfs_node.c (revision 68653)
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