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