1 /*
2  * Copyright (c) 1992 The Regents of the University of California
3  * Copyright (c) 1990, 1992 Jan-Simon Pendry
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	7.7 (Berkeley) 10/09/92
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 	{ "root",	0,		KTT_NULL,	VREAD,		VDIR },
67 	{ "rootdev",	0,		KTT_NULL,	VREAD,		VBLK },
68 	{ "rrootdev",	0,		KTT_NULL,	VREAD,		VCHR },
69 	{ "time",	0,		KTT_TIME,	VREAD,		VREG },
70 	{ "version",	version,	KTT_STRING,	VREAD,		VREG },
71 };
72 
73 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
74 
75 static int
76 kernfs_xread(kt, buf, len, lenp)
77 	struct kern_target *kt;
78 	char *buf;
79 	int len;
80 	int *lenp;
81 {
82 	int xlen;
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)
114 			return (EINVAL);
115 
116 		sprintf(buf, "%s\n", cp);
117 		break;
118 	}
119 
120 	case KTT_AVENRUN:
121 		sprintf(buf, "%ld %ld %ld %ld\n",
122 				averunnable.ldavg[0],
123 				averunnable.ldavg[1],
124 				averunnable.ldavg[2],
125 				averunnable.fscale);
126 		break;
127 
128 	default:
129 		return (EINVAL);
130 	}
131 
132 	*lenp = strlen(buf);
133 	return (0);
134 }
135 
136 static int
137 kernfs_xwrite(kt, buf, len)
138 	struct kern_target *kt;
139 	char *buf;
140 	int len;
141 {
142 	switch (kt->kt_tag) {
143 	case KTT_HOSTNAME: {
144 		if (buf[len-1] == '\n')
145 			--len;
146 		bcopy(buf, hostname, len);
147 		hostnamelen = len - 1;
148 		return (0);
149 	}
150 
151 	default:
152 		return (EIO);
153 	}
154 }
155 
156 
157 /*
158  * vp is the current namei directory
159  * ndp is the name to locate in that directory...
160  */
161 kernfs_lookup(ap)
162 	struct vop_lookup_args /* {
163 		struct vnode * a_dvp;
164 		struct vnode ** a_vpp;
165 		struct componentname * a_cnp;
166 	} */ *ap;
167 {
168 	struct vnode **vpp = ap->a_vpp;
169 	struct vnode *dvp = ap->a_dvp;
170 	struct componentname *cnp = ap->a_cnp;
171 	char *pname;
172 	struct proc *p;
173 	int error;
174 	struct vnode *fvp;
175 	int i;
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 (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
193 		*vpp = rootdir;
194 		VREF(rootdir);
195 		VOP_LOCK(rootdir);
196 		return (0);
197 	}
198 
199 	/*
200 	 * /kern/rootdev is the root device
201 	 */
202 	if (cnp->cn_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
203 		*vpp = rootvp;
204 		VREF(rootvp);
205 		VOP_LOCK(rootvp);
206 		return (0);
207 	}
208 
209 	/*
210 	 * /kern/rrootdev is the raw root device
211 	 */
212 	if (cnp->cn_namelen == 8 && bcmp(pname, "rrootdev", 8) == 0) {
213 		if (rrootvp) {
214 			*vpp = rrootvp;
215 			VREF(rrootvp);
216 			VOP_LOCK(rrootvp);
217 			return (0);
218 		}
219 		error = ENXIO;
220 		goto bad;
221 	}
222 
223 	error = ENOENT;
224 
225 	for (i = 0; i < nkern_targets; i++) {
226 		struct kern_target *kt = &kern_targets[i];
227 		if (cnp->cn_namelen == strlen(kt->kt_name) &&
228 		    bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) {
229 			error = 0;
230 			break;
231 		}
232 	}
233 
234 #ifdef KERNFS_DIAGNOSTIC
235 	printf("kernfs_lookup: i = %d, error = %d\n", i, error);
236 #endif
237 
238 	if (error)
239 		goto bad;
240 
241 #ifdef KERNFS_DIAGNOSTIC
242 	printf("kernfs_lookup: allocate new vnode\n");
243 #endif
244 	error = getnewvnode(VT_UFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
245 	if (error)
246 		goto bad;
247 	MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK);
248 	VTOKERN(fvp)->kf_kt = &kern_targets[i];
249 	fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
250 	*vpp = fvp;
251 #ifdef KERNFS_DIAGNOSTIC
252 	printf("kernfs_lookup: newvp = %x\n", fvp);
253 #endif
254 	return (0);
255 
256 bad:;
257 	*vpp = NULL;
258 #ifdef KERNFS_DIAGNOSTIC
259 	printf("kernfs_lookup: error = %d\n", error);
260 #endif
261 	return (error);
262 }
263 
264 kernfs_open(ap)
265 	struct vop_open_args /* {
266 		struct vnode *a_vp;
267 		int  a_mode;
268 		struct ucred *a_cred;
269 		struct proc *a_p;
270 	} */ *ap;
271 {
272 	struct vnode *vp = ap->a_vp;
273 
274 	/*
275 	 * Can always open the root (modulo perms)
276 	 */
277 	if (vp->v_flag & VROOT)
278 		return (0);
279 
280 #ifdef KERNFS_DIAGNOSTIC
281 	printf("kernfs_open, mode = %x, file = %s\n",
282 			ap->a_mode, VTOKERN(vp)->kf_kt->kt_name);
283 #endif
284 
285 	if ((ap->a_mode & FWRITE) && !(VTOKERN(vp)->kf_kt->kt_rw & VWRITE))
286 		return (EBADF);
287 
288 	return (0);
289 }
290 
291 static int
292 kernfs_access(ap)
293 	struct vop_access_args /* {
294 		struct vnode *a_vp;
295 		int  a_mode;
296 		struct ucred *a_cred;
297 		struct proc *a_p;
298 	} */ *ap;
299 {
300 	struct vnode *vp = ap->a_vp;
301 	struct ucred *cred = ap->a_cred;
302 	mode_t mode = ap->a_mode;
303 
304 	if (mode & VEXEC) {
305 		if (vp->v_flag & VROOT)
306 			return (0);
307 		return (EACCES);
308 	}
309 
310 	if (cred->cr_uid == 0) {
311 		if ((vp->v_flag & VROOT) == 0) {
312 			struct kern_target *kt = VTOKERN(vp)->kf_kt;
313 
314 			if ((mode & VWRITE) && !(kt->kt_rw & VWRITE))
315 				return (EROFS);
316 		}
317 		return (0);
318 	}
319 
320 	if (mode & VWRITE)
321 		return (EACCES);
322 
323 	return (0);
324 }
325 
326 
327 kernfs_getattr(ap)
328 	struct vop_getattr_args /* {
329 		struct vnode *a_vp;
330 		struct vattr *a_vap;
331 		struct ucred *a_cred;
332 		struct proc *a_p;
333 	} */ *ap;
334 {
335 	struct vnode *vp = ap->a_vp;
336 	struct vattr *vap = ap->a_vap;
337 	int error = 0;
338 	char strbuf[KSTRING];
339 
340 	bzero((caddr_t) vap, sizeof(*vap));
341 	vattr_null(vap);
342 	vap->va_uid = 0;
343 	vap->va_gid = 0;
344 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
345 	/* vap->va_qsize = 0; */
346 	vap->va_blocksize = DEV_BSIZE;
347 	microtime(&vap->va_atime);
348 	vap->va_mtime = vap->va_atime;
349 	vap->va_ctime = vap->va_ctime;
350 	vap->va_gen = 0;
351 	vap->va_flags = 0;
352 	vap->va_rdev = 0;
353 	/* vap->va_qbytes = 0; */
354 	vap->va_bytes = 0;
355 
356 	if (vp->v_flag & VROOT) {
357 #ifdef KERNFS_DIAGNOSTIC
358 		printf("kernfs_getattr: stat rootdir\n");
359 #endif
360 		vap->va_type = VDIR;
361 		vap->va_mode = DIR_MODE;
362 		vap->va_nlink = 2;
363 		vap->va_fileid = 2;
364 		vap->va_size = DEV_BSIZE;
365 	} else {
366 		struct kern_target *kt = VTOKERN(vp)->kf_kt;
367 		int nbytes;
368 #ifdef KERNFS_DIAGNOSTIC
369 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
370 #endif
371 		vap->va_type = kt->kt_vtype;
372 		vap->va_mode = (kt->kt_rw & VWRITE ? WRITE_MODE : READ_MODE);
373 		vap->va_nlink = 1;
374 		vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
375 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes);
376 		vap->va_size = nbytes;
377 	}
378 
379 	vp->v_type = vap->va_type;
380 #ifdef KERNFS_DIAGNOSTIC
381 	printf("kernfs_getattr: return error %d\n", error);
382 #endif
383 	return (error);
384 }
385 
386 kernfs_setattr(ap)
387 	struct vop_setattr_args /* {
388 		struct vnode *a_vp;
389 		struct vattr *a_vap;
390 		struct ucred *a_cred;
391 		struct proc *a_p;
392 	} */ *ap;
393 {
394 
395 	/*
396 	 * Silently ignore attribute changes.
397 	 * This allows for open with truncate to have no
398 	 * effect until some data is written.  I want to
399 	 * do it this way because all writes are atomic.
400 	 */
401 	return (0);
402 }
403 
404 static int
405 kernfs_read(ap)
406 	struct vop_read_args /* {
407 		struct vnode *a_vp;
408 		struct uio *a_uio;
409 		int  a_ioflag;
410 		struct ucred *a_cred;
411 	} */ *ap;
412 {
413 	struct vnode *vp = ap->a_vp;
414 	struct uio *uio = ap->a_uio;
415 	struct kern_target *kt;
416 	char strbuf[KSTRING];
417 	int off = uio->uio_offset;
418 	int len = 0;
419 	char *cp = strbuf;
420 	int error;
421 
422 	if (vp->v_flag & VROOT)
423 		return (0);
424 
425 	kt = VTOKERN(vp)->kf_kt;
426 
427 #ifdef KERNFS_DIAGNOSTIC
428 	printf("kern_read %s\n", kt->kt_name);
429 #endif
430 
431 	error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
432 	if (error)
433 		return (error);
434 	cp = strbuf + off;
435 	len -= off;
436 	return (uiomove(cp, len, uio));
437 }
438 
439 static int
440 kernfs_write(ap)
441 	struct vop_write_args /* {
442 		struct vnode *a_vp;
443 		struct uio *a_uio;
444 		int  a_ioflag;
445 		struct ucred *a_cred;
446 	} */ *ap;
447 {
448 	struct vnode *vp = ap->a_vp;
449 	struct uio *uio = ap->a_uio;
450 	struct kern_target *kt;
451 	char strbuf[KSTRING];
452 	int len = uio->uio_resid;
453 	char *cp = strbuf;
454 	int xlen;
455 	int error;
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 	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 	printf("kernfs_reclaim(%x)\n", vp);
553 	if (vp->v_data) {
554 		FREE(vp->v_data, M_TEMP);
555 		vp->v_data = 0;
556 	}
557 	return (0);
558 }
559 
560 /*
561  * Print out the contents of a /dev/fd vnode.
562  */
563 /* ARGSUSED */
564 kernfs_print(ap)
565 	struct vop_print_args /* {
566 		struct vnode *a_vp;
567 	} */ *ap;
568 {
569 
570 	printf("tag VT_NON, kernfs vnode\n");
571 	return (0);
572 }
573 
574 /*void*/
575 kernfs_vfree(ap)
576 	struct vop_vfree_args /* {
577 		struct vnode *a_pvp;
578 		ino_t a_ino;
579 		int a_mode;
580 	} */ *ap;
581 {
582 
583 	return (0);
584 }
585 
586 /*
587  * /dev/fd vnode unsupported operation
588  */
589 kernfs_enotsupp()
590 {
591 
592 	return (EOPNOTSUPP);
593 }
594 
595 /*
596  * /dev/fd "should never get here" operation
597  */
598 kernfs_badop()
599 {
600 
601 	panic("kernfs: bad op");
602 	/* NOTREACHED */
603 }
604 
605 /*
606  * kernfs vnode null operation
607  */
608 kernfs_nullop()
609 {
610 
611 	return (0);
612 }
613 
614 #define kernfs_create ((int (*) __P((struct  vop_create_args *)))kernfs_enotsupp)
615 #define kernfs_mknod ((int (*) __P((struct  vop_mknod_args *)))kernfs_enotsupp)
616 #define kernfs_close ((int (*) __P((struct  vop_close_args *)))nullop)
617 #define kernfs_ioctl ((int (*) __P((struct  vop_ioctl_args *)))kernfs_enotsupp)
618 #define kernfs_select ((int (*) __P((struct  vop_select_args *)))kernfs_enotsupp)
619 #define kernfs_mmap ((int (*) __P((struct  vop_mmap_args *)))kernfs_enotsupp)
620 #define kernfs_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
621 #define kernfs_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
622 #define kernfs_remove ((int (*) __P((struct  vop_remove_args *)))kernfs_enotsupp)
623 #define kernfs_link ((int (*) __P((struct  vop_link_args *)))kernfs_enotsupp)
624 #define kernfs_rename ((int (*) __P((struct  vop_rename_args *)))kernfs_enotsupp)
625 #define kernfs_mkdir ((int (*) __P((struct  vop_mkdir_args *)))kernfs_enotsupp)
626 #define kernfs_rmdir ((int (*) __P((struct  vop_rmdir_args *)))kernfs_enotsupp)
627 #define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp)
628 #define kernfs_readlink \
629 	((int (*) __P((struct  vop_readlink_args *)))kernfs_enotsupp)
630 #define kernfs_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
631 #define kernfs_lock ((int (*) __P((struct  vop_lock_args *)))nullop)
632 #define kernfs_unlock ((int (*) __P((struct  vop_unlock_args *)))nullop)
633 #define kernfs_bmap ((int (*) __P((struct  vop_bmap_args *)))kernfs_badop)
634 #define kernfs_strategy ((int (*) __P((struct  vop_strategy_args *)))kernfs_badop)
635 #define kernfs_islocked ((int (*) __P((struct  vop_islocked_args *)))nullop)
636 #define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp)
637 #define kernfs_blkatoff \
638 	((int (*) __P((struct  vop_blkatoff_args *)))kernfs_enotsupp)
639 #define kernfs_valloc ((int(*) __P(( \
640 		struct vnode *pvp, \
641 		int mode, \
642 		struct ucred *cred, \
643 		struct vnode **vpp))) kernfs_enotsupp)
644 #define kernfs_truncate \
645 	((int (*) __P((struct  vop_truncate_args *)))kernfs_enotsupp)
646 #define kernfs_update ((int (*) __P((struct  vop_update_args *)))kernfs_enotsupp)
647 #define kernfs_bwrite ((int (*) __P((struct  vop_bwrite_args *)))kernfs_enotsupp)
648 
649 int (**kernfs_vnodeop_p)();
650 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
651 	{ &vop_default_desc, vn_default_error },
652 	{ &vop_lookup_desc, kernfs_lookup },	/* lookup */
653 	{ &vop_create_desc, kernfs_create },	/* create */
654 	{ &vop_mknod_desc, kernfs_mknod },	/* mknod */
655 	{ &vop_open_desc, kernfs_open },		/* open */
656 	{ &vop_close_desc, kernfs_close },	/* close */
657 	{ &vop_access_desc, kernfs_access },	/* access */
658 	{ &vop_getattr_desc, kernfs_getattr },	/* getattr */
659 	{ &vop_setattr_desc, kernfs_setattr },	/* setattr */
660 	{ &vop_read_desc, kernfs_read },		/* read */
661 	{ &vop_write_desc, kernfs_write },	/* write */
662 	{ &vop_ioctl_desc, kernfs_ioctl },	/* ioctl */
663 	{ &vop_select_desc, kernfs_select },	/* select */
664 	{ &vop_mmap_desc, kernfs_mmap },		/* mmap */
665 	{ &vop_fsync_desc, kernfs_fsync },	/* fsync */
666 	{ &vop_seek_desc, kernfs_seek },		/* seek */
667 	{ &vop_remove_desc, kernfs_remove },	/* remove */
668 	{ &vop_link_desc, kernfs_link },		/* link */
669 	{ &vop_rename_desc, kernfs_rename },	/* rename */
670 	{ &vop_mkdir_desc, kernfs_mkdir },	/* mkdir */
671 	{ &vop_rmdir_desc, kernfs_rmdir },	/* rmdir */
672 	{ &vop_symlink_desc, kernfs_symlink },	/* symlink */
673 	{ &vop_readdir_desc, kernfs_readdir },	/* readdir */
674 	{ &vop_readlink_desc, kernfs_readlink },	/* readlink */
675 	{ &vop_abortop_desc, kernfs_abortop },	/* abortop */
676 	{ &vop_inactive_desc, kernfs_inactive },	/* inactive */
677 	{ &vop_reclaim_desc, kernfs_reclaim },	/* reclaim */
678 	{ &vop_lock_desc, kernfs_lock },		/* lock */
679 	{ &vop_unlock_desc, kernfs_unlock },	/* unlock */
680 	{ &vop_bmap_desc, kernfs_bmap },		/* bmap */
681 	{ &vop_strategy_desc, kernfs_strategy },	/* strategy */
682 	{ &vop_print_desc, kernfs_print },	/* print */
683 	{ &vop_islocked_desc, kernfs_islocked },	/* islocked */
684 	{ &vop_advlock_desc, kernfs_advlock },	/* advlock */
685 	{ &vop_blkatoff_desc, kernfs_blkatoff },	/* blkatoff */
686 	{ &vop_valloc_desc, kernfs_valloc },	/* valloc */
687 	{ &vop_vfree_desc, kernfs_vfree },	/* vfree */
688 	{ &vop_truncate_desc, kernfs_truncate },	/* truncate */
689 	{ &vop_update_desc, kernfs_update },	/* update */
690 	{ &vop_bwrite_desc, kernfs_bwrite },	/* bwrite */
691 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
692 };
693 struct vnodeopv_desc kernfs_vnodeop_opv_desc =
694 	{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
695