genfs_vnops.c revision 1.168 1 /* $NetBSD: genfs_vnops.c,v 1.168 2009/04/18 15:40:33 pooka 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.168 2009/04/18 15:40:33 pooka 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 /*
351 * VOP_PUTPAGES() for vnodes which never have pages.
352 */
353
354 int
355 genfs_null_putpages(void *v)
356 {
357 struct vop_putpages_args /* {
358 struct vnode *a_vp;
359 voff_t a_offlo;
360 voff_t a_offhi;
361 int a_flags;
362 } */ *ap = v;
363 struct vnode *vp = ap->a_vp;
364
365 KASSERT(vp->v_uobj.uo_npages == 0);
366 mutex_exit(&vp->v_interlock);
367 return (0);
368 }
369
370 void
371 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops)
372 {
373 struct genfs_node *gp = VTOG(vp);
374
375 rw_init(&gp->g_glock);
376 gp->g_op = ops;
377 }
378
379 void
380 genfs_node_destroy(struct vnode *vp)
381 {
382 struct genfs_node *gp = VTOG(vp);
383
384 rw_destroy(&gp->g_glock);
385 }
386
387 void
388 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
389 {
390 int bsize;
391
392 bsize = 1 << vp->v_mount->mnt_fs_bshift;
393 *eobp = (size + bsize - 1) & ~(bsize - 1);
394 }
395
396 static void
397 filt_genfsdetach(struct knote *kn)
398 {
399 struct vnode *vp = (struct vnode *)kn->kn_hook;
400
401 mutex_enter(&vp->v_interlock);
402 SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext);
403 mutex_exit(&vp->v_interlock);
404 }
405
406 static int
407 filt_genfsread(struct knote *kn, long hint)
408 {
409 struct vnode *vp = (struct vnode *)kn->kn_hook;
410 int rv;
411
412 /*
413 * filesystem is gone, so set the EOF flag and schedule
414 * the knote for deletion.
415 */
416 switch (hint) {
417 case NOTE_REVOKE:
418 KASSERT(mutex_owned(&vp->v_interlock));
419 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
420 return (1);
421 case 0:
422 mutex_enter(&vp->v_interlock);
423 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
424 rv = (kn->kn_data != 0);
425 mutex_exit(&vp->v_interlock);
426 return rv;
427 default:
428 KASSERT(mutex_owned(&vp->v_interlock));
429 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
430 return (kn->kn_data != 0);
431 }
432 }
433
434 static int
435 filt_genfsvnode(struct knote *kn, long hint)
436 {
437 struct vnode *vp = (struct vnode *)kn->kn_hook;
438 int fflags;
439
440 switch (hint) {
441 case NOTE_REVOKE:
442 KASSERT(mutex_owned(&vp->v_interlock));
443 kn->kn_flags |= EV_EOF;
444 if ((kn->kn_sfflags & hint) != 0)
445 kn->kn_fflags |= hint;
446 return (1);
447 case 0:
448 mutex_enter(&vp->v_interlock);
449 fflags = kn->kn_fflags;
450 mutex_exit(&vp->v_interlock);
451 break;
452 default:
453 KASSERT(mutex_owned(&vp->v_interlock));
454 if ((kn->kn_sfflags & hint) != 0)
455 kn->kn_fflags |= hint;
456 fflags = kn->kn_fflags;
457 break;
458 }
459
460 return (fflags != 0);
461 }
462
463 static const struct filterops genfsread_filtops =
464 { 1, NULL, filt_genfsdetach, filt_genfsread };
465 static const struct filterops genfsvnode_filtops =
466 { 1, NULL, filt_genfsdetach, filt_genfsvnode };
467
468 int
469 genfs_kqfilter(void *v)
470 {
471 struct vop_kqfilter_args /* {
472 struct vnode *a_vp;
473 struct knote *a_kn;
474 } */ *ap = v;
475 struct vnode *vp;
476 struct knote *kn;
477
478 vp = ap->a_vp;
479 kn = ap->a_kn;
480 switch (kn->kn_filter) {
481 case EVFILT_READ:
482 kn->kn_fop = &genfsread_filtops;
483 break;
484 case EVFILT_VNODE:
485 kn->kn_fop = &genfsvnode_filtops;
486 break;
487 default:
488 return (EINVAL);
489 }
490
491 kn->kn_hook = vp;
492
493 mutex_enter(&vp->v_interlock);
494 SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext);
495 mutex_exit(&vp->v_interlock);
496
497 return (0);
498 }
499
500 void
501 genfs_node_wrlock(struct vnode *vp)
502 {
503 struct genfs_node *gp = VTOG(vp);
504
505 rw_enter(&gp->g_glock, RW_WRITER);
506 }
507
508 void
509 genfs_node_rdlock(struct vnode *vp)
510 {
511 struct genfs_node *gp = VTOG(vp);
512
513 rw_enter(&gp->g_glock, RW_READER);
514 }
515
516 void
517 genfs_node_unlock(struct vnode *vp)
518 {
519 struct genfs_node *gp = VTOG(vp);
520
521 rw_exit(&gp->g_glock);
522 }
523