xref: /csrg-svn/sys/nfs/nfs_node.c (revision 65249)
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*65249Smckusick  *	@(#)nfs_node.c	8.2 (Berkeley) 12/30/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);
92*65249Smckusick 		if (vget(vp, 1))
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;
13757784Smckusick 	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 		 */
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);
15351985Smckusick #ifdef SILLYSEPARATE
15448364Smckusick 		free((caddr_t)sp, M_NFSREQ);
15551985Smckusick #endif
15639395Smckusick 	}
15759705Smckusick 	np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
15859705Smckusick 		NQNFSNONCACHE | NQNFSWRITE);
15939395Smckusick 	return (0);
16039395Smckusick }
16139395Smckusick 
16239395Smckusick /*
16339395Smckusick  * Reclaim an nfsnode so that it can be used for other purposes.
16439395Smckusick  */
16554666Smckusick nfs_reclaim(ap)
16654666Smckusick 	struct vop_reclaim_args /* {
16754666Smckusick 		struct vnode *a_vp;
16854666Smckusick 	} */ *ap;
16939395Smckusick {
17054666Smckusick 	register struct vnode *vp = ap->a_vp;
17154666Smckusick 	register struct nfsnode *np = VTONFS(vp);
17254666Smckusick 	register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
17355520Smckusick 	register struct nfsnode *nq;
17439575Smckusick 	extern int prtactive;
17539395Smckusick 
17654666Smckusick 	if (prtactive && vp->v_usecount != 0)
17754666Smckusick 		vprint("nfs_reclaim: pushing active", vp);
17839395Smckusick 	/*
17939395Smckusick 	 * Remove the nfsnode from its hash chain.
18039395Smckusick 	 */
18155520Smckusick 	if (nq = np->n_forw)
18255520Smckusick 		nq->n_back = np->n_back;
18355520Smckusick 	*np->n_back = nq;
18452196Smckusick 
18552196Smckusick 	/*
18652196Smckusick 	 * For nqnfs, take it off the timer queue as required.
18752196Smckusick 	 */
18852196Smckusick 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) {
18952196Smckusick 		if (np->n_tnext == (struct nfsnode *)nmp)
19052196Smckusick 			nmp->nm_tprev = np->n_tprev;
19152196Smckusick 		else
19252196Smckusick 			np->n_tnext->n_tprev = np->n_tprev;
19352196Smckusick 		if (np->n_tprev == (struct nfsnode *)nmp)
19452196Smckusick 			nmp->nm_tnext = np->n_tnext;
19552196Smckusick 		else
19652196Smckusick 			np->n_tprev->n_tnext = np->n_tnext;
19752196Smckusick 	}
19854666Smckusick 	cache_purge(vp);
19954666Smckusick 	FREE(vp->v_data, M_NFSNODE);
20054666Smckusick 	vp->v_data = (void *)0;
20138415Smckusick 	return (0);
20238415Smckusick }
20338415Smckusick 
20438415Smckusick /*
20538415Smckusick  * Lock an nfsnode
20638415Smckusick  */
20754666Smckusick nfs_lock(ap)
20854666Smckusick 	struct vop_lock_args /* {
20954666Smckusick 		struct vnode *a_vp;
21054666Smckusick 	} */ *ap;
21138415Smckusick {
21256806Smckusick 	register struct vnode *vp = ap->a_vp;
21338415Smckusick 
21457784Smckusick 	/*
21557784Smckusick 	 * Ugh, another place where interruptible mounts will get hung.
21657784Smckusick 	 * If you make this sleep interruptible, then you have to fix all
21757784Smckusick 	 * the VOP_LOCK() calls to expect interruptibility.
21857784Smckusick 	 */
21956806Smckusick 	while (vp->v_flag & VXLOCK) {
22056806Smckusick 		vp->v_flag |= VXWANT;
22156806Smckusick 		sleep((caddr_t)vp, PINOD);
22256806Smckusick 	}
22356806Smckusick 	if (vp->v_tag == VT_NON)
22456806Smckusick 		return (ENOENT);
22552196Smckusick 	return (0);
22638415Smckusick }
22738415Smckusick 
22838415Smckusick /*
22938415Smckusick  * Unlock an nfsnode
23038415Smckusick  */
23154666Smckusick nfs_unlock(ap)
23254666Smckusick 	struct vop_unlock_args /* {
23354666Smckusick 		struct vnode *a_vp;
23454666Smckusick 	} */ *ap;
23538415Smckusick {
23638415Smckusick 
23752196Smckusick 	return (0);
23838415Smckusick }
23938415Smckusick 
24038415Smckusick /*
24139908Smckusick  * Check for a locked nfsnode
24239908Smckusick  */
24354666Smckusick nfs_islocked(ap)
24454666Smckusick 	struct vop_islocked_args /* {
24554666Smckusick 		struct vnode *a_vp;
24654666Smckusick 	} */ *ap;
24739908Smckusick {
24839908Smckusick 
24939908Smckusick 	return (0);
25039908Smckusick }
25139908Smckusick 
25239908Smckusick /*
25342467Smckusick  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
25442467Smckusick  * done. Currently nothing to do.
25542467Smckusick  */
25642467Smckusick /* ARGSUSED */
25752234Sheideman int
25854666Smckusick nfs_abortop(ap)
25954666Smckusick 	struct vop_abortop_args /* {
26054666Smckusick 		struct vnode *a_dvp;
26154666Smckusick 		struct componentname *a_cnp;
26254666Smckusick 	} */ *ap;
26338415Smckusick {
26438415Smckusick 
26553599Sheideman 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
26653599Sheideman 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
26742467Smckusick 	return (0);
26838415Smckusick }
269