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.3 (Berkeley) 01/04/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  * Print out the contents of a /dev/fd vnode.
565  */
566 /* ARGSUSED */
567 kernfs_print(ap)
568 	struct vop_print_args /* {
569 		struct vnode *a_vp;
570 	} */ *ap;
571 {
572 
573 	printf("tag VT_KERNFS, kernfs vnode\n");
574 	return (0);
575 }
576 
577 /*void*/
578 kernfs_vfree(ap)
579 	struct vop_vfree_args /* {
580 		struct vnode *a_pvp;
581 		ino_t a_ino;
582 		int a_mode;
583 	} */ *ap;
584 {
585 
586 	return (0);
587 }
588 
589 /*
590  * /dev/fd vnode unsupported operation
591  */
592 kernfs_enotsupp()
593 {
594 
595 	return (EOPNOTSUPP);
596 }
597 
598 /*
599  * /dev/fd "should never get here" operation
600  */
601 kernfs_badop()
602 {
603 
604 	panic("kernfs: bad op");
605 	/* NOTREACHED */
606 }
607 
608 /*
609  * kernfs vnode null operation
610  */
611 kernfs_nullop()
612 {
613 
614 	return (0);
615 }
616 
617 #define kernfs_create ((int (*) __P((struct  vop_create_args *)))kernfs_enotsupp)
618 #define kernfs_mknod ((int (*) __P((struct  vop_mknod_args *)))kernfs_enotsupp)
619 #define kernfs_close ((int (*) __P((struct  vop_close_args *)))nullop)
620 #define kernfs_ioctl ((int (*) __P((struct  vop_ioctl_args *)))kernfs_enotsupp)
621 #define kernfs_select ((int (*) __P((struct  vop_select_args *)))kernfs_enotsupp)
622 #define kernfs_mmap ((int (*) __P((struct  vop_mmap_args *)))kernfs_enotsupp)
623 #define kernfs_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
624 #define kernfs_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
625 #define kernfs_remove ((int (*) __P((struct  vop_remove_args *)))kernfs_enotsupp)
626 #define kernfs_link ((int (*) __P((struct  vop_link_args *)))kernfs_enotsupp)
627 #define kernfs_rename ((int (*) __P((struct  vop_rename_args *)))kernfs_enotsupp)
628 #define kernfs_mkdir ((int (*) __P((struct  vop_mkdir_args *)))kernfs_enotsupp)
629 #define kernfs_rmdir ((int (*) __P((struct  vop_rmdir_args *)))kernfs_enotsupp)
630 #define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp)
631 #define kernfs_readlink \
632 	((int (*) __P((struct  vop_readlink_args *)))kernfs_enotsupp)
633 #define kernfs_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
634 #define kernfs_lock ((int (*) __P((struct  vop_lock_args *)))nullop)
635 #define kernfs_unlock ((int (*) __P((struct  vop_unlock_args *)))nullop)
636 #define kernfs_bmap ((int (*) __P((struct  vop_bmap_args *)))kernfs_badop)
637 #define kernfs_strategy ((int (*) __P((struct  vop_strategy_args *)))kernfs_badop)
638 #define kernfs_islocked ((int (*) __P((struct  vop_islocked_args *)))nullop)
639 #define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp)
640 #define kernfs_blkatoff \
641 	((int (*) __P((struct  vop_blkatoff_args *)))kernfs_enotsupp)
642 #define kernfs_valloc ((int(*) __P(( \
643 		struct vnode *pvp, \
644 		int mode, \
645 		struct ucred *cred, \
646 		struct vnode **vpp))) kernfs_enotsupp)
647 #define kernfs_truncate \
648 	((int (*) __P((struct  vop_truncate_args *)))kernfs_enotsupp)
649 #define kernfs_update ((int (*) __P((struct  vop_update_args *)))kernfs_enotsupp)
650 #define kernfs_bwrite ((int (*) __P((struct  vop_bwrite_args *)))kernfs_enotsupp)
651 
652 int (**kernfs_vnodeop_p)();
653 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
654 	{ &vop_default_desc, vn_default_error },
655 	{ &vop_lookup_desc, kernfs_lookup },	/* lookup */
656 	{ &vop_create_desc, kernfs_create },	/* create */
657 	{ &vop_mknod_desc, kernfs_mknod },	/* mknod */
658 	{ &vop_open_desc, kernfs_open },		/* open */
659 	{ &vop_close_desc, kernfs_close },	/* close */
660 	{ &vop_access_desc, kernfs_access },	/* access */
661 	{ &vop_getattr_desc, kernfs_getattr },	/* getattr */
662 	{ &vop_setattr_desc, kernfs_setattr },	/* setattr */
663 	{ &vop_read_desc, kernfs_read },		/* read */
664 	{ &vop_write_desc, kernfs_write },	/* write */
665 	{ &vop_ioctl_desc, kernfs_ioctl },	/* ioctl */
666 	{ &vop_select_desc, kernfs_select },	/* select */
667 	{ &vop_mmap_desc, kernfs_mmap },		/* mmap */
668 	{ &vop_fsync_desc, kernfs_fsync },	/* fsync */
669 	{ &vop_seek_desc, kernfs_seek },		/* seek */
670 	{ &vop_remove_desc, kernfs_remove },	/* remove */
671 	{ &vop_link_desc, kernfs_link },		/* link */
672 	{ &vop_rename_desc, kernfs_rename },	/* rename */
673 	{ &vop_mkdir_desc, kernfs_mkdir },	/* mkdir */
674 	{ &vop_rmdir_desc, kernfs_rmdir },	/* rmdir */
675 	{ &vop_symlink_desc, kernfs_symlink },	/* symlink */
676 	{ &vop_readdir_desc, kernfs_readdir },	/* readdir */
677 	{ &vop_readlink_desc, kernfs_readlink },	/* readlink */
678 	{ &vop_abortop_desc, kernfs_abortop },	/* abortop */
679 	{ &vop_inactive_desc, kernfs_inactive },	/* inactive */
680 	{ &vop_reclaim_desc, kernfs_reclaim },	/* reclaim */
681 	{ &vop_lock_desc, kernfs_lock },		/* lock */
682 	{ &vop_unlock_desc, kernfs_unlock },	/* unlock */
683 	{ &vop_bmap_desc, kernfs_bmap },		/* bmap */
684 	{ &vop_strategy_desc, kernfs_strategy },	/* strategy */
685 	{ &vop_print_desc, kernfs_print },	/* print */
686 	{ &vop_islocked_desc, kernfs_islocked },	/* islocked */
687 	{ &vop_advlock_desc, kernfs_advlock },	/* advlock */
688 	{ &vop_blkatoff_desc, kernfs_blkatoff },	/* blkatoff */
689 	{ &vop_valloc_desc, kernfs_valloc },	/* valloc */
690 	{ &vop_vfree_desc, kernfs_vfree },	/* vfree */
691 	{ &vop_truncate_desc, kernfs_truncate },	/* truncate */
692 	{ &vop_update_desc, kernfs_update },	/* update */
693 	{ &vop_bwrite_desc, kernfs_bwrite },	/* bwrite */
694 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
695 };
696 struct vnodeopv_desc kernfs_vnodeop_opv_desc =
697 	{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
698