genfs_vnops.c revision 1.166.2.1 1 /* $NetBSD: genfs_vnops.c,v 1.166.2.1 2008/05/16 02:25:39 yamt 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.166.2.1 2008/05/16 02:25:39 yamt 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