xref: /csrg-svn/sys/nfs/nfs_node.c (revision 42467)
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  *
838415Smckusick  * Redistribution and use in source and binary forms are permitted
938415Smckusick  * provided that the above copyright notice and this paragraph are
1038415Smckusick  * duplicated in all such forms and that any documentation,
1138415Smckusick  * advertising materials, and other materials related to such
1238415Smckusick  * distribution and use acknowledge that the software was developed
1338415Smckusick  * by the University of California, Berkeley.  The name of the
1438415Smckusick  * University may not be used to endorse or promote products derived
1538415Smckusick  * from this software without specific prior written permission.
1638415Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1738415Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1838415Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1938415Smckusick  *
20*42467Smckusick  *	@(#)nfs_node.c	7.27 (Berkeley) 05/30/90
2138415Smckusick  */
2238415Smckusick 
2338415Smckusick #include "param.h"
2438415Smckusick #include "systm.h"
2538415Smckusick #include "user.h"
2638415Smckusick #include "proc.h"
2738415Smckusick #include "mount.h"
2838415Smckusick #include "vnode.h"
2938415Smckusick #include "errno.h"
3038415Smckusick #include "nfsv2.h"
3138415Smckusick #include "nfs.h"
3238415Smckusick #include "nfsnode.h"
3338415Smckusick #include "nfsmount.h"
3438415Smckusick #include "kernel.h"
3538415Smckusick #include "malloc.h"
3638415Smckusick 
3738415Smckusick /* The request list head */
3838415Smckusick extern struct nfsreq nfsreqh;
3938415Smckusick 
4038415Smckusick #define	NFSNOHSZ	512
4138415Smckusick #if	((NFSNOHSZ&(NFSNOHSZ-1)) == 0)
4238415Smckusick #define	NFSNOHASH(fhsum)	((fhsum)&(NFSNOHSZ-1))
4338415Smckusick #else
4438415Smckusick #define	NFSNOHASH(fhsum)	(((unsigned)(fhsum))%NFSNOHSZ)
4538415Smckusick #endif
4638415Smckusick 
4739395Smckusick union nhead {
4838415Smckusick 	union  nhead *nh_head[2];
4938415Smckusick 	struct nfsnode *nh_chain[2];
5038415Smckusick } nhead[NFSNOHSZ];
5138415Smckusick 
5238884Smacklem #define TRUE	1
5338884Smacklem #define	FALSE	0
5438884Smacklem 
5538415Smckusick /*
5638415Smckusick  * Initialize hash links for nfsnodes
5738415Smckusick  * and build nfsnode free list.
5838415Smckusick  */
5938415Smckusick nfs_nhinit()
6038415Smckusick {
6138415Smckusick 	register int i;
6238415Smckusick 	register union  nhead *nh = nhead;
6338415Smckusick 
6439494Smckusick #ifndef lint
6539395Smckusick 	if (VN_MAXPRIVATE < sizeof(struct nfsnode))
6639395Smckusick 		panic("nfs_nhinit: too small");
6739494Smckusick #endif /* not lint */
6838415Smckusick 	for (i = NFSNOHSZ; --i >= 0; nh++) {
6938415Smckusick 		nh->nh_head[0] = nh;
7038415Smckusick 		nh->nh_head[1] = nh;
7138415Smckusick 	}
7238415Smckusick }
7338415Smckusick 
7438415Smckusick /*
7539445Smckusick  * Compute an entry in the NFS hash table structure
7639445Smckusick  */
7739445Smckusick union nhead *
7839445Smckusick nfs_hash(fhp)
7939445Smckusick 	register nfsv2fh_t *fhp;
8039445Smckusick {
8139445Smckusick 	register u_char *fhpp;
8239445Smckusick 	register u_long fhsum;
8339445Smckusick 	int i;
8439445Smckusick 
8539445Smckusick 	fhpp = &fhp->fh_bytes[0];
8639445Smckusick 	fhsum = 0;
8739445Smckusick 	for (i = 0; i < NFSX_FH; i++)
8839445Smckusick 		fhsum += *fhpp++;
8939445Smckusick 	return (&nhead[NFSNOHASH(fhsum)]);
9039445Smckusick }
9139445Smckusick 
9239445Smckusick /*
9339395Smckusick  * Look up a vnode/nfsnode by file handle.
9438415Smckusick  * Callers must check for mount points!!
9538415Smckusick  * In all cases, a pointer to a
9638415Smckusick  * nfsnode structure is returned.
9738415Smckusick  */
9838415Smckusick nfs_nget(mntp, fhp, npp)
9938415Smckusick 	struct mount *mntp;
10038415Smckusick 	register nfsv2fh_t *fhp;
10138415Smckusick 	struct nfsnode **npp;
10238415Smckusick {
10338415Smckusick 	register struct nfsnode *np;
10438415Smckusick 	register struct vnode *vp;
10539445Smckusick 	extern struct vnodeops nfsv2_vnodeops;
10639395Smckusick 	struct vnode *nvp;
10739395Smckusick 	union nhead *nh;
10839445Smckusick 	int error;
10938415Smckusick 
11039445Smckusick 	nh = nfs_hash(fhp);
11138415Smckusick loop:
11238884Smacklem 	for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) {
11339395Smckusick 		if (mntp != NFSTOV(np)->v_mount ||
11439395Smckusick 		    bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
11539395Smckusick 			continue;
11639395Smckusick 		if ((np->n_flag & NLOCKED) != 0) {
11739395Smckusick 			np->n_flag |= NWANT;
11839395Smckusick 			sleep((caddr_t)np, PINOD);
11939395Smckusick 			goto loop;
12039395Smckusick 		}
12139395Smckusick 		vp = NFSTOV(np);
12239445Smckusick 		if (vget(vp))
12339445Smckusick 			goto loop;
12439395Smckusick 		*npp = np;
12539395Smckusick 		return(0);
12638884Smacklem 	}
12739395Smckusick 	if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) {
12838415Smckusick 		*npp = 0;
12939395Smckusick 		return (error);
13038415Smckusick 	}
13139395Smckusick 	vp = nvp;
13239395Smckusick 	np = VTONFS(vp);
13339395Smckusick 	np->n_vnode = vp;
13438415Smckusick 	/*
13538884Smacklem 	 * Insert the nfsnode in the hash queue for its new file handle
13638884Smacklem 	 */
13739908Smckusick 	np->n_flag = 0;
13838415Smckusick 	insque(np, nh);
13939908Smckusick 	nfs_lock(vp);
14038415Smckusick 	bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
14138415Smckusick 	np->n_attrstamp = 0;
14241898Smckusick 	np->n_direofoffset = 0;
14338415Smckusick 	np->n_sillyrename = (struct sillyrename *)0;
14438884Smacklem 	np->n_size = 0;
14538884Smacklem 	np->n_mtime = 0;
14638415Smckusick 	*npp = np;
14738415Smckusick 	return (0);
14838415Smckusick }
14938415Smckusick 
15038415Smckusick nfs_inactive(vp)
15138415Smckusick 	struct vnode *vp;
15238415Smckusick {
15338415Smckusick 	register struct nfsnode *np;
15438415Smckusick 	register struct nameidata *ndp;
15538415Smckusick 	register struct sillyrename *sp;
15638415Smckusick 	struct nfsnode *dnp;
15739575Smckusick 	extern int prtactive;
15838415Smckusick 
15939395Smckusick 	np = VTONFS(vp);
16039810Smckusick 	if (prtactive && vp->v_usecount != 0)
16139671Smckusick 		vprint("nfs_inactive: pushing active", vp);
16239395Smckusick 	nfs_lock(vp);
16339395Smckusick 	sp = np->n_sillyrename;
16439395Smckusick 	np->n_sillyrename = (struct sillyrename *)0;
16539395Smckusick 	if (sp) {
16638415Smckusick 		/*
16739395Smckusick 		 * Remove the silly file that was rename'd earlier
16838415Smckusick 		 */
16939395Smckusick 		ndp = &sp->s_namei;
17039395Smckusick 		if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) {
17139395Smckusick 			ndp->ni_dvp = NFSTOV(dnp);
17239395Smckusick 			nfs_removeit(ndp);
17339395Smckusick 			nfs_nput(ndp->ni_dvp);
17438415Smckusick 		}
17539395Smckusick 		crfree(ndp->ni_cred);
17639395Smckusick 		free((caddr_t)sp, M_TEMP);
17739395Smckusick 	}
17839395Smckusick 	nfs_unlock(vp);
17941898Smckusick 	np->n_flag &= NMODIFIED;
18039395Smckusick #ifdef notdef
18139395Smckusick 	/*
18239395Smckusick 	 * Scan the request list for any requests left hanging about
18339395Smckusick 	 */
18439395Smckusick 	s = splnet();
18539395Smckusick 	rep = nfsreqh.r_next;
18639395Smckusick 	while (rep && rep != &nfsreqh) {
18739395Smckusick 		if (rep->r_vp == vp) {
18839395Smckusick 			rep->r_prev->r_next = rep2 = rep->r_next;
18939395Smckusick 			rep->r_next->r_prev = rep->r_prev;
19039395Smckusick 			m_freem(rep->r_mreq);
19139395Smckusick 			if (rep->r_mrep != NULL)
19239395Smckusick 				m_freem(rep->r_mrep);
19339395Smckusick 			free((caddr_t)rep, M_NFSREQ);
19439395Smckusick 			rep = rep2;
19539395Smckusick 		} else
19639395Smckusick 			rep = rep->r_next;
19739395Smckusick 	}
19839395Smckusick 	splx(s);
19938884Smacklem #endif
20039395Smckusick 	return (0);
20139395Smckusick }
20239395Smckusick 
20339395Smckusick /*
20439395Smckusick  * Reclaim an nfsnode so that it can be used for other purposes.
20539395Smckusick  */
20639395Smckusick nfs_reclaim(vp)
20739395Smckusick 	register struct vnode *vp;
20839395Smckusick {
20939395Smckusick 	register struct nfsnode *np = VTONFS(vp);
21039575Smckusick 	extern int prtactive;
21139395Smckusick 
21239810Smckusick 	if (prtactive && vp->v_usecount != 0)
21339671Smckusick 		vprint("nfs_reclaim: pushing active", vp);
21439395Smckusick 	/*
21539395Smckusick 	 * Remove the nfsnode from its hash chain.
21639395Smckusick 	 */
21739395Smckusick 	remque(np);
21839395Smckusick 	np->n_forw = np;
21939395Smckusick 	np->n_back = np;
22039395Smckusick 	cache_purge(vp);
22139752Smckusick 	np->n_flag = 0;
22241898Smckusick 	np->n_direofoffset = 0;
22338415Smckusick 	return (0);
22438415Smckusick }
22538415Smckusick 
22638415Smckusick /*
22738415Smckusick  * Lock an nfsnode
22838415Smckusick  */
22938415Smckusick nfs_lock(vp)
23038415Smckusick 	struct vnode *vp;
23138415Smckusick {
23238415Smckusick 	register struct nfsnode *np = VTONFS(vp);
23338415Smckusick 
23438415Smckusick 	while (np->n_flag & NLOCKED) {
23538415Smckusick 		np->n_flag |= NWANT;
23639904Smckusick 		if (np->n_lockholder == u.u_procp->p_pid)
23739904Smckusick 			panic("locking against myself");
23839904Smckusick 		np->n_lockwaiter = u.u_procp->p_pid;
23939908Smckusick 		(void) sleep((caddr_t)np, PINOD);
24038415Smckusick 	}
24139904Smckusick 	np->n_lockwaiter = 0;
24239904Smckusick 	np->n_lockholder = u.u_procp->p_pid;
24339904Smckusick 	u.u_spare[0]++;
24438415Smckusick 	np->n_flag |= NLOCKED;
24538415Smckusick }
24638415Smckusick 
24738415Smckusick /*
24838415Smckusick  * Unlock an nfsnode
24938415Smckusick  */
25038415Smckusick nfs_unlock(vp)
25138415Smckusick 	struct vnode *vp;
25238415Smckusick {
25338415Smckusick 	register struct nfsnode *np = VTONFS(vp);
25438415Smckusick 
25539904Smckusick 	if ((np->n_flag & NLOCKED) == 0)
25639904Smckusick 		vprint("nfs_unlock: unlocked nfsnode", vp);
25739904Smckusick 	np->n_lockholder = 0;
25839904Smckusick 	u.u_spare[0]--;
25938415Smckusick 	np->n_flag &= ~NLOCKED;
26038415Smckusick 	if (np->n_flag & NWANT) {
26138415Smckusick 		np->n_flag &= ~NWANT;
26238415Smckusick 		wakeup((caddr_t)np);
26338415Smckusick 	}
26438415Smckusick }
26538415Smckusick 
26638415Smckusick /*
26739908Smckusick  * Check for a locked nfsnode
26839908Smckusick  */
26939908Smckusick nfs_islocked(vp)
27039908Smckusick 	struct vnode *vp;
27139908Smckusick {
27239908Smckusick 
27339908Smckusick 	if (VTONFS(vp)->n_flag & NLOCKED)
27439908Smckusick 		return (1);
27539908Smckusick 	return (0);
27639908Smckusick }
27739908Smckusick 
27839908Smckusick /*
27938415Smckusick  * Unlock and vrele()
28038415Smckusick  * since I can't decide if dirs. should be locked, I will check for
28138415Smckusick  * the lock and be flexible
28238415Smckusick  */
28338415Smckusick nfs_nput(vp)
28438415Smckusick 	struct vnode *vp;
28538415Smckusick {
28638415Smckusick 	register struct nfsnode *np = VTONFS(vp);
28738415Smckusick 
28838415Smckusick 	if (np->n_flag & NLOCKED)
28938415Smckusick 		nfs_unlock(vp);
29038415Smckusick 	vrele(vp);
29138415Smckusick }
29238415Smckusick 
293*42467Smckusick /*
294*42467Smckusick  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
295*42467Smckusick  * done. Currently nothing to do.
296*42467Smckusick  */
297*42467Smckusick /* ARGSUSED */
29838415Smckusick nfs_abortop(ndp)
299*42467Smckusick 	struct nameidata *ndp;
30038415Smckusick {
30138415Smckusick 
302*42467Smckusick 	return (0);
30338415Smckusick }
304