1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software donated to Berkeley by
6  * Jan-Simon Pendry.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)kernfs_vnops.c	8.14 (Berkeley) 05/21/95
11  */
12 
13 /*
14  * Kernel parameter filesystem (/kern)
15  */
16 
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/kernel.h>
20 #include <sys/vmmeter.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/proc.h>
24 #include <sys/vnode.h>
25 #include <sys/malloc.h>
26 #include <sys/file.h>
27 #include <sys/stat.h>
28 #include <sys/mount.h>
29 #include <sys/namei.h>
30 #include <sys/buf.h>
31 #include <sys/dirent.h>
32 #include <miscfs/kernfs/kernfs.h>
33 
34 #define KSTRING	256		/* Largest I/O available via this filesystem */
35 #define	UIO_MX 32
36 
37 #define	READ_MODE	(S_IRUSR|S_IRGRP|S_IROTH)
38 #define	WRITE_MODE	(S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
39 #define DIR_MODE	(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
40 
41 struct kern_target {
42 	u_char kt_type;
43 	u_char kt_namlen;
44 	char *kt_name;
45 	void *kt_data;
46 #define	KTT_NULL	 1
47 #define	KTT_TIME	 5
48 #define KTT_INT		17
49 #define	KTT_STRING	31
50 #define KTT_HOSTNAME	47
51 #define KTT_AVENRUN	53
52 #define KTT_DEVICE	71
53 	u_char kt_tag;
54 	u_char kt_vtype;
55 	mode_t kt_mode;
56 } kern_targets[] = {
57 /* NOTE: The name must be less than UIO_MX-16 chars in length */
58 #define N(s) sizeof(s)-1, s
59      /*        name            data          tag           type  ro/rw */
60      { DT_DIR, N("."),         0,            KTT_NULL,     VDIR, DIR_MODE   },
61      { DT_DIR, N(".."),        0,            KTT_NULL,     VDIR, DIR_MODE   },
62      { DT_REG, N("boottime"),  &boottime.tv_sec, KTT_INT,  VREG, READ_MODE  },
63      { DT_REG, N("copyright"), copyright,    KTT_STRING,   VREG, READ_MODE  },
64      { DT_REG, N("hostname"),  0,            KTT_HOSTNAME, VREG, WRITE_MODE },
65      { DT_REG, N("hz"),        &hz,          KTT_INT,      VREG, READ_MODE  },
66      { DT_REG, N("loadavg"),   0,            KTT_AVENRUN,  VREG, READ_MODE  },
67      { DT_REG, N("pagesize"),  &cnt.v_page_size, KTT_INT,  VREG, READ_MODE  },
68      { DT_REG, N("physmem"),   &physmem,     KTT_INT,      VREG, READ_MODE  },
69 #if 0
70      { DT_DIR, N("root"),      0,            KTT_NULL,     VDIR, DIR_MODE   },
71 #endif
72      { DT_BLK, N("rootdev"),   &rootdev,     KTT_DEVICE,   VBLK, READ_MODE  },
73      { DT_CHR, N("rrootdev"),  &rrootdev,    KTT_DEVICE,   VCHR, READ_MODE  },
74      { DT_REG, N("time"),      0,            KTT_TIME,     VREG, READ_MODE  },
75      { DT_REG, N("version"),   version,      KTT_STRING,   VREG, READ_MODE  },
76 #undef N
77 };
78 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
79 
80 static int
81 kernfs_xread(kt, buf, len, lenp)
82 	struct kern_target *kt;
83 	char *buf;
84 	int len;
85 	int *lenp;
86 {
87 
88 	switch (kt->kt_tag) {
89 	case KTT_TIME: {
90 		struct timeval tv;
91 		microtime(&tv);
92 		sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
93 		break;
94 	}
95 
96 	case KTT_INT: {
97 		int *ip = kt->kt_data;
98 		sprintf(buf, "%d\n", *ip);
99 		break;
100 	}
101 
102 	case KTT_STRING: {
103 		char *cp = kt->kt_data;
104 		int xlen = strlen(cp) + 1;
105 
106 		if (xlen >= len)
107 			return (EINVAL);
108 
109 		bcopy(cp, buf, xlen);
110 		break;
111 	}
112 
113 	case KTT_HOSTNAME: {
114 		char *cp = hostname;
115 		int xlen = hostnamelen;
116 
117 		if (xlen >= (len-2))
118 			return (EINVAL);
119 
120 		bcopy(cp, buf, xlen);
121 		buf[xlen] = '\n';
122 		buf[xlen+1] = '\0';
123 		break;
124 	}
125 
126 	case KTT_AVENRUN:
127 		sprintf(buf, "%ld %ld %ld %ld\n",
128 		    averunnable.ldavg[0], averunnable.ldavg[1],
129 		    averunnable.ldavg[2], averunnable.fscale);
130 		break;
131 
132 	default:
133 		return (EIO);
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 
147 	switch (kt->kt_tag) {
148 	case KTT_HOSTNAME:
149 		if (buf[len-1] == '\n')
150 			--len;
151 		bcopy(buf, hostname, len);
152 		hostname[len] = '\0';
153 		hostnamelen = len;
154 		return (0);
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 componentname *cnp = ap->a_cnp;
174 	struct vnode **vpp = ap->a_vpp;
175 	struct vnode *dvp = ap->a_dvp;
176 	char *pname = cnp->cn_nameptr;
177 	struct proc *p = cnp->cn_proc;
178 	struct kern_target *kt;
179 	struct vnode *fvp;
180 	int error, 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 	printf("kernfs_lookup(%s)\n", pname);
186 #endif
187 
188 	*vpp = NULLVP;
189 
190 	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
191 		return (EROFS);
192 
193 	if (cnp->cn_namelen == 1 && *pname == '.') {
194 		*vpp = dvp;
195 		VREF(dvp);
196 		/*VOP_LOCK(dvp);*/
197 		return (0);
198 	}
199 
200 #if 0
201 	if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
202 		*vpp = rootdir;
203 		VREF(rootdir);
204 		vn_lock(rootdir, LK_EXCLUSIVE | LK_RETRY, p)
205 		return (0);
206 	}
207 #endif
208 
209 	for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) {
210 		if (cnp->cn_namelen == kt->kt_namlen &&
211 		    bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
212 			goto found;
213 	}
214 
215 #ifdef KERNFS_DIAGNOSTIC
216 	printf("kernfs_lookup: i = %d, failed", i);
217 #endif
218 
219 	return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
220 
221 found:
222 	if (kt->kt_tag == KTT_DEVICE) {
223 		dev_t *dp = kt->kt_data;
224 	loop:
225 		if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
226 			return (ENOENT);
227 		*vpp = fvp;
228 		if (vget(fvp, LK_EXCLUSIVE, p))
229 			goto loop;
230 		return (0);
231 	}
232 
233 #ifdef KERNFS_DIAGNOSTIC
234 	printf("kernfs_lookup: allocate new vnode\n");
235 #endif
236 	if (error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p,
237 	    &fvp))
238 		return (error);
239 
240 	MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP,
241 	    M_WAITOK);
242 	VTOKERN(fvp)->kf_kt = kt;
243 	fvp->v_type = kt->kt_vtype;
244 	*vpp = fvp;
245 
246 #ifdef KERNFS_DIAGNOSTIC
247 	printf("kernfs_lookup: newvp = %x\n", fvp);
248 #endif
249 	return (0);
250 }
251 
252 kernfs_open(ap)
253 	struct vop_open_args /* {
254 		struct vnode *a_vp;
255 		int  a_mode;
256 		struct ucred *a_cred;
257 		struct proc *a_p;
258 	} */ *ap;
259 {
260 
261 	/* Only need to check access permissions. */
262 	return (0);
263 }
264 
265 static int
266 kernfs_access(ap)
267 	struct vop_access_args /* {
268 		struct vnode *a_vp;
269 		int  a_mode;
270 		struct ucred *a_cred;
271 		struct proc *a_p;
272 	} */ *ap;
273 {
274 	register struct vnode *vp = ap->a_vp;
275 	register struct ucred *cred = ap->a_cred;
276 	mode_t amode = ap->a_mode;
277 	mode_t fmode =
278 	    (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode;
279 	mode_t mask = 0;
280 	register gid_t *gp;
281 	int i;
282 
283 	/* Some files are simply not modifiable. */
284 	if ((amode & VWRITE) && (fmode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0)
285 		return (EPERM);
286 
287 	/* Root can do anything else. */
288 	if (cred->cr_uid == 0)
289 		return (0);
290 
291 	/* Check for group 0 (wheel) permissions. */
292 	for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
293 		if (*gp == 0) {
294 			if (amode & VEXEC)
295 				mask |= S_IXGRP;
296 			if (amode & VREAD)
297 				mask |= S_IRGRP;
298 			if (amode & VWRITE)
299 				mask |= S_IWGRP;
300 			return ((fmode & mask) == mask ?  0 : EACCES);
301 		}
302 
303         /* Otherwise, check everyone else. */
304 	if (amode & VEXEC)
305 		mask |= S_IXOTH;
306 	if (amode & VREAD)
307 		mask |= S_IROTH;
308 	if (amode & VWRITE)
309 		mask |= S_IWOTH;
310 	return ((fmode & mask) == mask ? 0 : EACCES);
311 }
312 
313 kernfs_getattr(ap)
314 	struct vop_getattr_args /* {
315 		struct vnode *a_vp;
316 		struct vattr *a_vap;
317 		struct ucred *a_cred;
318 		struct proc *a_p;
319 	} */ *ap;
320 {
321 	struct vnode *vp = ap->a_vp;
322 	struct vattr *vap = ap->a_vap;
323 	struct timeval tv;
324 	int error = 0;
325 	char strbuf[KSTRING];
326 
327 	bzero((caddr_t) vap, sizeof(*vap));
328 	vattr_null(vap);
329 	vap->va_uid = 0;
330 	vap->va_gid = 0;
331 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
332 	vap->va_size = 0;
333 	vap->va_blocksize = DEV_BSIZE;
334 	microtime(&tv);
335 	TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
336 	vap->va_mtime = vap->va_atime;
337 	vap->va_ctime = vap->va_ctime;
338 	vap->va_gen = 0;
339 	vap->va_flags = 0;
340 	vap->va_rdev = 0;
341 	vap->va_bytes = 0;
342 
343 	if (vp->v_flag & VROOT) {
344 #ifdef KERNFS_DIAGNOSTIC
345 		printf("kernfs_getattr: stat rootdir\n");
346 #endif
347 		vap->va_type = VDIR;
348 		vap->va_mode = DIR_MODE;
349 		vap->va_nlink = 2;
350 		vap->va_fileid = 2;
351 		vap->va_size = DEV_BSIZE;
352 	} else {
353 		struct kern_target *kt = VTOKERN(vp)->kf_kt;
354 		int nbytes;
355 #ifdef KERNFS_DIAGNOSTIC
356 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
357 #endif
358 		vap->va_type = kt->kt_vtype;
359 		vap->va_mode = kt->kt_mode;
360 		vap->va_nlink = 1;
361 		vap->va_fileid = 1 + (kt - kern_targets) / sizeof(*kt);
362 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes);
363 		vap->va_size = nbytes;
364 	}
365 
366 #ifdef KERNFS_DIAGNOSTIC
367 	printf("kernfs_getattr: return error %d\n", error);
368 #endif
369 	return (error);
370 }
371 
372 kernfs_setattr(ap)
373 	struct vop_setattr_args /* {
374 		struct vnode *a_vp;
375 		struct vattr *a_vap;
376 		struct ucred *a_cred;
377 		struct proc *a_p;
378 	} */ *ap;
379 {
380 
381 	/*
382 	 * Silently ignore attribute changes.
383 	 * This allows for open with truncate to have no
384 	 * effect until some data is written.  I want to
385 	 * do it this way because all writes are atomic.
386 	 */
387 	return (0);
388 }
389 
390 static int
391 kernfs_read(ap)
392 	struct vop_read_args /* {
393 		struct vnode *a_vp;
394 		struct uio *a_uio;
395 		int  a_ioflag;
396 		struct ucred *a_cred;
397 	} */ *ap;
398 {
399 	struct vnode *vp = ap->a_vp;
400 	struct uio *uio = ap->a_uio;
401 	struct kern_target *kt;
402 	char strbuf[KSTRING];
403 	int off = uio->uio_offset;
404 	int error, len;
405 	char *cp;
406 
407 	if (vp->v_type == VDIR)
408 		return (EOPNOTSUPP);
409 
410 	kt = VTOKERN(vp)->kf_kt;
411 
412 #ifdef KERNFS_DIAGNOSTIC
413 	printf("kern_read %s\n", kt->kt_name);
414 #endif
415 
416 	len = 0;
417 	if (error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len))
418 		return (error);
419 	if (len <= off)
420 		return (0);
421 	return (uiomove(&strbuf[off], len - off, uio));
422 }
423 
424 static int
425 kernfs_write(ap)
426 	struct vop_write_args /* {
427 		struct vnode *a_vp;
428 		struct uio *a_uio;
429 		int  a_ioflag;
430 		struct ucred *a_cred;
431 	} */ *ap;
432 {
433 	struct vnode *vp = ap->a_vp;
434 	struct uio *uio = ap->a_uio;
435 	struct kern_target *kt;
436 	int error, xlen;
437 	char strbuf[KSTRING];
438 
439 	if (vp->v_type == VDIR)
440 		return (EOPNOTSUPP);
441 
442 	kt = VTOKERN(vp)->kf_kt;
443 
444 	if (uio->uio_offset != 0)
445 		return (EINVAL);
446 
447 	xlen = min(uio->uio_resid, KSTRING-1);
448 	if (error = uiomove(strbuf, xlen, uio))
449 		return (error);
450 
451 	if (uio->uio_resid != 0)
452 		return (EIO);
453 
454 	strbuf[xlen] = '\0';
455 	xlen = strlen(strbuf);
456 	return (kernfs_xwrite(kt, strbuf, xlen));
457 }
458 
459 kernfs_readdir(ap)
460 	struct vop_readdir_args /* {
461 		struct vnode *a_vp;
462 		struct uio *a_uio;
463 		struct ucred *a_cred;
464 		int *a_eofflag;
465 		u_long *a_cookies;
466 		int a_ncookies;
467 	} */ *ap;
468 {
469 	int error, i;
470 	struct uio *uio = ap->a_uio;
471 	struct kern_target *kt;
472 	struct dirent d;
473 
474 	if (ap->a_vp->v_type != VDIR)
475 		return (ENOTDIR);
476 
477 	/*
478 	 * We don't allow exporting kernfs mounts, and currently local
479 	 * requests do not need cookies.
480 	 */
481 	if (ap->a_ncookies != NULL)
482 		panic("kernfs_readdir: not hungry");
483 
484 	i = uio->uio_offset / UIO_MX;
485 	error = 0;
486 	for (kt = &kern_targets[i];
487 		uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
488 		struct dirent *dp = &d;
489 #ifdef KERNFS_DIAGNOSTIC
490 		printf("kernfs_readdir: i = %d\n", i);
491 #endif
492 
493 		if (kt->kt_tag == KTT_DEVICE) {
494 			dev_t *dp = kt->kt_data;
495 			struct vnode *fvp;
496 
497 			if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
498 				continue;
499 		}
500 
501 		bzero((caddr_t)dp, UIO_MX);
502 		dp->d_namlen = kt->kt_namlen;
503 		bcopy(kt->kt_name, dp->d_name, kt->kt_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 = kt->kt_type;
515 		/*
516 		 * And ship to userland
517 		 */
518 		if (error = uiomove((caddr_t)dp, UIO_MX, uio))
519 			break;
520 	}
521 
522 	uio->uio_offset = i * UIO_MX;
523 
524 	return (error);
525 }
526 
527 kernfs_inactive(ap)
528 	struct vop_inactive_args /* {
529 		struct vnode *a_vp;
530 		struct proc *a_p;
531 	} */ *ap;
532 {
533 	struct vnode *vp = ap->a_vp;
534 
535 #ifdef KERNFS_DIAGNOSTIC
536 	printf("kernfs_inactive(%x)\n", vp);
537 #endif
538 	/*
539 	 * Clear out the v_type field to avoid
540 	 * nasty things happening in vgone().
541 	 */
542 	VOP_UNLOCK(vp, 0, ap->a_p);
543 	vp->v_type = VNON;
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 
554 #ifdef KERNFS_DIAGNOSTIC
555 	printf("kernfs_reclaim(%x)\n", vp);
556 #endif
557 	if (vp->v_data) {
558 		FREE(vp->v_data, M_TEMP);
559 		vp->v_data = 0;
560 	}
561 	return (0);
562 }
563 
564 /*
565  * Return POSIX pathconf information applicable to special devices.
566  */
567 kernfs_pathconf(ap)
568 	struct vop_pathconf_args /* {
569 		struct vnode *a_vp;
570 		int a_name;
571 		int *a_retval;
572 	} */ *ap;
573 {
574 
575 	switch (ap->a_name) {
576 	case _PC_LINK_MAX:
577 		*ap->a_retval = LINK_MAX;
578 		return (0);
579 	case _PC_MAX_CANON:
580 		*ap->a_retval = MAX_CANON;
581 		return (0);
582 	case _PC_MAX_INPUT:
583 		*ap->a_retval = MAX_INPUT;
584 		return (0);
585 	case _PC_PIPE_BUF:
586 		*ap->a_retval = PIPE_BUF;
587 		return (0);
588 	case _PC_CHOWN_RESTRICTED:
589 		*ap->a_retval = 1;
590 		return (0);
591 	case _PC_VDISABLE:
592 		*ap->a_retval = _POSIX_VDISABLE;
593 		return (0);
594 	default:
595 		return (EINVAL);
596 	}
597 	/* NOTREACHED */
598 }
599 
600 /*
601  * Print out the contents of a /dev/fd vnode.
602  */
603 /* ARGSUSED */
604 kernfs_print(ap)
605 	struct vop_print_args /* {
606 		struct vnode *a_vp;
607 	} */ *ap;
608 {
609 
610 	printf("tag VT_KERNFS, kernfs vnode\n");
611 	return (0);
612 }
613 
614 /*void*/
615 kernfs_vfree(ap)
616 	struct vop_vfree_args /* {
617 		struct vnode *a_pvp;
618 		ino_t a_ino;
619 		int a_mode;
620 	} */ *ap;
621 {
622 
623 	return (0);
624 }
625 
626 /*
627  * /dev/fd "should never get here" operation
628  */
629 kernfs_badop()
630 {
631 
632 	panic("kernfs: bad op");
633 	/* NOTREACHED */
634 }
635 
636 /*
637  * kernfs vnode null operation
638  */
639 kernfs_nullop()
640 {
641 
642 	return (0);
643 }
644 
645 #define kernfs_create ((int (*) __P((struct  vop_create_args *)))eopnotsupp)
646 #define kernfs_mknod ((int (*) __P((struct  vop_mknod_args *)))eopnotsupp)
647 #define kernfs_close ((int (*) __P((struct  vop_close_args *)))nullop)
648 #define kernfs_ioctl ((int (*) __P((struct  vop_ioctl_args *)))eopnotsupp)
649 #define kernfs_select ((int (*) __P((struct  vop_select_args *)))eopnotsupp)
650 #define kernfs_revoke vop_revoke
651 #define kernfs_mmap ((int (*) __P((struct  vop_mmap_args *)))eopnotsupp)
652 #define kernfs_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
653 #define kernfs_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
654 #define kernfs_remove ((int (*) __P((struct  vop_remove_args *)))eopnotsupp)
655 #define kernfs_link ((int (*) __P((struct  vop_link_args *)))eopnotsupp)
656 #define kernfs_rename ((int (*) __P((struct  vop_rename_args *)))eopnotsupp)
657 #define kernfs_mkdir ((int (*) __P((struct  vop_mkdir_args *)))eopnotsupp)
658 #define kernfs_rmdir ((int (*) __P((struct  vop_rmdir_args *)))eopnotsupp)
659 #define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
660 #define kernfs_readlink ((int (*) __P((struct  vop_readlink_args *)))eopnotsupp)
661 #define kernfs_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
662 #define kernfs_lock ((int (*) __P((struct  vop_lock_args *)))vop_nolock)
663 #define kernfs_unlock ((int (*) __P((struct  vop_unlock_args *)))vop_nounlock)
664 #define kernfs_bmap ((int (*) __P((struct  vop_bmap_args *)))kernfs_badop)
665 #define kernfs_strategy \
666 	((int (*) __P((struct  vop_strategy_args *)))kernfs_badop)
667 #define kernfs_islocked \
668 	((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
669 #define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
670 #define kernfs_blkatoff ((int (*) __P((struct  vop_blkatoff_args *)))eopnotsupp)
671 #define kernfs_valloc ((int(*) __P(( \
672 		struct vnode *pvp, \
673 		int mode, \
674 		struct ucred *cred, \
675 		struct vnode **vpp))) eopnotsupp)
676 #define kernfs_truncate ((int (*) __P((struct  vop_truncate_args *)))eopnotsupp)
677 #define kernfs_update ((int (*) __P((struct  vop_update_args *)))eopnotsupp)
678 #define kernfs_bwrite ((int (*) __P((struct  vop_bwrite_args *)))eopnotsupp)
679 
680 int (**kernfs_vnodeop_p)();
681 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
682 	{ &vop_default_desc, vn_default_error },
683 	{ &vop_lookup_desc, kernfs_lookup },	/* lookup */
684 	{ &vop_create_desc, kernfs_create },	/* create */
685 	{ &vop_mknod_desc, kernfs_mknod },	/* mknod */
686 	{ &vop_open_desc, kernfs_open },	/* open */
687 	{ &vop_close_desc, kernfs_close },	/* close */
688 	{ &vop_access_desc, kernfs_access },	/* access */
689 	{ &vop_getattr_desc, kernfs_getattr },	/* getattr */
690 	{ &vop_setattr_desc, kernfs_setattr },	/* setattr */
691 	{ &vop_read_desc, kernfs_read },	/* read */
692 	{ &vop_write_desc, kernfs_write },	/* write */
693 	{ &vop_ioctl_desc, kernfs_ioctl },	/* ioctl */
694 	{ &vop_select_desc, kernfs_select },	/* select */
695 	{ &vop_revoke_desc, kernfs_revoke },	/* revoke */
696 	{ &vop_mmap_desc, kernfs_mmap },	/* mmap */
697 	{ &vop_fsync_desc, kernfs_fsync },	/* fsync */
698 	{ &vop_seek_desc, kernfs_seek },	/* seek */
699 	{ &vop_remove_desc, kernfs_remove },	/* remove */
700 	{ &vop_link_desc, kernfs_link },	/* link */
701 	{ &vop_rename_desc, kernfs_rename },	/* rename */
702 	{ &vop_mkdir_desc, kernfs_mkdir },	/* mkdir */
703 	{ &vop_rmdir_desc, kernfs_rmdir },	/* rmdir */
704 	{ &vop_symlink_desc, kernfs_symlink },	/* symlink */
705 	{ &vop_readdir_desc, kernfs_readdir },	/* readdir */
706 	{ &vop_readlink_desc, kernfs_readlink },/* readlink */
707 	{ &vop_abortop_desc, kernfs_abortop },	/* abortop */
708 	{ &vop_inactive_desc, kernfs_inactive },/* inactive */
709 	{ &vop_reclaim_desc, kernfs_reclaim },	/* reclaim */
710 	{ &vop_lock_desc, kernfs_lock },	/* lock */
711 	{ &vop_unlock_desc, kernfs_unlock },	/* unlock */
712 	{ &vop_bmap_desc, kernfs_bmap },	/* bmap */
713 	{ &vop_strategy_desc, kernfs_strategy },/* strategy */
714 	{ &vop_print_desc, kernfs_print },	/* print */
715 	{ &vop_islocked_desc, kernfs_islocked },/* islocked */
716 	{ &vop_pathconf_desc, kernfs_pathconf },/* pathconf */
717 	{ &vop_advlock_desc, kernfs_advlock },	/* advlock */
718 	{ &vop_blkatoff_desc, kernfs_blkatoff },/* blkatoff */
719 	{ &vop_valloc_desc, kernfs_valloc },	/* valloc */
720 	{ &vop_vfree_desc, kernfs_vfree },	/* vfree */
721 	{ &vop_truncate_desc, kernfs_truncate },/* truncate */
722 	{ &vop_update_desc, kernfs_update },	/* update */
723 	{ &vop_bwrite_desc, kernfs_bwrite },	/* bwrite */
724 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
725 };
726 struct vnodeopv_desc kernfs_vnodeop_opv_desc =
727 	{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
728