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