genfs_vnops.c revision 1.160 1 /* $NetBSD: genfs_vnops.c,v 1.160 2008/01/02 11:48:59 ad 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.160 2008/01/02 11:48:59 ad 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, **vpp;
223 enum vtype type;
224 dev_t dev;
225
226 #ifdef DIAGNOSTIC
227 if ((ap->a_flags & REVOKEALL) == 0)
228 panic("genfs_revoke: not revokeall");
229 #endif
230 vp = ap->a_vp;
231
232 mutex_enter(&vp->v_interlock);
233 if ((vp->v_iflag & VI_CLEAN) != 0) {
234 mutex_exit(&vp->v_interlock);
235 return (0);
236 } else {
237 dev = vp->v_rdev;
238 type = vp->v_type;
239 mutex_exit(&vp->v_interlock);
240 }
241
242 if (type != VBLK && type != VCHR)
243 return (0);
244
245 vpp = &speclisth[SPECHASH(dev)];
246 mutex_enter(&spechash_lock);
247 for (vq = *vpp; vq != NULL;) {
248 if (vq->v_rdev != dev || vq->v_type != type) {
249 vq = vq->v_specnext;
250 continue;
251 }
252 mutex_enter(&vq->v_interlock);
253 mutex_exit(&spechash_lock);
254 vq->v_usecount++;
255 vclean(vq, DOCLOSE);
256 vrelel(vq, 1, 0);
257 mutex_enter(&spechash_lock);
258 vq = *vpp;
259 }
260 mutex_exit(&spechash_lock);
261
262 return (0);
263 }
264
265 /*
266 * Lock the node.
267 */
268 int
269 genfs_lock(void *v)
270 {
271 struct vop_lock_args /* {
272 struct vnode *a_vp;
273 int a_flags;
274 } */ *ap = v;
275 struct vnode *vp = ap->a_vp;
276
277 return (lockmgr(vp->v_vnlock, ap->a_flags, &vp->v_interlock));
278 }
279
280 /*
281 * Unlock the node.
282 */
283 int
284 genfs_unlock(void *v)
285 {
286 struct vop_unlock_args /* {
287 struct vnode *a_vp;
288 int a_flags;
289 } */ *ap = v;
290 struct vnode *vp = ap->a_vp;
291
292 return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE,
293 &vp->v_interlock));
294 }
295
296 /*
297 * Return whether or not the node is locked.
298 */
299 int
300 genfs_islocked(void *v)
301 {
302 struct vop_islocked_args /* {
303 struct vnode *a_vp;
304 } */ *ap = v;
305 struct vnode *vp = ap->a_vp;
306
307 return (lockstatus(vp->v_vnlock));
308 }
309
310 /*
311 * Stubs to use when there is no locking to be done on the underlying object.
312 */
313 int
314 genfs_nolock(void *v)
315 {
316 struct vop_lock_args /* {
317 struct vnode *a_vp;
318 int a_flags;
319 struct lwp *a_l;
320 } */ *ap = v;
321
322 /*
323 * Since we are not using the lock manager, we must clear
324 * the interlock here.
325 */
326 if (ap->a_flags & LK_INTERLOCK)
327 mutex_exit(&ap->a_vp->v_interlock);
328 return (0);
329 }
330
331 int
332 genfs_nounlock(void *v)
333 {
334
335 return (0);
336 }
337
338 int
339 genfs_noislocked(void *v)
340 {
341
342 return (0);
343 }
344
345 /*
346 * Local lease check.
347 */
348 int
349 genfs_lease_check(void *v)
350 {
351
352 return (0);
353 }
354
355 int
356 genfs_mmap(void *v)
357 {
358
359 return (0);
360 }
361
362 void
363 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops)
364 {
365 struct genfs_node *gp = VTOG(vp);
366
367 rw_init(&gp->g_glock);
368 gp->g_op = ops;
369 }
370
371 void
372 genfs_node_destroy(struct vnode *vp)
373 {
374 struct genfs_node *gp = VTOG(vp);
375
376 rw_destroy(&gp->g_glock);
377 }
378
379 void
380 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
381 {
382 int bsize;
383
384 bsize = 1 << vp->v_mount->mnt_fs_bshift;
385 *eobp = (size + bsize - 1) & ~(bsize - 1);
386 }
387
388 static void
389 filt_genfsdetach(struct knote *kn)
390 {
391 struct vnode *vp = (struct vnode *)kn->kn_hook;
392
393 /* XXXLUKEM lock the struct? */
394 SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext);
395 }
396
397 static int
398 filt_genfsread(struct knote *kn, long hint)
399 {
400 struct vnode *vp = (struct vnode *)kn->kn_hook;
401
402 /*
403 * filesystem is gone, so set the EOF flag and schedule
404 * the knote for deletion.
405 */
406 if (hint == NOTE_REVOKE) {
407 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
408 return (1);
409 }
410
411 /* XXXLUKEM lock the struct? */
412 kn->kn_data = vp->v_size - kn->kn_fp->f_offset;
413 return (kn->kn_data != 0);
414 }
415
416 static int
417 filt_genfsvnode(struct knote *kn, long hint)
418 {
419
420 if (kn->kn_sfflags & hint)
421 kn->kn_fflags |= hint;
422 if (hint == NOTE_REVOKE) {
423 kn->kn_flags |= EV_EOF;
424 return (1);
425 }
426 return (kn->kn_fflags != 0);
427 }
428
429 static const struct filterops genfsread_filtops =
430 { 1, NULL, filt_genfsdetach, filt_genfsread };
431 static const struct filterops genfsvnode_filtops =
432 { 1, NULL, filt_genfsdetach, filt_genfsvnode };
433
434 int
435 genfs_kqfilter(void *v)
436 {
437 struct vop_kqfilter_args /* {
438 struct vnode *a_vp;
439 struct knote *a_kn;
440 } */ *ap = v;
441 struct vnode *vp;
442 struct knote *kn;
443
444 vp = ap->a_vp;
445 kn = ap->a_kn;
446 switch (kn->kn_filter) {
447 case EVFILT_READ:
448 kn->kn_fop = &genfsread_filtops;
449 break;
450 case EVFILT_VNODE:
451 kn->kn_fop = &genfsvnode_filtops;
452 break;
453 default:
454 return (EINVAL);
455 }
456
457 kn->kn_hook = vp;
458
459 /* XXXLUKEM lock the struct? */
460 SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext);
461
462 return (0);
463 }
464
465 void
466 genfs_node_wrlock(struct vnode *vp)
467 {
468 struct genfs_node *gp = VTOG(vp);
469
470 rw_enter(&gp->g_glock, RW_WRITER);
471 }
472
473 void
474 genfs_node_rdlock(struct vnode *vp)
475 {
476 struct genfs_node *gp = VTOG(vp);
477
478 rw_enter(&gp->g_glock, RW_READER);
479 }
480
481 void
482 genfs_node_unlock(struct vnode *vp)
483 {
484 struct genfs_node *gp = VTOG(vp);
485
486 rw_exit(&gp->g_glock);
487 }
488