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