xref: /csrg-svn/sys/nfs/nfs_node.c (revision 56535)
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*56535Sbostic  *	@(#)nfs_node.c	7.44 (Berkeley) 10/11/92
1138415Smckusick  */
1238415Smckusick 
13*56535Sbostic #include <sys/param.h>
14*56535Sbostic #include <sys/systm.h>
15*56535Sbostic #include <sys/proc.h>
16*56535Sbostic #include <sys/mount.h>
17*56535Sbostic #include <sys/namei.h>
18*56535Sbostic #include <sys/vnode.h>
19*56535Sbostic #include <sys/kernel.h>
20*56535Sbostic #include <sys/malloc.h>
2147573Skarels 
22*56535Sbostic #include <nfs/rpcv2.h>
23*56535Sbostic #include <nfs/nfsv2.h>
24*56535Sbostic #include <nfs/nfs.h>
25*56535Sbostic #include <nfs/nfsnode.h>
26*56535Sbostic #include <nfs/nfsmount.h>
27*56535Sbostic #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;
13739575Smckusick 	extern int prtactive;
13838415Smckusick 
13953599Sheideman 	np = VTONFS(ap->a_vp);
14053599Sheideman 	if (prtactive && ap->a_vp->v_usecount != 0)
14153599Sheideman 		vprint("nfs_inactive: pushing active", ap->a_vp);
14239395Smckusick 	sp = np->n_sillyrename;
14339395Smckusick 	np->n_sillyrename = (struct sillyrename *)0;
14439395Smckusick 	if (sp) {
14538415Smckusick 		/*
14639395Smckusick 		 * Remove the silly file that was rename'd earlier
14738415Smckusick 		 */
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 	}
15541898Smckusick 	np->n_flag &= NMODIFIED;
15639395Smckusick 	return (0);
15739395Smckusick }
15839395Smckusick 
15939395Smckusick /*
16039395Smckusick  * Reclaim an nfsnode so that it can be used for other purposes.
16139395Smckusick  */
16254666Smckusick nfs_reclaim(ap)
16354666Smckusick 	struct vop_reclaim_args /* {
16454666Smckusick 		struct vnode *a_vp;
16554666Smckusick 	} */ *ap;
16639395Smckusick {
16754666Smckusick 	register struct vnode *vp = ap->a_vp;
16854666Smckusick 	register struct nfsnode *np = VTONFS(vp);
16954666Smckusick 	register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
17055520Smckusick 	register struct nfsnode *nq;
17139575Smckusick 	extern int prtactive;
17239395Smckusick 
17354666Smckusick 	if (prtactive && vp->v_usecount != 0)
17454666Smckusick 		vprint("nfs_reclaim: pushing active", vp);
17539395Smckusick 	/*
17639395Smckusick 	 * Remove the nfsnode from its hash chain.
17739395Smckusick 	 */
17855520Smckusick 	if (nq = np->n_forw)
17955520Smckusick 		nq->n_back = np->n_back;
18055520Smckusick 	*np->n_back = nq;
18152196Smckusick 
18252196Smckusick 	/*
18352196Smckusick 	 * For nqnfs, take it off the timer queue as required.
18452196Smckusick 	 */
18552196Smckusick 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) {
18652196Smckusick 		if (np->n_tnext == (struct nfsnode *)nmp)
18752196Smckusick 			nmp->nm_tprev = np->n_tprev;
18852196Smckusick 		else
18952196Smckusick 			np->n_tnext->n_tprev = np->n_tprev;
19052196Smckusick 		if (np->n_tprev == (struct nfsnode *)nmp)
19152196Smckusick 			nmp->nm_tnext = np->n_tnext;
19252196Smckusick 		else
19352196Smckusick 			np->n_tprev->n_tnext = np->n_tnext;
19452196Smckusick 	}
19554666Smckusick 	cache_purge(vp);
19654666Smckusick 	FREE(vp->v_data, M_NFSNODE);
19754666Smckusick 	vp->v_data = (void *)0;
19838415Smckusick 	return (0);
19938415Smckusick }
20038415Smckusick 
20138415Smckusick /*
20238415Smckusick  * Lock an nfsnode
20338415Smckusick  */
20454666Smckusick nfs_lock(ap)
20554666Smckusick 	struct vop_lock_args /* {
20654666Smckusick 		struct vnode *a_vp;
20754666Smckusick 	} */ *ap;
20838415Smckusick {
20938415Smckusick 
21052196Smckusick 	return (0);
21138415Smckusick }
21238415Smckusick 
21338415Smckusick /*
21438415Smckusick  * Unlock an nfsnode
21538415Smckusick  */
21654666Smckusick nfs_unlock(ap)
21754666Smckusick 	struct vop_unlock_args /* {
21854666Smckusick 		struct vnode *a_vp;
21954666Smckusick 	} */ *ap;
22038415Smckusick {
22138415Smckusick 
22252196Smckusick 	return (0);
22338415Smckusick }
22438415Smckusick 
22538415Smckusick /*
22639908Smckusick  * Check for a locked nfsnode
22739908Smckusick  */
22854666Smckusick nfs_islocked(ap)
22954666Smckusick 	struct vop_islocked_args /* {
23054666Smckusick 		struct vnode *a_vp;
23154666Smckusick 	} */ *ap;
23239908Smckusick {
23339908Smckusick 
23439908Smckusick 	return (0);
23539908Smckusick }
23639908Smckusick 
23739908Smckusick /*
23842467Smckusick  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
23942467Smckusick  * done. Currently nothing to do.
24042467Smckusick  */
24142467Smckusick /* ARGSUSED */
24252234Sheideman int
24354666Smckusick nfs_abortop(ap)
24454666Smckusick 	struct vop_abortop_args /* {
24554666Smckusick 		struct vnode *a_dvp;
24654666Smckusick 		struct componentname *a_cnp;
24754666Smckusick 	} */ *ap;
24838415Smckusick {
24938415Smckusick 
25053599Sheideman 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
25153599Sheideman 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
25242467Smckusick 	return (0);
25338415Smckusick }
254