xref: /netbsd-src/sys/miscfs/genfs/genfs_vnops.c (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
1 /*	$NetBSD: genfs_vnops.c,v 1.167 2008/04/28 20:24:08 martin Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Copyright (c) 1982, 1986, 1989, 1993
31  *	The Regents of the University of California.  All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  * 3. Neither the name of the University nor the names of its contributors
42  *    may be used to endorse or promote products derived from this software
43  *    without specific prior written permission.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55  * SUCH DAMAGE.
56  *
57  */
58 
59 #include <sys/cdefs.h>
60 __KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.167 2008/04/28 20:24:08 martin Exp $");
61 
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/proc.h>
65 #include <sys/kernel.h>
66 #include <sys/mount.h>
67 #include <sys/namei.h>
68 #include <sys/vnode.h>
69 #include <sys/fcntl.h>
70 #include <sys/kmem.h>
71 #include <sys/poll.h>
72 #include <sys/mman.h>
73 #include <sys/file.h>
74 #include <sys/kauth.h>
75 
76 #include <miscfs/genfs/genfs.h>
77 #include <miscfs/genfs/genfs_node.h>
78 #include <miscfs/specfs/specdev.h>
79 
80 #include <uvm/uvm.h>
81 #include <uvm/uvm_pager.h>
82 
83 static void filt_genfsdetach(struct knote *);
84 static int filt_genfsread(struct knote *, long);
85 static int filt_genfsvnode(struct knote *, long);
86 
87 int
88 genfs_poll(void *v)
89 {
90 	struct vop_poll_args /* {
91 		struct vnode *a_vp;
92 		int a_events;
93 		struct lwp *a_l;
94 	} */ *ap = v;
95 
96 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
97 }
98 
99 int
100 genfs_seek(void *v)
101 {
102 	struct vop_seek_args /* {
103 		struct vnode *a_vp;
104 		off_t a_oldoff;
105 		off_t a_newoff;
106 		kauth_cred_t cred;
107 	} */ *ap = v;
108 
109 	if (ap->a_newoff < 0)
110 		return (EINVAL);
111 
112 	return (0);
113 }
114 
115 int
116 genfs_abortop(void *v)
117 {
118 	struct vop_abortop_args /* {
119 		struct vnode *a_dvp;
120 		struct componentname *a_cnp;
121 	} */ *ap = v;
122 
123 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
124 		PNBUF_PUT(ap->a_cnp->cn_pnbuf);
125 	return (0);
126 }
127 
128 int
129 genfs_fcntl(void *v)
130 {
131 	struct vop_fcntl_args /* {
132 		struct vnode *a_vp;
133 		u_int a_command;
134 		void *a_data;
135 		int a_fflag;
136 		kauth_cred_t a_cred;
137 		struct lwp *a_l;
138 	} */ *ap = v;
139 
140 	if (ap->a_command == F_SETFL)
141 		return (0);
142 	else
143 		return (EOPNOTSUPP);
144 }
145 
146 /*ARGSUSED*/
147 int
148 genfs_badop(void *v)
149 {
150 
151 	panic("genfs: bad op");
152 }
153 
154 /*ARGSUSED*/
155 int
156 genfs_nullop(void *v)
157 {
158 
159 	return (0);
160 }
161 
162 /*ARGSUSED*/
163 int
164 genfs_einval(void *v)
165 {
166 
167 	return (EINVAL);
168 }
169 
170 /*
171  * Called when an fs doesn't support a particular vop.
172  * This takes care to vrele, vput, or vunlock passed in vnodes.
173  */
174 int
175 genfs_eopnotsupp(void *v)
176 {
177 	struct vop_generic_args /*
178 		struct vnodeop_desc *a_desc;
179 		/ * other random data follows, presumably * /
180 	} */ *ap = v;
181 	struct vnodeop_desc *desc = ap->a_desc;
182 	struct vnode *vp, *vp_last = NULL;
183 	int flags, i, j, offset;
184 
185 	flags = desc->vdesc_flags;
186 	for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) {
187 		if ((offset = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET)
188 			break;	/* stop at end of list */
189 		if ((j = flags & VDESC_VP0_WILLPUT)) {
190 			vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap);
191 
192 			/* Skip if NULL */
193 			if (!vp)
194 				continue;
195 
196 			switch (j) {
197 			case VDESC_VP0_WILLPUT:
198 				/* Check for dvp == vp cases */
199 				if (vp == vp_last)
200 					vrele(vp);
201 				else {
202 					vput(vp);
203 					vp_last = vp;
204 				}
205 				break;
206 			case VDESC_VP0_WILLUNLOCK:
207 				VOP_UNLOCK(vp, 0);
208 				break;
209 			case VDESC_VP0_WILLRELE:
210 				vrele(vp);
211 				break;
212 			}
213 		}
214 	}
215 
216 	return (EOPNOTSUPP);
217 }
218 
219 /*ARGSUSED*/
220 int
221 genfs_ebadf(void *v)
222 {
223 
224 	return (EBADF);
225 }
226 
227 /* ARGSUSED */
228 int
229 genfs_enoioctl(void *v)
230 {
231 
232 	return (EPASSTHROUGH);
233 }
234 
235 
236 /*
237  * Eliminate all activity associated with the requested vnode
238  * and with all vnodes aliased to the requested vnode.
239  */
240 int
241 genfs_revoke(void *v)
242 {
243 	struct vop_revoke_args /* {
244 		struct vnode *a_vp;
245 		int a_flags;
246 	} */ *ap = v;
247 
248 #ifdef DIAGNOSTIC
249 	if ((ap->a_flags & REVOKEALL) == 0)
250 		panic("genfs_revoke: not revokeall");
251 #endif
252 	vrevoke(ap->a_vp);
253 	return (0);
254 }
255 
256 /*
257  * Lock the node.
258  */
259 int
260 genfs_lock(void *v)
261 {
262 	struct vop_lock_args /* {
263 		struct vnode *a_vp;
264 		int a_flags;
265 	} */ *ap = v;
266 	struct vnode *vp = ap->a_vp;
267 	int flags = ap->a_flags;
268 
269 	if ((flags & LK_INTERLOCK) != 0) {
270 		flags &= ~LK_INTERLOCK;
271 		mutex_exit(&vp->v_interlock);
272 	}
273 
274 	return (vlockmgr(vp->v_vnlock, flags));
275 }
276 
277 /*
278  * Unlock the node.
279  */
280 int
281 genfs_unlock(void *v)
282 {
283 	struct vop_unlock_args /* {
284 		struct vnode *a_vp;
285 		int a_flags;
286 	} */ *ap = v;
287 	struct vnode *vp = ap->a_vp;
288 
289 	KASSERT(ap->a_flags == 0);
290 
291 	return (vlockmgr(vp->v_vnlock, LK_RELEASE));
292 }
293 
294 /*
295  * Return whether or not the node is locked.
296  */
297 int
298 genfs_islocked(void *v)
299 {
300 	struct vop_islocked_args /* {
301 		struct vnode *a_vp;
302 	} */ *ap = v;
303 	struct vnode *vp = ap->a_vp;
304 
305 	return (vlockstatus(vp->v_vnlock));
306 }
307 
308 /*
309  * Stubs to use when there is no locking to be done on the underlying object.
310  */
311 int
312 genfs_nolock(void *v)
313 {
314 	struct vop_lock_args /* {
315 		struct vnode *a_vp;
316 		int a_flags;
317 		struct lwp *a_l;
318 	} */ *ap = v;
319 
320 	/*
321 	 * Since we are not using the lock manager, we must clear
322 	 * the interlock here.
323 	 */
324 	if (ap->a_flags & LK_INTERLOCK)
325 		mutex_exit(&ap->a_vp->v_interlock);
326 	return (0);
327 }
328 
329 int
330 genfs_nounlock(void *v)
331 {
332 
333 	return (0);
334 }
335 
336 int
337 genfs_noislocked(void *v)
338 {
339 
340 	return (0);
341 }
342 
343 int
344 genfs_mmap(void *v)
345 {
346 
347 	return (0);
348 }
349 
350 void
351 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops)
352 {
353 	struct genfs_node *gp = VTOG(vp);
354 
355 	rw_init(&gp->g_glock);
356 	gp->g_op = ops;
357 }
358 
359 void
360 genfs_node_destroy(struct vnode *vp)
361 {
362 	struct genfs_node *gp = VTOG(vp);
363 
364 	rw_destroy(&gp->g_glock);
365 }
366 
367 void
368 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
369 {
370 	int bsize;
371 
372 	bsize = 1 << vp->v_mount->mnt_fs_bshift;
373 	*eobp = (size + bsize - 1) & ~(bsize - 1);
374 }
375 
376 static void
377 filt_genfsdetach(struct knote *kn)
378 {
379 	struct vnode *vp = (struct vnode *)kn->kn_hook;
380 
381 	mutex_enter(&vp->v_interlock);
382 	SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext);
383 	mutex_exit(&vp->v_interlock);
384 }
385 
386 static int
387 filt_genfsread(struct knote *kn, long hint)
388 {
389 	struct vnode *vp = (struct vnode *)kn->kn_hook;
390 	int rv;
391 
392 	/*
393 	 * filesystem is gone, so set the EOF flag and schedule
394 	 * the knote for deletion.
395 	 */
396 	switch (hint) {
397 	case NOTE_REVOKE:
398 		KASSERT(mutex_owned(&vp->v_interlock));
399 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
400 		return (1);
401 	case 0:
402 		mutex_enter(&vp->v_interlock);
403 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
404 		rv = (kn->kn_data != 0);
405 		mutex_exit(&vp->v_interlock);
406 		return rv;
407 	default:
408 		KASSERT(mutex_owned(&vp->v_interlock));
409 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
410 		return (kn->kn_data != 0);
411 	}
412 }
413 
414 static int
415 filt_genfsvnode(struct knote *kn, long hint)
416 {
417 	struct vnode *vp = (struct vnode *)kn->kn_hook;
418 	int fflags;
419 
420 	switch (hint) {
421 	case NOTE_REVOKE:
422 		KASSERT(mutex_owned(&vp->v_interlock));
423 		kn->kn_flags |= EV_EOF;
424 		if ((kn->kn_sfflags & hint) != 0)
425 			kn->kn_fflags |= hint;
426 		return (1);
427 	case 0:
428 		mutex_enter(&vp->v_interlock);
429 		fflags = kn->kn_fflags;
430 		mutex_exit(&vp->v_interlock);
431 		break;
432 	default:
433 		KASSERT(mutex_owned(&vp->v_interlock));
434 		if ((kn->kn_sfflags & hint) != 0)
435 			kn->kn_fflags |= hint;
436 		fflags = kn->kn_fflags;
437 		break;
438 	}
439 
440 	return (fflags != 0);
441 }
442 
443 static const struct filterops genfsread_filtops =
444 	{ 1, NULL, filt_genfsdetach, filt_genfsread };
445 static const struct filterops genfsvnode_filtops =
446 	{ 1, NULL, filt_genfsdetach, filt_genfsvnode };
447 
448 int
449 genfs_kqfilter(void *v)
450 {
451 	struct vop_kqfilter_args /* {
452 		struct vnode	*a_vp;
453 		struct knote	*a_kn;
454 	} */ *ap = v;
455 	struct vnode *vp;
456 	struct knote *kn;
457 
458 	vp = ap->a_vp;
459 	kn = ap->a_kn;
460 	switch (kn->kn_filter) {
461 	case EVFILT_READ:
462 		kn->kn_fop = &genfsread_filtops;
463 		break;
464 	case EVFILT_VNODE:
465 		kn->kn_fop = &genfsvnode_filtops;
466 		break;
467 	default:
468 		return (EINVAL);
469 	}
470 
471 	kn->kn_hook = vp;
472 
473 	mutex_enter(&vp->v_interlock);
474 	SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext);
475 	mutex_exit(&vp->v_interlock);
476 
477 	return (0);
478 }
479 
480 void
481 genfs_node_wrlock(struct vnode *vp)
482 {
483 	struct genfs_node *gp = VTOG(vp);
484 
485 	rw_enter(&gp->g_glock, RW_WRITER);
486 }
487 
488 void
489 genfs_node_rdlock(struct vnode *vp)
490 {
491 	struct genfs_node *gp = VTOG(vp);
492 
493 	rw_enter(&gp->g_glock, RW_READER);
494 }
495 
496 void
497 genfs_node_unlock(struct vnode *vp)
498 {
499 	struct genfs_node *gp = VTOG(vp);
500 
501 	rw_exit(&gp->g_glock);
502 }
503