xref: /csrg-svn/sys/nfs/nfs_node.c (revision 67708)
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*67708Smckusick  *	@(#)nfs_node.c	8.3 (Berkeley) 08/18/94
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 
29*67708Smckusick #define	NFSNOHASH(fhsum) \
30*67708Smckusick 	(&nfsnodehashtbl[(fhsum) & nfsnodehash])
31*67708Smckusick LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
32*67708Smckusick u_long nfsnodehash;
3338415Smckusick 
3438884Smacklem #define TRUE	1
3538884Smacklem #define	FALSE	0
3638884Smacklem 
3738415Smckusick /*
3838415Smckusick  * Initialize hash links for nfsnodes
3938415Smckusick  * and build nfsnode free list.
4038415Smckusick  */
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 */
48*67708Smckusick 	nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, &nfsnodehash);
4938415Smckusick }
5038415Smckusick 
5138415Smckusick /*
5239445Smckusick  * Compute an entry in the NFS hash table structure
5339445Smckusick  */
54*67708Smckusick struct nfsnodehashhead *
5539445Smckusick nfs_hash(fhp)
5639445Smckusick 	register nfsv2fh_t *fhp;
5739445Smckusick {
5839445Smckusick 	register u_char *fhpp;
5939445Smckusick 	register u_long fhsum;
6039445Smckusick 	int i;
6139445Smckusick 
6239445Smckusick 	fhpp = &fhp->fh_bytes[0];
6339445Smckusick 	fhsum = 0;
6439445Smckusick 	for (i = 0; i < NFSX_FH; i++)
6539445Smckusick 		fhsum += *fhpp++;
66*67708Smckusick 	return (NFSNOHASH(fhsum));
6739445Smckusick }
6839445Smckusick 
6939445Smckusick /*
7039395Smckusick  * Look up a vnode/nfsnode by file handle.
7138415Smckusick  * Callers must check for mount points!!
7238415Smckusick  * In all cases, a pointer to a
7338415Smckusick  * nfsnode structure is returned.
7438415Smckusick  */
7538415Smckusick nfs_nget(mntp, fhp, npp)
7638415Smckusick 	struct mount *mntp;
7738415Smckusick 	register nfsv2fh_t *fhp;
7838415Smckusick 	struct nfsnode **npp;
7938415Smckusick {
80*67708Smckusick 	register struct nfsnode *np;
81*67708Smckusick 	struct nfsnodehashhead *nhpp;
8238415Smckusick 	register struct vnode *vp;
8353550Sheideman 	extern int (**nfsv2_vnodeop_p)();
8439395Smckusick 	struct vnode *nvp;
8539445Smckusick 	int error;
8638415Smckusick 
8755520Smckusick 	nhpp = nfs_hash(fhp);
8838415Smckusick loop:
89*67708Smckusick 	for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
9039395Smckusick 		if (mntp != NFSTOV(np)->v_mount ||
9139395Smckusick 		    bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
9239395Smckusick 			continue;
9339395Smckusick 		vp = NFSTOV(np);
9465249Smckusick 		if (vget(vp, 1))
9539445Smckusick 			goto loop;
9639395Smckusick 		*npp = np;
9739395Smckusick 		return(0);
9838884Smacklem 	}
9953550Sheideman 	if (error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp)) {
10038415Smckusick 		*npp = 0;
10139395Smckusick 		return (error);
10238415Smckusick 	}
10339395Smckusick 	vp = nvp;
10451985Smckusick 	MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
10551985Smckusick 	vp->v_data = np;
10639395Smckusick 	np->n_vnode = vp;
10738415Smckusick 	/*
10838884Smacklem 	 * Insert the nfsnode in the hash queue for its new file handle
10938884Smacklem 	 */
11039908Smckusick 	np->n_flag = 0;
111*67708Smckusick 	LIST_INSERT_HEAD(nhpp, np, n_hash);
11238415Smckusick 	bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
11338415Smckusick 	np->n_attrstamp = 0;
11441898Smckusick 	np->n_direofoffset = 0;
11538415Smckusick 	np->n_sillyrename = (struct sillyrename *)0;
11638884Smacklem 	np->n_size = 0;
11756283Smckusick 	np->n_mtime = 0;
11852196Smckusick 	if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
11954447Smckusick 		np->n_brev = 0;
12054447Smckusick 		np->n_lrev = 0;
12152196Smckusick 		np->n_expiry = (time_t)0;
122*67708Smckusick 		np->n_timer.cqe_next = (struct nfsnode *)0;
12356283Smckusick 	}
12438415Smckusick 	*npp = np;
12538415Smckusick 	return (0);
12638415Smckusick }
12738415Smckusick 
12854666Smckusick nfs_inactive(ap)
12954666Smckusick 	struct vop_inactive_args /* {
13054666Smckusick 		struct vnode *a_vp;
13154666Smckusick 	} */ *ap;
13238415Smckusick {
13338415Smckusick 	register struct nfsnode *np;
13438415Smckusick 	register struct sillyrename *sp;
13557784Smckusick 	struct proc *p = curproc;	/* XXX */
13639575Smckusick 	extern int prtactive;
13738415Smckusick 
13853599Sheideman 	np = VTONFS(ap->a_vp);
13953599Sheideman 	if (prtactive && ap->a_vp->v_usecount != 0)
14053599Sheideman 		vprint("nfs_inactive: pushing active", ap->a_vp);
14139395Smckusick 	sp = np->n_sillyrename;
14239395Smckusick 	np->n_sillyrename = (struct sillyrename *)0;
14339395Smckusick 	if (sp) {
14438415Smckusick 		/*
14539395Smckusick 		 * Remove the silly file that was rename'd earlier
14638415Smckusick 		 */
14757784Smckusick 		(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
14854447Smckusick 		nfs_removeit(sp);
14948364Smckusick 		crfree(sp->s_cred);
15048364Smckusick 		vrele(sp->s_dvp);
15151985Smckusick #ifdef SILLYSEPARATE
15248364Smckusick 		free((caddr_t)sp, M_NFSREQ);
15351985Smckusick #endif
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  */
16354666Smckusick nfs_reclaim(ap)
16454666Smckusick 	struct vop_reclaim_args /* {
16554666Smckusick 		struct vnode *a_vp;
16654666Smckusick 	} */ *ap;
16739395Smckusick {
16854666Smckusick 	register struct vnode *vp = ap->a_vp;
16954666Smckusick 	register struct nfsnode *np = VTONFS(vp);
17054666Smckusick 	register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
17139575Smckusick 	extern int prtactive;
17239395Smckusick 
17354666Smckusick 	if (prtactive && vp->v_usecount != 0)
17454666Smckusick 		vprint("nfs_reclaim: pushing active", vp);
175*67708Smckusick 	LIST_REMOVE(np, n_hash);
17652196Smckusick 
17752196Smckusick 	/*
17852196Smckusick 	 * For nqnfs, take it off the timer queue as required.
17952196Smckusick 	 */
180*67708Smckusick 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0)
181*67708Smckusick 		CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
18254666Smckusick 	cache_purge(vp);
18354666Smckusick 	FREE(vp->v_data, M_NFSNODE);
18454666Smckusick 	vp->v_data = (void *)0;
18538415Smckusick 	return (0);
18638415Smckusick }
18738415Smckusick 
18838415Smckusick /*
18938415Smckusick  * Lock an nfsnode
19038415Smckusick  */
19154666Smckusick nfs_lock(ap)
19254666Smckusick 	struct vop_lock_args /* {
19354666Smckusick 		struct vnode *a_vp;
19454666Smckusick 	} */ *ap;
19538415Smckusick {
19656806Smckusick 	register struct vnode *vp = ap->a_vp;
19738415Smckusick 
19857784Smckusick 	/*
19957784Smckusick 	 * Ugh, another place where interruptible mounts will get hung.
20057784Smckusick 	 * If you make this sleep interruptible, then you have to fix all
20157784Smckusick 	 * the VOP_LOCK() calls to expect interruptibility.
20257784Smckusick 	 */
20356806Smckusick 	while (vp->v_flag & VXLOCK) {
20456806Smckusick 		vp->v_flag |= VXWANT;
20556806Smckusick 		sleep((caddr_t)vp, PINOD);
20656806Smckusick 	}
20756806Smckusick 	if (vp->v_tag == VT_NON)
20856806Smckusick 		return (ENOENT);
20952196Smckusick 	return (0);
21038415Smckusick }
21138415Smckusick 
21238415Smckusick /*
21338415Smckusick  * Unlock an nfsnode
21438415Smckusick  */
21554666Smckusick nfs_unlock(ap)
21654666Smckusick 	struct vop_unlock_args /* {
21754666Smckusick 		struct vnode *a_vp;
21854666Smckusick 	} */ *ap;
21938415Smckusick {
22038415Smckusick 
22152196Smckusick 	return (0);
22238415Smckusick }
22338415Smckusick 
22438415Smckusick /*
22539908Smckusick  * Check for a locked nfsnode
22639908Smckusick  */
22754666Smckusick nfs_islocked(ap)
22854666Smckusick 	struct vop_islocked_args /* {
22954666Smckusick 		struct vnode *a_vp;
23054666Smckusick 	} */ *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
24254666Smckusick nfs_abortop(ap)
24354666Smckusick 	struct vop_abortop_args /* {
24454666Smckusick 		struct vnode *a_dvp;
24554666Smckusick 		struct componentname *a_cnp;
24654666Smckusick 	} */ *ap;
24738415Smckusick {
24838415Smckusick 
24953599Sheideman 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
25053599Sheideman 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
25142467Smckusick 	return (0);
25238415Smckusick }
253