1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software donated to Berkeley by
6 * Jan-Simon Pendry.
7 *
8 * %sccs.include.redist.c%
9 *
10 * @(#)kernfs_vnops.c 8.15 (Berkeley) 05/21/95
11 */
12
13 /*
14 * Kernel parameter filesystem (/kern)
15 */
16
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/kernel.h>
20 #include <sys/vmmeter.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/proc.h>
24 #include <sys/vnode.h>
25 #include <sys/malloc.h>
26 #include <sys/file.h>
27 #include <sys/stat.h>
28 #include <sys/mount.h>
29 #include <sys/namei.h>
30 #include <sys/buf.h>
31 #include <sys/dirent.h>
32 #include <miscfs/kernfs/kernfs.h>
33
34 #define KSTRING 256 /* Largest I/O available via this filesystem */
35 #define UIO_MX 32
36
37 #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH)
38 #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
39 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
40
41 struct kern_target {
42 u_char kt_type;
43 u_char kt_namlen;
44 char *kt_name;
45 void *kt_data;
46 #define KTT_NULL 1
47 #define KTT_TIME 5
48 #define KTT_INT 17
49 #define KTT_STRING 31
50 #define KTT_HOSTNAME 47
51 #define KTT_AVENRUN 53
52 #define KTT_DEVICE 71
53 u_char kt_tag;
54 u_char kt_vtype;
55 mode_t kt_mode;
56 } kern_targets[] = {
57 /* NOTE: The name must be less than UIO_MX-16 chars in length */
58 #define N(s) sizeof(s)-1, s
59 /* name data tag type ro/rw */
60 { DT_DIR, N("."), 0, KTT_NULL, VDIR, DIR_MODE },
61 { DT_DIR, N(".."), 0, KTT_NULL, VDIR, DIR_MODE },
62 { DT_REG, N("boottime"), &boottime.tv_sec, KTT_INT, VREG, READ_MODE },
63 { DT_REG, N("copyright"), copyright, KTT_STRING, VREG, READ_MODE },
64 { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE },
65 { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE },
66 { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE },
67 { DT_REG, N("pagesize"), &cnt.v_page_size, KTT_INT, VREG, READ_MODE },
68 { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE },
69 #if 0
70 { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE },
71 #endif
72 { DT_BLK, N("rootdev"), &rootdev, KTT_DEVICE, VBLK, READ_MODE },
73 { DT_CHR, N("rrootdev"), &rrootdev, KTT_DEVICE, VCHR, READ_MODE },
74 { DT_REG, N("time"), 0, KTT_TIME, VREG, READ_MODE },
75 { DT_REG, N("version"), version, KTT_STRING, VREG, READ_MODE },
76 #undef N
77 };
78 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
79
80 static int
kernfs_xread(kt,buf,len,lenp)81 kernfs_xread(kt, buf, len, lenp)
82 struct kern_target *kt;
83 char *buf;
84 int len;
85 int *lenp;
86 {
87
88 switch (kt->kt_tag) {
89 case KTT_TIME: {
90 struct timeval tv;
91 microtime(&tv);
92 sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
93 break;
94 }
95
96 case KTT_INT: {
97 int *ip = kt->kt_data;
98 sprintf(buf, "%d\n", *ip);
99 break;
100 }
101
102 case KTT_STRING: {
103 char *cp = kt->kt_data;
104 int xlen = strlen(cp) + 1;
105
106 if (xlen >= len)
107 return (EINVAL);
108
109 bcopy(cp, buf, xlen);
110 break;
111 }
112
113 case KTT_HOSTNAME: {
114 char *cp = hostname;
115 int xlen = hostnamelen;
116
117 if (xlen >= (len-2))
118 return (EINVAL);
119
120 bcopy(cp, buf, xlen);
121 buf[xlen] = '\n';
122 buf[xlen+1] = '\0';
123 break;
124 }
125
126 case KTT_AVENRUN:
127 sprintf(buf, "%ld %ld %ld %ld\n",
128 averunnable.ldavg[0], averunnable.ldavg[1],
129 averunnable.ldavg[2], averunnable.fscale);
130 break;
131
132 default:
133 return (EIO);
134 }
135
136 *lenp = strlen(buf);
137 return (0);
138 }
139
140 static int
kernfs_xwrite(kt,buf,len)141 kernfs_xwrite(kt, buf, len)
142 struct kern_target *kt;
143 char *buf;
144 int len;
145 {
146
147 switch (kt->kt_tag) {
148 case KTT_HOSTNAME:
149 if (buf[len-1] == '\n')
150 --len;
151 bcopy(buf, hostname, len);
152 hostname[len] = '\0';
153 hostnamelen = len;
154 return (0);
155
156 default:
157 return (EIO);
158 }
159 }
160
161
162 /*
163 * vp is the current namei directory
164 * ndp is the name to locate in that directory...
165 */
166 kernfs_lookup(ap)
167 struct vop_lookup_args /* {
168 struct vnode * a_dvp;
169 struct vnode ** a_vpp;
170 struct componentname * a_cnp;
171 } */ *ap;
172 {
173 struct componentname *cnp = ap->a_cnp;
174 struct vnode **vpp = ap->a_vpp;
175 struct vnode *dvp = ap->a_dvp;
176 char *pname = cnp->cn_nameptr;
177 struct proc *p = cnp->cn_proc;
178 struct kern_target *kt;
179 struct vnode *fvp;
180 int error, i;
181
182 #ifdef KERNFS_DIAGNOSTIC
183 printf("kernfs_lookup(%x)\n", ap);
184 printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp);
185 printf("kernfs_lookup(%s)\n", pname);
186 #endif
187
188 *vpp = NULLVP;
189
190 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
191 return (EROFS);
192
193 VOP_UNLOCK(dvp, 0, p);
194 if (cnp->cn_namelen == 1 && *pname == '.') {
195 *vpp = dvp;
196 VREF(dvp);
197 vn_lock(dvp, LK_SHARED | LK_RETRY, p);
198 return (0);
199 }
200
201 #if 0
202 if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
203 *vpp = rootdir;
204 VREF(rootdir);
205 vn_lock(rootdir, LK_SHARED | LK_RETRY, p)
206 return (0);
207 }
208 #endif
209
210 for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) {
211 if (cnp->cn_namelen == kt->kt_namlen &&
212 bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
213 goto found;
214 }
215
216 #ifdef KERNFS_DIAGNOSTIC
217 printf("kernfs_lookup: i = %d, failed", i);
218 #endif
219
220 vn_lock(dvp, LK_SHARED | LK_RETRY, p);
221 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
222
223 found:
224 if (kt->kt_tag == KTT_DEVICE) {
225 dev_t *dp = kt->kt_data;
226 loop:
227 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
228 vn_lock(dvp, LK_SHARED | LK_RETRY, p);
229 return (ENOENT);
230 }
231 *vpp = fvp;
232 if (vget(fvp, LK_EXCLUSIVE, p))
233 goto loop;
234 return (0);
235 }
236
237 #ifdef KERNFS_DIAGNOSTIC
238 printf("kernfs_lookup: allocate new vnode\n");
239 #endif
240 if (error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p,
241 &fvp)) {
242 vn_lock(dvp, LK_SHARED | LK_RETRY, p);
243 return (error);
244 }
245
246 MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP,
247 M_WAITOK);
248 VTOKERN(fvp)->kf_kt = kt;
249 fvp->v_type = kt->kt_vtype;
250 vn_lock(fvp, LK_SHARED | LK_RETRY, p);
251 *vpp = fvp;
252
253 #ifdef KERNFS_DIAGNOSTIC
254 printf("kernfs_lookup: newvp = %x\n", fvp);
255 #endif
256 return (0);
257 }
258
259 kernfs_open(ap)
260 struct vop_open_args /* {
261 struct vnode *a_vp;
262 int a_mode;
263 struct ucred *a_cred;
264 struct proc *a_p;
265 } */ *ap;
266 {
267
268 /* Only need to check access permissions. */
269 return (0);
270 }
271
272 static int
kernfs_access(ap)273 kernfs_access(ap)
274 struct vop_access_args /* {
275 struct vnode *a_vp;
276 int a_mode;
277 struct ucred *a_cred;
278 struct proc *a_p;
279 } */ *ap;
280 {
281 register struct vnode *vp = ap->a_vp;
282 register struct ucred *cred = ap->a_cred;
283 mode_t amode = ap->a_mode;
284 mode_t fmode =
285 (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode;
286 mode_t mask = 0;
287 register gid_t *gp;
288 int i;
289
290 /* Some files are simply not modifiable. */
291 if ((amode & VWRITE) && (fmode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0)
292 return (EPERM);
293
294 /* Root can do anything else. */
295 if (cred->cr_uid == 0)
296 return (0);
297
298 /* Check for group 0 (wheel) permissions. */
299 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
300 if (*gp == 0) {
301 if (amode & VEXEC)
302 mask |= S_IXGRP;
303 if (amode & VREAD)
304 mask |= S_IRGRP;
305 if (amode & VWRITE)
306 mask |= S_IWGRP;
307 return ((fmode & mask) == mask ? 0 : EACCES);
308 }
309
310 /* Otherwise, check everyone else. */
311 if (amode & VEXEC)
312 mask |= S_IXOTH;
313 if (amode & VREAD)
314 mask |= S_IROTH;
315 if (amode & VWRITE)
316 mask |= S_IWOTH;
317 return ((fmode & mask) == mask ? 0 : EACCES);
318 }
319
320 kernfs_getattr(ap)
321 struct vop_getattr_args /* {
322 struct vnode *a_vp;
323 struct vattr *a_vap;
324 struct ucred *a_cred;
325 struct proc *a_p;
326 } */ *ap;
327 {
328 struct vnode *vp = ap->a_vp;
329 struct vattr *vap = ap->a_vap;
330 struct timeval tv;
331 int error = 0;
332 char strbuf[KSTRING];
333
334 bzero((caddr_t) vap, sizeof(*vap));
335 vattr_null(vap);
336 vap->va_uid = 0;
337 vap->va_gid = 0;
338 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
339 vap->va_size = 0;
340 vap->va_blocksize = DEV_BSIZE;
341 microtime(&tv);
342 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
343 vap->va_mtime = vap->va_atime;
344 vap->va_ctime = vap->va_ctime;
345 vap->va_gen = 0;
346 vap->va_flags = 0;
347 vap->va_rdev = 0;
348 vap->va_bytes = 0;
349
350 if (vp->v_flag & VROOT) {
351 #ifdef KERNFS_DIAGNOSTIC
352 printf("kernfs_getattr: stat rootdir\n");
353 #endif
354 vap->va_type = VDIR;
355 vap->va_mode = DIR_MODE;
356 vap->va_nlink = 2;
357 vap->va_fileid = 2;
358 vap->va_size = DEV_BSIZE;
359 } else {
360 struct kern_target *kt = VTOKERN(vp)->kf_kt;
361 int nbytes;
362 #ifdef KERNFS_DIAGNOSTIC
363 printf("kernfs_getattr: stat target %s\n", kt->kt_name);
364 #endif
365 vap->va_type = kt->kt_vtype;
366 vap->va_mode = kt->kt_mode;
367 vap->va_nlink = 1;
368 vap->va_fileid = 1 + (kt - kern_targets) / sizeof(*kt);
369 error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes);
370 vap->va_size = nbytes;
371 }
372
373 #ifdef KERNFS_DIAGNOSTIC
374 printf("kernfs_getattr: return error %d\n", error);
375 #endif
376 return (error);
377 }
378
379 kernfs_setattr(ap)
380 struct vop_setattr_args /* {
381 struct vnode *a_vp;
382 struct vattr *a_vap;
383 struct ucred *a_cred;
384 struct proc *a_p;
385 } */ *ap;
386 {
387
388 /*
389 * Silently ignore attribute changes.
390 * This allows for open with truncate to have no
391 * effect until some data is written. I want to
392 * do it this way because all writes are atomic.
393 */
394 return (0);
395 }
396
397 static int
kernfs_read(ap)398 kernfs_read(ap)
399 struct vop_read_args /* {
400 struct vnode *a_vp;
401 struct uio *a_uio;
402 int a_ioflag;
403 struct ucred *a_cred;
404 } */ *ap;
405 {
406 struct vnode *vp = ap->a_vp;
407 struct uio *uio = ap->a_uio;
408 struct kern_target *kt;
409 char strbuf[KSTRING];
410 int off = uio->uio_offset;
411 int error, len;
412 char *cp;
413
414 if (vp->v_type == VDIR)
415 return (EOPNOTSUPP);
416
417 kt = VTOKERN(vp)->kf_kt;
418
419 #ifdef KERNFS_DIAGNOSTIC
420 printf("kern_read %s\n", kt->kt_name);
421 #endif
422
423 len = 0;
424 if (error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len))
425 return (error);
426 if (len <= off)
427 return (0);
428 return (uiomove(&strbuf[off], len - off, uio));
429 }
430
431 static int
kernfs_write(ap)432 kernfs_write(ap)
433 struct vop_write_args /* {
434 struct vnode *a_vp;
435 struct uio *a_uio;
436 int a_ioflag;
437 struct ucred *a_cred;
438 } */ *ap;
439 {
440 struct vnode *vp = ap->a_vp;
441 struct uio *uio = ap->a_uio;
442 struct kern_target *kt;
443 int error, xlen;
444 char strbuf[KSTRING];
445
446 if (vp->v_type == VDIR)
447 return (EOPNOTSUPP);
448
449 kt = VTOKERN(vp)->kf_kt;
450
451 if (uio->uio_offset != 0)
452 return (EINVAL);
453
454 xlen = min(uio->uio_resid, KSTRING-1);
455 if (error = uiomove(strbuf, xlen, uio))
456 return (error);
457
458 if (uio->uio_resid != 0)
459 return (EIO);
460
461 strbuf[xlen] = '\0';
462 xlen = strlen(strbuf);
463 return (kernfs_xwrite(kt, strbuf, xlen));
464 }
465
466 kernfs_readdir(ap)
467 struct vop_readdir_args /* {
468 struct vnode *a_vp;
469 struct uio *a_uio;
470 struct ucred *a_cred;
471 int *a_eofflag;
472 u_long *a_cookies;
473 int a_ncookies;
474 } */ *ap;
475 {
476 int error, i;
477 struct uio *uio = ap->a_uio;
478 struct kern_target *kt;
479 struct dirent d;
480
481 if (ap->a_vp->v_type != VDIR)
482 return (ENOTDIR);
483
484 /*
485 * We don't allow exporting kernfs mounts, and currently local
486 * requests do not need cookies.
487 */
488 if (ap->a_ncookies != NULL)
489 panic("kernfs_readdir: not hungry");
490
491 i = uio->uio_offset / UIO_MX;
492 error = 0;
493 for (kt = &kern_targets[i];
494 uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
495 struct dirent *dp = &d;
496 #ifdef KERNFS_DIAGNOSTIC
497 printf("kernfs_readdir: i = %d\n", i);
498 #endif
499
500 if (kt->kt_tag == KTT_DEVICE) {
501 dev_t *dp = kt->kt_data;
502 struct vnode *fvp;
503
504 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
505 continue;
506 }
507
508 bzero((caddr_t)dp, UIO_MX);
509 dp->d_namlen = kt->kt_namlen;
510 bcopy(kt->kt_name, dp->d_name, kt->kt_namlen+1);
511
512 #ifdef KERNFS_DIAGNOSTIC
513 printf("kernfs_readdir: name = %s, len = %d\n",
514 dp->d_name, dp->d_namlen);
515 #endif
516 /*
517 * Fill in the remaining fields
518 */
519 dp->d_reclen = UIO_MX;
520 dp->d_fileno = i + 3;
521 dp->d_type = kt->kt_type;
522 /*
523 * And ship to userland
524 */
525 if (error = uiomove((caddr_t)dp, UIO_MX, uio))
526 break;
527 }
528
529 uio->uio_offset = i * UIO_MX;
530
531 return (error);
532 }
533
534 kernfs_inactive(ap)
535 struct vop_inactive_args /* {
536 struct vnode *a_vp;
537 struct proc *a_p;
538 } */ *ap;
539 {
540 struct vnode *vp = ap->a_vp;
541
542 #ifdef KERNFS_DIAGNOSTIC
543 printf("kernfs_inactive(%x)\n", vp);
544 #endif
545 /*
546 * Clear out the v_type field to avoid
547 * nasty things happening in vgone().
548 */
549 VOP_UNLOCK(vp, 0, ap->a_p);
550 vp->v_type = VNON;
551 return (0);
552 }
553
554 kernfs_reclaim(ap)
555 struct vop_reclaim_args /* {
556 struct vnode *a_vp;
557 } */ *ap;
558 {
559 struct vnode *vp = ap->a_vp;
560
561 #ifdef KERNFS_DIAGNOSTIC
562 printf("kernfs_reclaim(%x)\n", vp);
563 #endif
564 if (vp->v_data) {
565 FREE(vp->v_data, M_TEMP);
566 vp->v_data = 0;
567 }
568 return (0);
569 }
570
571 /*
572 * Return POSIX pathconf information applicable to special devices.
573 */
574 kernfs_pathconf(ap)
575 struct vop_pathconf_args /* {
576 struct vnode *a_vp;
577 int a_name;
578 int *a_retval;
579 } */ *ap;
580 {
581
582 switch (ap->a_name) {
583 case _PC_LINK_MAX:
584 *ap->a_retval = LINK_MAX;
585 return (0);
586 case _PC_MAX_CANON:
587 *ap->a_retval = MAX_CANON;
588 return (0);
589 case _PC_MAX_INPUT:
590 *ap->a_retval = MAX_INPUT;
591 return (0);
592 case _PC_PIPE_BUF:
593 *ap->a_retval = PIPE_BUF;
594 return (0);
595 case _PC_CHOWN_RESTRICTED:
596 *ap->a_retval = 1;
597 return (0);
598 case _PC_VDISABLE:
599 *ap->a_retval = _POSIX_VDISABLE;
600 return (0);
601 default:
602 return (EINVAL);
603 }
604 /* NOTREACHED */
605 }
606
607 /*
608 * Print out the contents of a /dev/fd vnode.
609 */
610 /* ARGSUSED */
611 kernfs_print(ap)
612 struct vop_print_args /* {
613 struct vnode *a_vp;
614 } */ *ap;
615 {
616
617 printf("tag VT_KERNFS, kernfs vnode\n");
618 return (0);
619 }
620
621 /*void*/
622 kernfs_vfree(ap)
623 struct vop_vfree_args /* {
624 struct vnode *a_pvp;
625 ino_t a_ino;
626 int a_mode;
627 } */ *ap;
628 {
629
630 return (0);
631 }
632
633 /*
634 * /dev/fd "should never get here" operation
635 */
kernfs_badop()636 kernfs_badop()
637 {
638
639 panic("kernfs: bad op");
640 /* NOTREACHED */
641 }
642
643 /*
644 * kernfs vnode null operation
645 */
kernfs_nullop()646 kernfs_nullop()
647 {
648
649 return (0);
650 }
651
652 #define kernfs_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
653 #define kernfs_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
654 #define kernfs_close ((int (*) __P((struct vop_close_args *)))nullop)
655 #define kernfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))eopnotsupp)
656 #define kernfs_select ((int (*) __P((struct vop_select_args *)))eopnotsupp)
657 #define kernfs_revoke vop_revoke
658 #define kernfs_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
659 #define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
660 #define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
661 #define kernfs_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
662 #define kernfs_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
663 #define kernfs_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
664 #define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
665 #define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
666 #define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
667 #define kernfs_readlink ((int (*) __P((struct vop_readlink_args *)))eopnotsupp)
668 #define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
669 #define kernfs_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
670 #define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
671 #define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop)
672 #define kernfs_strategy \
673 ((int (*) __P((struct vop_strategy_args *)))kernfs_badop)
674 #define kernfs_islocked \
675 ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
676 #define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
677 #define kernfs_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
678 #define kernfs_valloc ((int(*) __P(( \
679 struct vnode *pvp, \
680 int mode, \
681 struct ucred *cred, \
682 struct vnode **vpp))) eopnotsupp)
683 #define kernfs_truncate ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
684 #define kernfs_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
685 #define kernfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
686
687 int (**kernfs_vnodeop_p)();
688 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
689 { &vop_default_desc, vn_default_error },
690 { &vop_lookup_desc, kernfs_lookup }, /* lookup */
691 { &vop_create_desc, kernfs_create }, /* create */
692 { &vop_mknod_desc, kernfs_mknod }, /* mknod */
693 { &vop_open_desc, kernfs_open }, /* open */
694 { &vop_close_desc, kernfs_close }, /* close */
695 { &vop_access_desc, kernfs_access }, /* access */
696 { &vop_getattr_desc, kernfs_getattr }, /* getattr */
697 { &vop_setattr_desc, kernfs_setattr }, /* setattr */
698 { &vop_read_desc, kernfs_read }, /* read */
699 { &vop_write_desc, kernfs_write }, /* write */
700 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
701 { &vop_select_desc, kernfs_select }, /* select */
702 { &vop_revoke_desc, kernfs_revoke }, /* revoke */
703 { &vop_mmap_desc, kernfs_mmap }, /* mmap */
704 { &vop_fsync_desc, kernfs_fsync }, /* fsync */
705 { &vop_seek_desc, kernfs_seek }, /* seek */
706 { &vop_remove_desc, kernfs_remove }, /* remove */
707 { &vop_link_desc, kernfs_link }, /* link */
708 { &vop_rename_desc, kernfs_rename }, /* rename */
709 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
710 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
711 { &vop_symlink_desc, kernfs_symlink }, /* symlink */
712 { &vop_readdir_desc, kernfs_readdir }, /* readdir */
713 { &vop_readlink_desc, kernfs_readlink },/* readlink */
714 { &vop_abortop_desc, kernfs_abortop }, /* abortop */
715 { &vop_inactive_desc, kernfs_inactive },/* inactive */
716 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
717 { &vop_lock_desc, kernfs_lock }, /* lock */
718 { &vop_unlock_desc, kernfs_unlock }, /* unlock */
719 { &vop_bmap_desc, kernfs_bmap }, /* bmap */
720 { &vop_strategy_desc, kernfs_strategy },/* strategy */
721 { &vop_print_desc, kernfs_print }, /* print */
722 { &vop_islocked_desc, kernfs_islocked },/* islocked */
723 { &vop_pathconf_desc, kernfs_pathconf },/* pathconf */
724 { &vop_advlock_desc, kernfs_advlock }, /* advlock */
725 { &vop_blkatoff_desc, kernfs_blkatoff },/* blkatoff */
726 { &vop_valloc_desc, kernfs_valloc }, /* valloc */
727 { &vop_vfree_desc, kernfs_vfree }, /* vfree */
728 { &vop_truncate_desc, kernfs_truncate },/* truncate */
729 { &vop_update_desc, kernfs_update }, /* update */
730 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
731 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
732 };
733 struct vnodeopv_desc kernfs_vnodeop_opv_desc =
734 { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
735