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