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