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