xref: /netbsd-src/sys/miscfs/kernfs/kernfs_vnops.c (revision ae1bfcddc410612bc8c58b807e1830becb69a24c)
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  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  * From:
38  *	Id: kernfs_vnops.c,v 4.1 1994/01/02 14:41:30 jsp Exp
39  *
40  *	$Id: kernfs_vnops.c,v 1.22 1994/05/17 06:59:17 mycroft Exp $
41  */
42 
43 /*
44  * Kernel parameter filesystem
45  */
46 
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/types.h>
51 #include <sys/time.h>
52 #include <sys/proc.h>
53 #include <sys/file.h>
54 #include <sys/vnode.h>
55 #include <sys/stat.h>
56 #include <sys/mount.h>
57 #include <sys/namei.h>
58 #include <sys/buf.h>
59 #include <miscfs/kernfs/kernfs.h>
60 
61 #include <ufs/dir.h>		/* For readdir() XXX */
62 
63 #define KSTRING	256		/* Largest I/O available via this filesystem */
64 #define	UIO_MX 32
65 
66 struct kern_target {
67 	char *kt_name;
68 	void *kt_data;
69 #define	KTT_NULL 1
70 #define	KTT_TIME 5
71 #define KTT_INT	17
72 #define	KTT_STRING 31
73 #define KTT_HOSTNAME 47
74 #define KTT_AVENRUN 53
75 	int kt_tag;
76 #define	KTM_RO	0
77 #define	KTM_RO_MODE \
78 		((VREAD) | (VREAD >> 3) | (VREAD >> 6))
79 #define	KTM_RW	43
80 #define	KTM_RW_MODE \
81 		((VWRITE) | KTM_RO_MODE)
82 #define KTM_DIR_MODE \
83 		((VREAD|VEXEC) | ((VREAD|VEXEC) >> 3) | ((VREAD|VEXEC) >> 6))
84 	int kt_rw;
85 	enum vtype kt_vtype;
86 } kern_targets[] = {
87 /* NOTE: The name must be less than UIO_MX-16 chars in length */
88 	/* name		data		tag		ro/rw */
89 	{ ".",		0,		KTT_NULL,	KTM_RO,	VDIR },
90 	{ "..",		0,		KTT_NULL,	KTM_RO,	VDIR },
91 	{ "copyright",	copyright,	KTT_STRING,	KTM_RO,	VREG },
92 	{ "hostname",	0,		KTT_HOSTNAME,	KTM_RW,	VREG },
93 	{ "hz",		&hz,		KTT_INT,	KTM_RO,	VREG },
94 	{ "loadavg",	0,		KTT_AVENRUN,	KTM_RO,	VREG },
95 	{ "physmem",	&physmem,	KTT_INT,	KTM_RO,	VREG },
96 #if 0
97 	{ "root",	0,		KTT_NULL,	KTM_RO,	VDIR },
98 #endif
99 	{ "rootdev",	0,		KTT_NULL,	KTM_RO,	VBLK },
100 #ifdef notdef
101 	{ "rrootdev",	0,		KTT_NULL,	KTM_RO,	VCHR },
102 #endif
103 	{ "time",	0,		KTT_TIME,	KTM_RO,	VREG },
104 	{ "version",	version,	KTT_STRING,	KTM_RO,	VREG },
105 };
106 
107 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
108 
109 static int
110 kernfs_xread(kt, buf, len, lenp)
111 	struct kern_target *kt;
112 	char *buf;
113 	int len;
114 	int *lenp;
115 {
116 	int xlen;
117 
118 	switch (kt->kt_tag) {
119 	case KTT_TIME: {
120 		struct timeval tv;
121 		microtime(&tv);
122 		sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
123 		break;
124 	}
125 
126 	case KTT_INT: {
127 		int *ip = kt->kt_data;
128 		sprintf(buf, "%d\n", *ip);
129 		break;
130 	}
131 
132 	case KTT_STRING: {
133 		char *cp = kt->kt_data;
134 		int xlen = strlen(cp) + 1;
135 
136 		if (xlen >= len)
137 			return (EINVAL);
138 
139 		bcopy(cp, buf, xlen);
140 		break;
141 	}
142 
143 	case KTT_HOSTNAME: {
144 		char *cp = hostname;
145 		int xlen = hostnamelen;
146 
147 		if (xlen >= (len-2))
148 			return (EINVAL);
149 
150 		bcopy(cp, buf, xlen);
151 		buf[xlen] = '\n';
152 		buf[xlen+1] = '\0';
153 		break;
154 	}
155 
156 	case KTT_AVENRUN:
157 		sprintf(buf, "%d %d %d %d\n",
158 		    averunnable.ldavg[0],
159 		    averunnable.ldavg[1],
160 		    averunnable.ldavg[2],
161 		    averunnable.fscale);
162 		break;
163 
164 	default:
165 		return (EINVAL);
166 	}
167 
168 	*lenp = strlen(buf);
169 	return (0);
170 }
171 
172 static int
173 kernfs_xwrite(kt, buf, len)
174 	struct kern_target *kt;
175 	char *buf;
176 	int len;
177 {
178 	switch (kt->kt_tag) {
179 	case KTT_HOSTNAME: {
180 		if (buf[len-1] == '\n')
181 			--len;
182 		bcopy(buf, hostname, len);
183 		hostname[len] = '\0';
184 		hostnamelen = len;
185 		return (0);
186 	}
187 
188 	default:
189 		return (EIO);
190 	}
191 }
192 
193 /*
194  * implement access checking.
195  *
196  * something very similar to this code is duplicated
197  * throughout the 4bsd kernel and should be moved
198  * into kern/vfs_subr.c sometime.
199  *
200  * actually, the check for super-user is slightly
201  * broken since it will allow read access to write-only
202  * objects.  this doesn't cause any particular trouble
203  * but does mean that the i/o entry points need to check
204  * that the operation really does make sense.
205  */
206 kernfs_access(vp, mode, cred, p)
207 	struct vnode *vp;
208 	int mode;
209 	struct ucred *cred;
210 	struct proc *p;
211 {
212 	struct vattr *vap;
213 	struct vattr vattr;
214 	int error;
215 
216 	/*
217 	 * If you're the super-user,
218 	 * you always get access.
219 	 */
220 	if (cred->cr_uid == (uid_t) 0)
221 		return (0);
222 	vap = &vattr;
223 	if (error = VOP_GETATTR(vp, vap, cred, p))
224 		return (error);
225 
226 	/*
227 	 * Access check is based on only one of owner, group, public.
228 	 * If not owner, then check group. If not a member of the
229 	 * group, then check public access.
230 	 */
231 	if (cred->cr_uid != vap->va_uid) {
232 		gid_t *gp;
233 		int i;
234 
235 		mode >>= 3;
236 		gp = cred->cr_groups;
237 		for (i = 0; i < cred->cr_ngroups; i++, gp++)
238 			if (vap->va_gid == *gp)
239 				goto found;
240 		mode >>= 3;
241 found:
242 		;
243 	}
244 
245 	if ((vap->va_mode & mode) == mode)
246 		return (0);
247 
248 	return (EACCES);
249 }
250 
251 /*
252  * vp is the current namei directory
253  * ndp is the name to locate in that directory...
254  */
255 kernfs_lookup(dvp, ndp, p)
256 	struct vnode *dvp;
257 	struct nameidata *ndp;
258 	struct proc *p;
259 {
260 	char *pname = ndp->ni_ptr;
261 	int error = ENOENT;
262 	int i;
263 	struct vnode *fvp;
264 
265 #ifdef KERNFS_DIAGNOSTIC
266 	printf("kernfs_lookup(%s)\n", pname);
267 #endif
268 	if (ndp->ni_namelen == 1 && *pname == '.') {
269 		ndp->ni_dvp = dvp;
270 		ndp->ni_vp = dvp;
271 		VREF(dvp);
272 		/*VOP_LOCK(dvp);*/
273 		return (0);
274 	}
275 
276 #if 0
277 	if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
278 		ndp->ni_dvp = rootdir;
279 		ndp->ni_vp = rootdir;
280 		VREF(rootdir);
281 		VREF(rootdir);
282 		VOP_LOCK(rootdir);
283 		return (0);
284 	}
285 #endif
286 
287 	/*
288 	 * /kern/rootdev is the root device
289 	 */
290 	if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
291 		if (vfinddev(rootdev, VBLK, &fvp))
292 			return (ENXIO);
293 		ndp->ni_dvp = dvp;
294 		ndp->ni_vp = fvp;
295 		VREF(fvp);
296 		VOP_LOCK(fvp);
297 		return (0);
298 	}
299 
300 	for (i = 0; i < nkern_targets; i++) {
301 		struct kern_target *kt = &kern_targets[i];
302 		if (ndp->ni_namelen == strlen(kt->kt_name) &&
303 		    bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
304 			error = 0;
305 			break;
306 		}
307 	}
308 
309 #ifdef KERNFS_DIAGNOSTIC
310 	printf("kernfs_lookup: i = %d, error = %d\n", i, error);
311 #endif
312 
313 	if (error)
314 		goto bad;
315 
316 #ifdef KERNFS_DIAGNOSTIC
317 	printf("kernfs_lookup: allocate new vnode\n");
318 #endif
319 	error = getnewvnode(VT_KERNFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
320 	if (error)
321 		goto bad;
322 	VTOKERN(fvp)->kf_kt = &kern_targets[i];
323 	fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
324 	ndp->ni_dvp = dvp;
325 	ndp->ni_vp = fvp;
326 #ifdef KERNFS_DIAGNOSTIC
327 	printf("kernfs_lookup: newvp = %x\n", fvp);
328 #endif
329 	return (0);
330 
331 bad:;
332 	ndp->ni_dvp = dvp;
333 	ndp->ni_vp = NULL;
334 #ifdef KERNFS_DIAGNOSTIC
335 	printf("kernfs_lookup: error = %d\n", error);
336 #endif
337 	return (error);
338 }
339 
340 kernfs_open(vp, mode, cred, p)
341 	struct vnode *vp;
342 	int mode;
343 	struct ucred *cred;
344 	struct proc *p;
345 {
346 	int error;
347 	struct filedesc *fdp;
348 	struct file *fp;
349 	int dfd;
350 	int fd;
351 
352 #ifdef KERNFS_DIAGNOSTIC
353 	printf("kernfs_open\n");
354 #endif
355 
356 	/*
357 	 * Can always open the root (modulo perms)
358 	 */
359 	if (vp->v_flag & VROOT)
360 		return (0);
361 
362 #ifdef KERNFS_DIAGNOSTIC
363 	printf("kernfs_open, mode = %x, file = %s\n",
364 			mode, VTOKERN(vp)->kf_kt->kt_name);
365 #endif
366 
367 	if ((mode & FWRITE) && VTOKERN(vp)->kf_kt->kt_rw != KTM_RW)
368 		return (EACCES);
369 
370 	return (0);
371 }
372 
373 kernfs_getattr(vp, vap, cred, p)
374 	struct vnode *vp;
375 	struct vattr *vap;
376 	struct ucred *cred;
377 	struct proc *p;
378 {
379 	int error = 0;
380 	char strbuf[KSTRING];
381 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
382 
383 	bzero((caddr_t) vap, sizeof(*vap));
384 	vattr_null(vap);
385 	vap->va_uid = 0;
386 	vap->va_gid = 0;
387 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
388 	vap->va_blocksize = DEV_BSIZE;
389 	microtime(&vap->va_atime);
390 	vap->va_mtime = vap->va_atime;
391 	vap->va_ctime = vap->va_ctime;
392 	vap->va_gen = 0;
393 	vap->va_flags = 0;
394 	vap->va_rdev = 0;
395 	vap->va_bytes = 0;
396 
397 	if (vp->v_flag & VROOT) {
398 #ifdef KERNFS_DIAGNOSTIC
399 		printf("kernfs_getattr: stat rootdir\n");
400 #endif
401 		vap->va_type = VDIR;
402 		vap->va_mode = KTM_DIR_MODE;
403 		vap->va_nlink = 2;
404 		vap->va_fileid = 2;
405 		vap->va_size = DEV_BSIZE;
406 	} else {
407 		int nbytes;
408 #ifdef KERNFS_DIAGNOSTIC
409 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
410 #endif
411 		vap->va_type = kt->kt_vtype;
412 		vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
413 		vap->va_nlink = 1;
414 		vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
415 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes);
416 		vap->va_size = nbytes;
417 	}
418 
419 	vp->v_type = vap->va_type;
420 #ifdef KERNFS_DIAGNOSTIC
421 	printf("kernfs_getattr: return error %d\n", error);
422 #endif
423 	return (error);
424 }
425 
426 kernfs_setattr(vp, vap, cred, p)
427 	struct vnode *vp;
428 	struct vattr *vap;
429 	struct ucred *cred;
430 	struct proc *p;
431 {
432 
433 	/*
434 	 * Silently ignore attribute changes.
435 	 * This allows for open with truncate to have no
436 	 * effect until some data is written.  I want to
437 	 * do it this way because all writes are atomic.
438 	 */
439 	return (0);
440 }
441 
442 static int
443 kernfs_read(vp, uio, ioflag, cred)
444 	struct vnode *vp;
445 	struct uio *uio;
446 	int ioflag;
447 	struct ucred *cred;
448 {
449 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
450 	char strbuf[KSTRING];
451 	int off = uio->uio_offset;
452 	int len = 0;
453 	char *cp = strbuf;
454 	int error;
455 #ifdef KERNFS_DIAGNOSTIC
456 	printf("kern_read %s\n", kt->kt_name);
457 #endif
458 
459 	if (vp->v_flag & VROOT)
460 		return (EOPNOTSUPP);
461 
462 	error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
463 	if (error)
464 		return (error);
465 	cp = strbuf + off;
466 	len -= off;
467 	return (uiomove(cp, len, uio));
468 }
469 
470 static int
471 kernfs_write(vp, uio, ioflag, cred)
472 	struct vnode *vp;
473 	struct uio *uio;
474 	int ioflag;
475 	struct ucred *cred;
476 {
477 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
478 	char strbuf[KSTRING];
479 	int len = uio->uio_resid;
480 	char *cp = strbuf;
481 	int xlen;
482 	int error;
483 
484 	if (uio->uio_offset != 0)
485 		return (EINVAL);
486 
487 	xlen = min(uio->uio_resid, KSTRING-1);
488 	error = uiomove(strbuf, xlen, uio);
489 	if (error)
490 		return (error);
491 
492 	if (uio->uio_resid != 0)
493 		return (EIO);
494 
495 	strbuf[xlen] = '\0';
496 	xlen = strlen(strbuf);
497 	return (kernfs_xwrite(kt, strbuf, xlen));
498 }
499 
500 kernfs_readdir(vp, uio, cred, eofflagp)
501 	struct vnode *vp;
502 	struct uio *uio;
503 	struct ucred *cred;
504 	int *eofflagp;
505 {
506 	struct filedesc *fdp;
507 	int i;
508 	int error;
509 
510 	i = uio->uio_offset / UIO_MX;
511 	error = 0;
512 	while (uio->uio_resid > 0) {
513 #ifdef KERNFS_DIAGNOSTIC
514 		printf("kernfs_readdir: i = %d\n", i);
515 #endif
516 		if (i >= nkern_targets) {
517 			*eofflagp = 1;
518 			break;
519 		}
520 		{
521 			struct direct d;
522 			struct direct *dp = &d;
523 			struct kern_target *kt = &kern_targets[i];
524 
525 			bzero((caddr_t) dp, UIO_MX);
526 
527 			dp->d_namlen = strlen(kt->kt_name);
528 			bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
529 
530 #ifdef KERNFS_DIAGNOSTIC
531 			printf("kernfs_readdir: name = %s, len = %d\n",
532 					dp->d_name, dp->d_namlen);
533 #endif
534 			/*
535 			 * Fill in the remaining fields
536 			 */
537 			dp->d_reclen = UIO_MX;
538 			dp->d_ino = i + 3;
539 			/*
540 			 * And ship to userland
541 			 */
542 			error = uiomove((caddr_t) dp, UIO_MX, uio);
543 			if (error)
544 				break;
545 		}
546 		i++;
547 	}
548 
549 	uio->uio_offset = i * UIO_MX;
550 
551 	return (error);
552 }
553 
554 kernfs_inactive(vp, p)
555 	struct vnode *vp;
556 	struct proc *p;
557 {
558 	/*
559 	 * Clear out the v_type field to avoid
560 	 * nasty things happening in vgone().
561 	 */
562 	vp->v_type = VNON;
563 #ifdef KERNFS_DIAGNOSTIC
564 	printf("kernfs_inactive(%x)\n", vp);
565 #endif
566 	return (0);
567 }
568 
569 /*
570  * Print out the contents of a kernfs vnode.
571  */
572 /* ARGSUSED */
573 kernfs_print(vp)
574 	struct vnode *vp;
575 {
576 	printf("tag VT_NON, kernfs vnode\n");
577 }
578 
579 /*
580  * kernfs vnode unsupported operation
581  */
582 kernfs_enotsupp()
583 {
584 	return (EOPNOTSUPP);
585 }
586 
587 /*
588  * kernfs "should never get here" operation
589  */
590 kernfs_badop()
591 {
592 	panic("kernfs: bad op");
593 	/* NOTREACHED */
594 }
595 
596 /*
597  * kernfs vnode null operation
598  */
599 kernfs_nullop()
600 {
601 	return (0);
602 }
603 
604 #define kernfs_create ((int (*) __P(( \
605 		struct nameidata *ndp, \
606 		struct vattr *vap, \
607 		struct proc *p))) kernfs_enotsupp)
608 #define kernfs_mknod ((int (*) __P(( \
609 		struct nameidata *ndp, \
610 		struct vattr *vap, \
611 		struct ucred *cred, \
612 		struct proc *p))) kernfs_enotsupp)
613 #define kernfs_close ((int (*) __P(( \
614 		struct vnode *vp, \
615 		int fflag, \
616 		struct ucred *cred, \
617 		struct proc *p))) nullop)
618 #define	kernfs_ioctl ((int (*) __P(( \
619 		struct vnode *vp, \
620 		int command, \
621 		caddr_t data, \
622 		int fflag, \
623 		struct ucred *cred, \
624 		struct proc *p))) kernfs_enotsupp)
625 #define	kernfs_select ((int (*) __P(( \
626 		struct vnode *vp, \
627 		int which, \
628 		int fflags, \
629 		struct ucred *cred, \
630 		struct proc *p))) kernfs_enotsupp)
631 #define kernfs_mmap ((int (*) __P(( \
632 		struct vnode *vp, \
633 		int fflags, \
634 		struct ucred *cred, \
635 		struct proc *p))) kernfs_enotsupp)
636 #define kernfs_fsync ((int (*) __P(( \
637 		struct vnode *vp, \
638 		int fflags, \
639 		struct ucred *cred, \
640 		int waitfor, \
641 		struct proc *p))) nullop)
642 #define kernfs_seek ((int (*) __P(( \
643 		struct vnode *vp, \
644 		off_t oldoff, \
645 		off_t newoff, \
646 		struct ucred *cred))) nullop)
647 #define kernfs_remove ((int (*) __P(( \
648 		struct nameidata *ndp, \
649 		struct proc *p))) kernfs_enotsupp)
650 #define kernfs_link ((int (*) __P(( \
651 		struct vnode *vp, \
652 		struct nameidata *ndp, \
653 		struct proc *p))) kernfs_enotsupp)
654 #define kernfs_rename ((int (*) __P(( \
655 		struct nameidata *fndp, \
656 		struct nameidata *tdnp, \
657 		struct proc *p))) kernfs_enotsupp)
658 #define kernfs_mkdir ((int (*) __P(( \
659 		struct nameidata *ndp, \
660 		struct vattr *vap, \
661 		struct proc *p))) kernfs_enotsupp)
662 #define kernfs_rmdir ((int (*) __P(( \
663 		struct nameidata *ndp, \
664 		struct proc *p))) kernfs_enotsupp)
665 #define kernfs_symlink ((int (*) __P(( \
666 		struct nameidata *ndp, \
667 		struct vattr *vap, \
668 		char *target, \
669 		struct proc *p))) kernfs_enotsupp)
670 #define kernfs_readlink ((int (*) __P(( \
671 		struct vnode *vp, \
672 		struct uio *uio, \
673 		struct ucred *cred))) kernfs_enotsupp)
674 #define kernfs_abortop ((int (*) __P(( \
675 		struct nameidata *ndp))) nullop)
676 #ifdef KERNFS_DIAGNOSTIC
677 int kernfs_reclaim(vp)
678 struct vnode *vp;
679 {
680 	printf("kernfs_reclaim(%x)\n", vp);
681 	return (0);
682 }
683 #else
684 #define kernfs_reclaim ((int (*) __P(( \
685 		struct vnode *vp))) nullop)
686 #endif
687 #define	kernfs_lock ((int (*) __P(( \
688 		struct vnode *vp))) nullop)
689 #define kernfs_unlock ((int (*) __P(( \
690 		struct vnode *vp))) nullop)
691 #define	kernfs_bmap ((int (*) __P(( \
692 		struct vnode *vp, \
693 		daddr_t bn, \
694 		struct vnode **vpp, \
695 		daddr_t *bnp))) kernfs_badop)
696 #define	kernfs_strategy ((int (*) __P(( \
697 		struct buf *bp))) kernfs_badop)
698 #define kernfs_islocked ((int (*) __P(( \
699 		struct vnode *vp))) nullop)
700 #define kernfs_advlock ((int (*) __P(( \
701 		struct vnode *vp, \
702 		caddr_t id, \
703 		int op, \
704 		struct flock *fl, \
705 		int flags))) kernfs_enotsupp)
706 
707 struct vnodeops kernfs_vnodeops = {
708 	kernfs_lookup,	/* lookup */
709 	kernfs_create,	/* create */
710 	kernfs_mknod,	/* mknod */
711 	kernfs_open,	/* open */
712 	kernfs_close,	/* close */
713 	kernfs_access,	/* access */
714 	kernfs_getattr,	/* getattr */
715 	kernfs_setattr,	/* setattr */
716 	kernfs_read,	/* read */
717 	kernfs_write,	/* write */
718 	kernfs_ioctl,	/* ioctl */
719 	kernfs_select,	/* select */
720 	kernfs_mmap,	/* mmap */
721 	kernfs_fsync,	/* fsync */
722 	kernfs_seek,	/* seek */
723 	kernfs_remove,	/* remove */
724 	kernfs_link,	/* link */
725 	kernfs_rename,	/* rename */
726 	kernfs_mkdir,	/* mkdir */
727 	kernfs_rmdir,	/* rmdir */
728 	kernfs_symlink,	/* symlink */
729 	kernfs_readdir,	/* readdir */
730 	kernfs_readlink,	/* readlink */
731 	kernfs_abortop,	/* abortop */
732 	kernfs_inactive,	/* inactive */
733 	kernfs_reclaim,	/* reclaim */
734 	kernfs_lock,	/* lock */
735 	kernfs_unlock,	/* unlock */
736 	kernfs_bmap,	/* bmap */
737 	kernfs_strategy,	/* strategy */
738 	kernfs_print,	/* print */
739 	kernfs_islocked,	/* islocked */
740 	kernfs_advlock,	/* advlock */
741 };
742