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