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