xref: /original-bsd/sys/nfs/nfs_node.c (revision 3705696b)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  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	8.1 (Berkeley) 06/10/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 		NQNFSNONCACHE | NQNFSWRITE);
159 	return (0);
160 }
161 
162 /*
163  * Reclaim an nfsnode so that it can be used for other purposes.
164  */
165 nfs_reclaim(ap)
166 	struct vop_reclaim_args /* {
167 		struct vnode *a_vp;
168 	} */ *ap;
169 {
170 	register struct vnode *vp = ap->a_vp;
171 	register struct nfsnode *np = VTONFS(vp);
172 	register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
173 	register struct nfsnode *nq;
174 	extern int prtactive;
175 
176 	if (prtactive && vp->v_usecount != 0)
177 		vprint("nfs_reclaim: pushing active", vp);
178 	/*
179 	 * Remove the nfsnode from its hash chain.
180 	 */
181 	if (nq = np->n_forw)
182 		nq->n_back = np->n_back;
183 	*np->n_back = nq;
184 
185 	/*
186 	 * For nqnfs, take it off the timer queue as required.
187 	 */
188 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) {
189 		if (np->n_tnext == (struct nfsnode *)nmp)
190 			nmp->nm_tprev = np->n_tprev;
191 		else
192 			np->n_tnext->n_tprev = np->n_tprev;
193 		if (np->n_tprev == (struct nfsnode *)nmp)
194 			nmp->nm_tnext = np->n_tnext;
195 		else
196 			np->n_tprev->n_tnext = np->n_tnext;
197 	}
198 	cache_purge(vp);
199 	FREE(vp->v_data, M_NFSNODE);
200 	vp->v_data = (void *)0;
201 	return (0);
202 }
203 
204 /*
205  * Lock an nfsnode
206  */
207 nfs_lock(ap)
208 	struct vop_lock_args /* {
209 		struct vnode *a_vp;
210 	} */ *ap;
211 {
212 	register struct vnode *vp = ap->a_vp;
213 
214 	/*
215 	 * Ugh, another place where interruptible mounts will get hung.
216 	 * If you make this sleep interruptible, then you have to fix all
217 	 * the VOP_LOCK() calls to expect interruptibility.
218 	 */
219 	while (vp->v_flag & VXLOCK) {
220 		vp->v_flag |= VXWANT;
221 		sleep((caddr_t)vp, PINOD);
222 	}
223 	if (vp->v_tag == VT_NON)
224 		return (ENOENT);
225 	return (0);
226 }
227 
228 /*
229  * Unlock an nfsnode
230  */
231 nfs_unlock(ap)
232 	struct vop_unlock_args /* {
233 		struct vnode *a_vp;
234 	} */ *ap;
235 {
236 
237 	return (0);
238 }
239 
240 /*
241  * Check for a locked nfsnode
242  */
243 nfs_islocked(ap)
244 	struct vop_islocked_args /* {
245 		struct vnode *a_vp;
246 	} */ *ap;
247 {
248 
249 	return (0);
250 }
251 
252 /*
253  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
254  * done. Currently nothing to do.
255  */
256 /* ARGSUSED */
257 int
258 nfs_abortop(ap)
259 	struct vop_abortop_args /* {
260 		struct vnode *a_dvp;
261 		struct componentname *a_cnp;
262 	} */ *ap;
263 {
264 
265 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
266 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
267 	return (0);
268 }
269