xref: /csrg-svn/sys/nfs/nfs_node.c (revision 59385)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)nfs_node.c	7.47 (Berkeley) 04/27/93
11  */
12 
13 #include <sys/param.h>
14 #include <sys/systm.h>
15 #include <sys/proc.h>
16 #include <sys/mount.h>
17 #include <sys/namei.h>
18 #include <sys/vnode.h>
19 #include <sys/kernel.h>
20 #include <sys/malloc.h>
21 
22 #include <nfs/rpcv2.h>
23 #include <nfs/nfsv2.h>
24 #include <nfs/nfs.h>
25 #include <nfs/nfsnode.h>
26 #include <nfs/nfsmount.h>
27 #include <nfs/nqnfs.h>
28 
29 struct nfsnode **nheadhashtbl;
30 u_long nheadhash;
31 #define	NFSNOHASH(fhsum)	((fhsum)&nheadhash)
32 
33 #define TRUE	1
34 #define	FALSE	0
35 
36 /*
37  * Initialize hash links for nfsnodes
38  * and build nfsnode free list.
39  */
40 nfs_nhinit()
41 {
42 
43 #ifndef lint
44 	if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode))
45 		printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode));
46 #endif /* not lint */
47 	nheadhashtbl = hashinit(desiredvnodes, M_NFSNODE, &nheadhash);
48 }
49 
50 /*
51  * Compute an entry in the NFS hash table structure
52  */
53 struct nfsnode **
54 nfs_hash(fhp)
55 	register nfsv2fh_t *fhp;
56 {
57 	register u_char *fhpp;
58 	register u_long fhsum;
59 	int i;
60 
61 	fhpp = &fhp->fh_bytes[0];
62 	fhsum = 0;
63 	for (i = 0; i < NFSX_FH; i++)
64 		fhsum += *fhpp++;
65 	return (&nheadhashtbl[NFSNOHASH(fhsum)]);
66 }
67 
68 /*
69  * Look up a vnode/nfsnode by file handle.
70  * Callers must check for mount points!!
71  * In all cases, a pointer to a
72  * nfsnode structure is returned.
73  */
74 nfs_nget(mntp, fhp, npp)
75 	struct mount *mntp;
76 	register nfsv2fh_t *fhp;
77 	struct nfsnode **npp;
78 {
79 	register struct nfsnode *np, *nq, **nhpp;
80 	register struct vnode *vp;
81 	extern int (**nfsv2_vnodeop_p)();
82 	struct vnode *nvp;
83 	int error;
84 
85 	nhpp = nfs_hash(fhp);
86 loop:
87 	for (np = *nhpp; np; np = np->n_forw) {
88 		if (mntp != NFSTOV(np)->v_mount ||
89 		    bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
90 			continue;
91 		vp = NFSTOV(np);
92 		if (vget(vp))
93 			goto loop;
94 		*npp = np;
95 		return(0);
96 	}
97 	if (error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp)) {
98 		*npp = 0;
99 		return (error);
100 	}
101 	vp = nvp;
102 	MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
103 	vp->v_data = np;
104 	np->n_vnode = vp;
105 	/*
106 	 * Insert the nfsnode in the hash queue for its new file handle
107 	 */
108 	np->n_flag = 0;
109 	if (nq = *nhpp)
110 		nq->n_back = &np->n_forw;
111 	np->n_forw = nq;
112 	np->n_back = nhpp;
113 	*nhpp = np;
114 	bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
115 	np->n_attrstamp = 0;
116 	np->n_direofoffset = 0;
117 	np->n_sillyrename = (struct sillyrename *)0;
118 	np->n_size = 0;
119 	np->n_mtime = 0;
120 	if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
121 		np->n_brev = 0;
122 		np->n_lrev = 0;
123 		np->n_expiry = (time_t)0;
124 		np->n_tnext = (struct nfsnode *)0;
125 	}
126 	*npp = np;
127 	return (0);
128 }
129 
130 nfs_inactive(ap)
131 	struct vop_inactive_args /* {
132 		struct vnode *a_vp;
133 	} */ *ap;
134 {
135 	register struct nfsnode *np;
136 	register struct sillyrename *sp;
137 	struct proc *p = curproc;	/* XXX */
138 	extern int prtactive;
139 
140 	np = VTONFS(ap->a_vp);
141 	if (prtactive && ap->a_vp->v_usecount != 0)
142 		vprint("nfs_inactive: pushing active", ap->a_vp);
143 	sp = np->n_sillyrename;
144 	np->n_sillyrename = (struct sillyrename *)0;
145 	if (sp) {
146 		/*
147 		 * Remove the silly file that was rename'd earlier
148 		 */
149 		(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
150 		nfs_removeit(sp);
151 		crfree(sp->s_cred);
152 		vrele(sp->s_dvp);
153 #ifdef SILLYSEPARATE
154 		free((caddr_t)sp, M_NFSREQ);
155 #endif
156 	}
157 	np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED);
158 	return (0);
159 }
160 
161 /*
162  * Reclaim an nfsnode so that it can be used for other purposes.
163  */
164 nfs_reclaim(ap)
165 	struct vop_reclaim_args /* {
166 		struct vnode *a_vp;
167 	} */ *ap;
168 {
169 	register struct vnode *vp = ap->a_vp;
170 	register struct nfsnode *np = VTONFS(vp);
171 	register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
172 	register struct nfsnode *nq;
173 	extern int prtactive;
174 
175 	if (prtactive && vp->v_usecount != 0)
176 		vprint("nfs_reclaim: pushing active", vp);
177 	/*
178 	 * Remove the nfsnode from its hash chain.
179 	 */
180 	if (nq = np->n_forw)
181 		nq->n_back = np->n_back;
182 	*np->n_back = nq;
183 
184 	/*
185 	 * For nqnfs, take it off the timer queue as required.
186 	 */
187 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) {
188 		if (np->n_tnext == (struct nfsnode *)nmp)
189 			nmp->nm_tprev = np->n_tprev;
190 		else
191 			np->n_tnext->n_tprev = np->n_tprev;
192 		if (np->n_tprev == (struct nfsnode *)nmp)
193 			nmp->nm_tnext = np->n_tnext;
194 		else
195 			np->n_tprev->n_tnext = np->n_tnext;
196 	}
197 	cache_purge(vp);
198 	FREE(vp->v_data, M_NFSNODE);
199 	vp->v_data = (void *)0;
200 	return (0);
201 }
202 
203 /*
204  * Lock an nfsnode
205  */
206 nfs_lock(ap)
207 	struct vop_lock_args /* {
208 		struct vnode *a_vp;
209 	} */ *ap;
210 {
211 	register struct vnode *vp = ap->a_vp;
212 
213 	/*
214 	 * Ugh, another place where interruptible mounts will get hung.
215 	 * If you make this sleep interruptible, then you have to fix all
216 	 * the VOP_LOCK() calls to expect interruptibility.
217 	 */
218 	while (vp->v_flag & VXLOCK) {
219 		vp->v_flag |= VXWANT;
220 		sleep((caddr_t)vp, PINOD);
221 	}
222 	if (vp->v_tag == VT_NON)
223 		return (ENOENT);
224 	return (0);
225 }
226 
227 /*
228  * Unlock an nfsnode
229  */
230 nfs_unlock(ap)
231 	struct vop_unlock_args /* {
232 		struct vnode *a_vp;
233 	} */ *ap;
234 {
235 
236 	return (0);
237 }
238 
239 /*
240  * Check for a locked nfsnode
241  */
242 nfs_islocked(ap)
243 	struct vop_islocked_args /* {
244 		struct vnode *a_vp;
245 	} */ *ap;
246 {
247 
248 	return (0);
249 }
250 
251 /*
252  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
253  * done. Currently nothing to do.
254  */
255 /* ARGSUSED */
256 int
257 nfs_abortop(ap)
258 	struct vop_abortop_args /* {
259 		struct vnode *a_dvp;
260 		struct componentname *a_cnp;
261 	} */ *ap;
262 {
263 
264 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
265 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
266 	return (0);
267 }
268