xref: /csrg-svn/sys/nfs/nfs_node.c (revision 57784)
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*57784Smckusick  *	@(#)nfs_node.c	7.46 (Berkeley) 02/02/93
1138415Smckusick  */
1238415Smckusick 
1356535Sbostic #include <sys/param.h>
1456535Sbostic #include <sys/systm.h>
1556535Sbostic #include <sys/proc.h>
1656535Sbostic #include <sys/mount.h>
1756535Sbostic #include <sys/namei.h>
1856535Sbostic #include <sys/vnode.h>
1956535Sbostic #include <sys/kernel.h>
2056535Sbostic #include <sys/malloc.h>
2147573Skarels 
2256535Sbostic #include <nfs/rpcv2.h>
2356535Sbostic #include <nfs/nfsv2.h>
2456535Sbostic #include <nfs/nfs.h>
2556535Sbostic #include <nfs/nfsnode.h>
2656535Sbostic #include <nfs/nfsmount.h>
2756535Sbostic #include <nfs/nqnfs.h>
2838415Smckusick 
2955520Smckusick struct nfsnode **nheadhashtbl;
3055520Smckusick u_long nheadhash;
3155520Smckusick #define	NFSNOHASH(fhsum)	((fhsum)&nheadhash)
3238415Smckusick 
3338884Smacklem #define TRUE	1
3438884Smacklem #define	FALSE	0
3538884Smacklem 
3638415Smckusick /*
3738415Smckusick  * Initialize hash links for nfsnodes
3838415Smckusick  * and build nfsnode free list.
3938415Smckusick  */
4038415Smckusick nfs_nhinit()
4138415Smckusick {
4238415Smckusick 
4339494Smckusick #ifndef lint
4451985Smckusick 	if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode))
4551985Smckusick 		printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode));
4639494Smckusick #endif /* not lint */
4755520Smckusick 	nheadhashtbl = hashinit(desiredvnodes, M_NFSNODE, &nheadhash);
4838415Smckusick }
4938415Smckusick 
5038415Smckusick /*
5139445Smckusick  * Compute an entry in the NFS hash table structure
5239445Smckusick  */
5355520Smckusick struct nfsnode **
5439445Smckusick nfs_hash(fhp)
5539445Smckusick 	register nfsv2fh_t *fhp;
5639445Smckusick {
5739445Smckusick 	register u_char *fhpp;
5839445Smckusick 	register u_long fhsum;
5939445Smckusick 	int i;
6039445Smckusick 
6139445Smckusick 	fhpp = &fhp->fh_bytes[0];
6239445Smckusick 	fhsum = 0;
6339445Smckusick 	for (i = 0; i < NFSX_FH; i++)
6439445Smckusick 		fhsum += *fhpp++;
6555520Smckusick 	return (&nheadhashtbl[NFSNOHASH(fhsum)]);
6639445Smckusick }
6739445Smckusick 
6839445Smckusick /*
6939395Smckusick  * Look up a vnode/nfsnode by file handle.
7038415Smckusick  * Callers must check for mount points!!
7138415Smckusick  * In all cases, a pointer to a
7238415Smckusick  * nfsnode structure is returned.
7338415Smckusick  */
7438415Smckusick nfs_nget(mntp, fhp, npp)
7538415Smckusick 	struct mount *mntp;
7638415Smckusick 	register nfsv2fh_t *fhp;
7738415Smckusick 	struct nfsnode **npp;
7838415Smckusick {
7955520Smckusick 	register struct nfsnode *np, *nq, **nhpp;
8038415Smckusick 	register struct vnode *vp;
8153550Sheideman 	extern int (**nfsv2_vnodeop_p)();
8239395Smckusick 	struct vnode *nvp;
8339445Smckusick 	int error;
8438415Smckusick 
8555520Smckusick 	nhpp = nfs_hash(fhp);
8638415Smckusick loop:
8755520Smckusick 	for (np = *nhpp; np; np = np->n_forw) {
8839395Smckusick 		if (mntp != NFSTOV(np)->v_mount ||
8939395Smckusick 		    bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
9039395Smckusick 			continue;
9139395Smckusick 		vp = NFSTOV(np);
9239445Smckusick 		if (vget(vp))
9339445Smckusick 			goto loop;
9439395Smckusick 		*npp = np;
9539395Smckusick 		return(0);
9638884Smacklem 	}
9753550Sheideman 	if (error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp)) {
9838415Smckusick 		*npp = 0;
9939395Smckusick 		return (error);
10038415Smckusick 	}
10139395Smckusick 	vp = nvp;
10251985Smckusick 	MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
10351985Smckusick 	vp->v_data = np;
10439395Smckusick 	np->n_vnode = vp;
10538415Smckusick 	/*
10638884Smacklem 	 * Insert the nfsnode in the hash queue for its new file handle
10738884Smacklem 	 */
10839908Smckusick 	np->n_flag = 0;
10955520Smckusick 	if (nq = *nhpp)
11055520Smckusick 		nq->n_back = &np->n_forw;
11155520Smckusick 	np->n_forw = nq;
11255520Smckusick 	np->n_back = nhpp;
11355520Smckusick 	*nhpp = np;
11438415Smckusick 	bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
11538415Smckusick 	np->n_attrstamp = 0;
11641898Smckusick 	np->n_direofoffset = 0;
11738415Smckusick 	np->n_sillyrename = (struct sillyrename *)0;
11838884Smacklem 	np->n_size = 0;
11956283Smckusick 	np->n_mtime = 0;
12052196Smckusick 	if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
12154447Smckusick 		np->n_brev = 0;
12254447Smckusick 		np->n_lrev = 0;
12352196Smckusick 		np->n_expiry = (time_t)0;
12452196Smckusick 		np->n_tnext = (struct nfsnode *)0;
12556283Smckusick 	}
12638415Smckusick 	*npp = np;
12738415Smckusick 	return (0);
12838415Smckusick }
12938415Smckusick 
13054666Smckusick nfs_inactive(ap)
13154666Smckusick 	struct vop_inactive_args /* {
13254666Smckusick 		struct vnode *a_vp;
13354666Smckusick 	} */ *ap;
13438415Smckusick {
13538415Smckusick 	register struct nfsnode *np;
13638415Smckusick 	register struct sillyrename *sp;
137*57784Smckusick 	struct proc *p = curproc;	/* XXX */
13839575Smckusick 	extern int prtactive;
13938415Smckusick 
14053599Sheideman 	np = VTONFS(ap->a_vp);
14153599Sheideman 	if (prtactive && ap->a_vp->v_usecount != 0)
14253599Sheideman 		vprint("nfs_inactive: pushing active", ap->a_vp);
14339395Smckusick 	sp = np->n_sillyrename;
14439395Smckusick 	np->n_sillyrename = (struct sillyrename *)0;
14539395Smckusick 	if (sp) {
14638415Smckusick 		/*
14739395Smckusick 		 * Remove the silly file that was rename'd earlier
14838415Smckusick 		 */
149*57784Smckusick 		(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);
15351985Smckusick #ifdef SILLYSEPARATE
15448364Smckusick 		free((caddr_t)sp, M_NFSREQ);
15551985Smckusick #endif
15639395Smckusick 	}
157*57784Smckusick 	np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT);
15839395Smckusick 	return (0);
15939395Smckusick }
16039395Smckusick 
16139395Smckusick /*
16239395Smckusick  * Reclaim an nfsnode so that it can be used for other purposes.
16339395Smckusick  */
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);
17255520Smckusick 	register struct nfsnode *nq;
17339575Smckusick 	extern int prtactive;
17439395Smckusick 
17554666Smckusick 	if (prtactive && vp->v_usecount != 0)
17654666Smckusick 		vprint("nfs_reclaim: pushing active", vp);
17739395Smckusick 	/*
17839395Smckusick 	 * Remove the nfsnode from its hash chain.
17939395Smckusick 	 */
18055520Smckusick 	if (nq = np->n_forw)
18155520Smckusick 		nq->n_back = np->n_back;
18255520Smckusick 	*np->n_back = nq;
18352196Smckusick 
18452196Smckusick 	/*
18552196Smckusick 	 * For nqnfs, take it off the timer queue as required.
18652196Smckusick 	 */
18752196Smckusick 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) {
18852196Smckusick 		if (np->n_tnext == (struct nfsnode *)nmp)
18952196Smckusick 			nmp->nm_tprev = np->n_tprev;
19052196Smckusick 		else
19152196Smckusick 			np->n_tnext->n_tprev = np->n_tprev;
19252196Smckusick 		if (np->n_tprev == (struct nfsnode *)nmp)
19352196Smckusick 			nmp->nm_tnext = np->n_tnext;
19452196Smckusick 		else
19552196Smckusick 			np->n_tprev->n_tnext = np->n_tnext;
19652196Smckusick 	}
19754666Smckusick 	cache_purge(vp);
19854666Smckusick 	FREE(vp->v_data, M_NFSNODE);
19954666Smckusick 	vp->v_data = (void *)0;
20038415Smckusick 	return (0);
20138415Smckusick }
20238415Smckusick 
20338415Smckusick /*
20438415Smckusick  * Lock an nfsnode
20538415Smckusick  */
20654666Smckusick nfs_lock(ap)
20754666Smckusick 	struct vop_lock_args /* {
20854666Smckusick 		struct vnode *a_vp;
20954666Smckusick 	} */ *ap;
21038415Smckusick {
21156806Smckusick 	register struct vnode *vp = ap->a_vp;
21238415Smckusick 
213*57784Smckusick 	/*
214*57784Smckusick 	 * Ugh, another place where interruptible mounts will get hung.
215*57784Smckusick 	 * If you make this sleep interruptible, then you have to fix all
216*57784Smckusick 	 * the VOP_LOCK() calls to expect interruptibility.
217*57784Smckusick 	 */
21856806Smckusick 	while (vp->v_flag & VXLOCK) {
21956806Smckusick 		vp->v_flag |= VXWANT;
22056806Smckusick 		sleep((caddr_t)vp, PINOD);
22156806Smckusick 	}
22256806Smckusick 	if (vp->v_tag == VT_NON)
22356806Smckusick 		return (ENOENT);
22452196Smckusick 	return (0);
22538415Smckusick }
22638415Smckusick 
22738415Smckusick /*
22838415Smckusick  * Unlock an nfsnode
22938415Smckusick  */
23054666Smckusick nfs_unlock(ap)
23154666Smckusick 	struct vop_unlock_args /* {
23254666Smckusick 		struct vnode *a_vp;
23354666Smckusick 	} */ *ap;
23438415Smckusick {
23538415Smckusick 
23652196Smckusick 	return (0);
23738415Smckusick }
23838415Smckusick 
23938415Smckusick /*
24039908Smckusick  * Check for a locked nfsnode
24139908Smckusick  */
24254666Smckusick nfs_islocked(ap)
24354666Smckusick 	struct vop_islocked_args /* {
24454666Smckusick 		struct vnode *a_vp;
24554666Smckusick 	} */ *ap;
24639908Smckusick {
24739908Smckusick 
24839908Smckusick 	return (0);
24939908Smckusick }
25039908Smckusick 
25139908Smckusick /*
25242467Smckusick  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
25342467Smckusick  * done. Currently nothing to do.
25442467Smckusick  */
25542467Smckusick /* ARGSUSED */
25652234Sheideman int
25754666Smckusick nfs_abortop(ap)
25854666Smckusick 	struct vop_abortop_args /* {
25954666Smckusick 		struct vnode *a_dvp;
26054666Smckusick 		struct componentname *a_cnp;
26154666Smckusick 	} */ *ap;
26238415Smckusick {
26338415Smckusick 
26453599Sheideman 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
26553599Sheideman 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
26642467Smckusick 	return (0);
26738415Smckusick }
268