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