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