Home | History | Annotate | Line # | Download | only in kernfs
kernfs_vnops.c revision 1.7
      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.7 1993/05/20 04:01:31 cgd 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 + 2 > len)	/* extra space for null and newline */
    137 			return (EINVAL);
    138 
    139 		bcopy(cp, buf, xlen);	/* safer than sprintf */
    140 		buf[xlen] = '\n';
    141 		buf[xlen+1] = '\0';
    142 		break;
    143 	}
    144 
    145 	case KTT_AVENRUN:
    146 		sprintf(buf, "%d %d %d %d\n",
    147 				averunnable[0],
    148 				averunnable[1],
    149 				averunnable[2],
    150 				FSCALE);
    151 		break;
    152 
    153 	default:
    154 		return (EINVAL);
    155 	}
    156 
    157 	*lenp = strlen(buf);
    158 	return (0);
    159 }
    160 
    161 static int
    162 kernfs_xwrite(kt, buf, len)
    163 	struct kern_target *kt;
    164 	char *buf;
    165 	int len;
    166 {
    167 	switch (kt->kt_tag) {
    168 	case KTT_HOSTNAME: {
    169 		if (buf[len-1] == '\n')
    170 			--len;
    171 		bcopy(buf, hostname, len);
    172 		/* kernfs_write set buf[value_passed_as_len] = \0.
    173 		 * therefore, buf len (hostnamelen) = len.
    174 		 */
    175 		hostnamelen = len;
    176 		hostname[hostnamelen] = '\0';	/* null end of string. */
    177 		return (0);
    178 	}
    179 
    180 	default:
    181 		return (EIO);
    182 	}
    183 }
    184 
    185 /*
    186  * vp is the current namei directory
    187  * ndp is the name to locate in that directory...
    188  */
    189 kernfs_lookup(dvp, ndp, p)
    190 	struct vnode *dvp;
    191 	struct nameidata *ndp;
    192 	struct proc *p;
    193 {
    194 	char *pname = ndp->ni_ptr;
    195 	int error = ENOENT;
    196 	int i;
    197 	struct vnode *fvp;
    198 
    199 #ifdef KERNFS_DIAGNOSTIC
    200 	printf("kernfs_lookup(%s)\n", pname);
    201 #endif
    202 	if (ndp->ni_namelen == 1 && *pname == '.') {
    203 		ndp->ni_dvp = dvp;
    204 		ndp->ni_vp = dvp;
    205 		VREF(dvp);
    206 		/*VOP_LOCK(dvp);*/
    207 		return (0);
    208 	}
    209 
    210 	if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
    211 		ndp->ni_dvp = dvp;
    212 		ndp->ni_vp = rootdir;
    213 		VREF(rootdir);
    214 		VOP_LOCK(rootdir);
    215 		return (0);
    216 	}
    217 
    218 	/*
    219 	 * /kern/rootdev is the root device
    220 	 */
    221 	if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
    222 		if (vfinddev(rootdev, VBLK, &fvp))
    223 			return (ENXIO);
    224 		ndp->ni_dvp = dvp;
    225 		ndp->ni_vp = fvp;
    226 		VREF(fvp);
    227 		VOP_LOCK(fvp);
    228 		return (0);
    229 	}
    230 
    231 	/*
    232 	 * /kern/rrootdev is the root device
    233 	 */
    234 	if (ndp->ni_namelen == 8 && bcmp(pname, "rrootdev", 7) == 0) {
    235 		ndp->ni_dvp = dvp;
    236 		ndp->ni_vp = rrootdevvp;
    237 		VREF(rrootdevvp);
    238 		VOP_LOCK(rrootdevvp);
    239 		return (0);
    240 	}
    241 
    242 	for (i = 0; i < nkern_targets; i++) {
    243 		struct kern_target *kt = &kern_targets[i];
    244 		if (ndp->ni_namelen == strlen(kt->kt_name) &&
    245 		    bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
    246 			error = 0;
    247 			break;
    248 		}
    249 	}
    250 
    251 #ifdef KERNFS_DIAGNOSTIC
    252 	printf("kernfs_lookup: i = %d, error = %d\n", i, error);
    253 #endif
    254 
    255 	if (error)
    256 		goto bad;
    257 
    258 #ifdef KERNFS_DIAGNOSTIC
    259 	printf("kernfs_lookup: allocate new vnode\n");
    260 #endif
    261 	error = getnewvnode(VT_UFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
    262 	if (error)
    263 		goto bad;
    264 	VTOKERN(fvp)->kf_kt = &kern_targets[i];
    265 	fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
    266 	ndp->ni_dvp = dvp;
    267 	ndp->ni_vp = fvp;
    268 #ifdef KERNFS_DIAGNOSTIC
    269 	printf("kernfs_lookup: newvp = %x\n", fvp);
    270 #endif
    271 	return (0);
    272 
    273 bad:;
    274 	ndp->ni_dvp = dvp;
    275 	ndp->ni_vp = NULL;
    276 #ifdef KERNFS_DIAGNOSTIC
    277 	printf("kernfs_lookup: error = %d\n", error);
    278 #endif
    279 	return (error);
    280 }
    281 
    282 kernfs_open(vp, mode, cred, p)
    283 	struct vnode *vp;
    284 	int mode;
    285 	struct ucred *cred;
    286 	struct proc *p;
    287 {
    288 	int error;
    289 	struct filedesc *fdp;
    290 	struct file *fp;
    291 	int dfd;
    292 	int fd;
    293 
    294 #ifdef KERNFS_DIAGNOSTIC
    295 	printf("kernfs_open\n");
    296 #endif
    297 
    298 	/*
    299 	 * Can always open the root (modulo perms)
    300 	 */
    301 	if (vp->v_flag & VROOT)
    302 		return (0);
    303 
    304 #ifdef KERNFS_DIAGNOSTIC
    305 	printf("kernfs_open, mode = %x, file = %s\n",
    306 			mode, VTOKERN(vp)->kf_kt->kt_name);
    307 #endif
    308 
    309 	if ((mode & FWRITE) && VTOKERN(vp)->kf_kt->kt_rw != KTM_RW)
    310 		return (EPERM);
    311 
    312 	return (0);
    313 }
    314 
    315 kernfs_getattr(vp, vap, cred, p)
    316 	struct vnode *vp;
    317 	struct vattr *vap;
    318 	struct ucred *cred;
    319 	struct proc *p;
    320 {
    321 	int error = 0;
    322 	char strbuf[KSTRING];
    323 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
    324 
    325 	bzero((caddr_t) vap, sizeof(*vap));
    326 	vattr_null(vap);
    327 	vap->va_uid = 0;
    328 	vap->va_gid = 0;
    329 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
    330 	/* vap->va_qsize = 0; */
    331 	vap->va_blocksize = DEV_BSIZE;
    332 	microtime(&vap->va_atime);
    333 	vap->va_mtime = vap->va_atime;
    334 	vap->va_ctime = vap->va_ctime;
    335 	vap->va_gen = 0;
    336 	vap->va_flags = 0;
    337 	vap->va_rdev = 0;
    338 	/* vap->va_qbytes = 0; */
    339 	vap->va_bytes = 0;
    340 
    341 	if (vp->v_flag & VROOT) {
    342 #ifdef KERNFS_DIAGNOSTIC
    343 		printf("kernfs_getattr: stat rootdir\n");
    344 #endif
    345 		vap->va_type = VDIR;
    346 		vap->va_mode = KTM_DIR_MODE;
    347 		vap->va_nlink = 2;
    348 		vap->va_fileid = 2;
    349 		vap->va_size = DEV_BSIZE;
    350 	} else {
    351 #ifdef KERNFS_DIAGNOSTIC
    352 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
    353 #endif
    354 		vap->va_type = kt->kt_vtype;
    355 		vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
    356 		vap->va_nlink = 1;
    357 		vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
    358 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
    359 	}
    360 
    361 	vp->v_type = vap->va_type;
    362 #ifdef KERNFS_DIAGNOSTIC
    363 	printf("kernfs_getattr: return error %d\n", error);
    364 #endif
    365 	return (error);
    366 }
    367 
    368 kernfs_setattr(vp, vap, cred, p)
    369 	struct vnode *vp;
    370 	struct vattr *vap;
    371 	struct ucred *cred;
    372 	struct proc *p;
    373 {
    374 
    375 	/*
    376 	 * Silently ignore attribute changes.
    377 	 * This allows for open with truncate to have no
    378 	 * effect until some data is written.  I want to
    379 	 * do it this way because all writes are atomic.
    380 	 */
    381 	return (0);
    382 }
    383 
    384 static int
    385 kernfs_read(vp, uio, ioflag, cred)
    386 	struct vnode *vp;
    387 	struct uio *uio;
    388 	int ioflag;
    389 	struct ucred *cred;
    390 {
    391 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
    392 	char strbuf[KSTRING];
    393 	int off = uio->uio_offset;
    394 	int len = 0;
    395 	char *cp = strbuf;
    396 	int error;
    397 #ifdef KERNFS_DIAGNOSTIC
    398 	printf("kern_read %s\n", kt->kt_name);
    399 #endif
    400 
    401 	error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
    402 	if (error)
    403 		return (error);
    404 	cp = strbuf + off;
    405 	len -= off;
    406 	return (uiomove(cp, len, uio));
    407 }
    408 
    409 static int
    410 kernfs_write(vp, uio, ioflag, cred)
    411 	struct vnode *vp;
    412 	struct uio *uio;
    413 	int ioflag;
    414 	struct ucred *cred;
    415 {
    416 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
    417 	char strbuf[KSTRING];
    418 	int len = uio->uio_resid;
    419 	char *cp = strbuf;
    420 	int xlen;
    421 	int error;
    422 
    423 	if (uio->uio_offset != 0)
    424 		return (EINVAL);
    425 
    426 	xlen = min(uio->uio_resid, KSTRING-1);
    427 	error = uiomove(strbuf, xlen, uio);
    428 	if (error)
    429 		return (error);
    430 
    431 	if (uio->uio_resid != 0)
    432 		return (EIO);
    433 
    434 	strbuf[xlen] = '\0';
    435 	return (kernfs_xwrite(kt, strbuf, xlen));
    436 }
    437 
    438 kernfs_readdir(vp, uio, cred, eofflagp)
    439 	struct vnode *vp;
    440 	struct uio *uio;
    441 	struct ucred *cred;
    442 	int *eofflagp;
    443 {
    444 	struct filedesc *fdp;
    445 	int i;
    446 	int error;
    447 
    448 	i = uio->uio_offset / UIO_MX;
    449 	error = 0;
    450 	while (uio->uio_resid > 0) {
    451 #ifdef KERNFS_DIAGNOSTIC
    452 		printf("kernfs_readdir: i = %d\n", i);
    453 #endif
    454 		if (i >= nkern_targets) {
    455 			*eofflagp = 1;
    456 			break;
    457 		}
    458 		{
    459 			struct direct d;
    460 			struct direct *dp = &d;
    461 			struct kern_target *kt = &kern_targets[i];
    462 
    463 			bzero((caddr_t) dp, UIO_MX);
    464 
    465 			dp->d_namlen = strlen(kt->kt_name);
    466 			bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
    467 
    468 #ifdef KERNFS_DIAGNOSTIC
    469 			printf("kernfs_readdir: name = %s, len = %d\n",
    470 					dp->d_name, dp->d_namlen);
    471 #endif
    472 			/*
    473 			 * Fill in the remaining fields
    474 			 */
    475 			dp->d_reclen = UIO_MX;
    476 			dp->d_ino = i + 3;
    477 			/*
    478 			 * And ship to userland
    479 			 */
    480 			error = uiomove((caddr_t) dp, UIO_MX, uio);
    481 			if (error)
    482 				break;
    483 		}
    484 		i++;
    485 	}
    486 
    487 	uio->uio_offset = i * UIO_MX;
    488 
    489 	return (error);
    490 }
    491 
    492 kernfs_inactive(vp, p)
    493 	struct vnode *vp;
    494 	struct proc *p;
    495 {
    496 	/*
    497 	 * Clear out the v_type field to avoid
    498 	 * nasty things happening in vgone().
    499 	 */
    500 	vp->v_type = VNON;
    501 #ifdef KERNFS_DIAGNOSTIC
    502 	printf("kernfs_inactive(%x)\n", vp);
    503 #endif
    504 	return (0);
    505 }
    506 
    507 /*
    508  * Print out the contents of a kernfs vnode.
    509  */
    510 /* ARGSUSED */
    511 kernfs_print(vp)
    512 	struct vnode *vp;
    513 {
    514 	printf("tag VT_NON, kernfs vnode\n");
    515 }
    516 
    517 /*
    518  * kernfs vnode unsupported operation
    519  */
    520 kernfs_enotsupp()
    521 {
    522 	return (EOPNOTSUPP);
    523 }
    524 
    525 /*
    526  * kernfs "should never get here" operation
    527  */
    528 kernfs_badop()
    529 {
    530 	panic("kernfs: bad op");
    531 	/* NOTREACHED */
    532 }
    533 
    534 /*
    535  * kernfs vnode null operation
    536  */
    537 kernfs_nullop()
    538 {
    539 	return (0);
    540 }
    541 
    542 #define kernfs_create ((int (*) __P(( \
    543 		struct nameidata *ndp, \
    544 		struct vattr *vap, \
    545 		struct proc *p))) kernfs_enotsupp)
    546 #define kernfs_mknod ((int (*) __P(( \
    547 		struct nameidata *ndp, \
    548 		struct vattr *vap, \
    549 		struct ucred *cred, \
    550 		struct proc *p))) kernfs_enotsupp)
    551 #define kernfs_close ((int (*) __P(( \
    552 		struct vnode *vp, \
    553 		int fflag, \
    554 		struct ucred *cred, \
    555 		struct proc *p))) nullop)
    556 #define kernfs_access ((int (*) __P(( \
    557 		struct vnode *vp, \
    558 		int mode, \
    559 		struct ucred *cred, \
    560 		struct proc *p))) nullop)
    561 #define	kernfs_ioctl ((int (*) __P(( \
    562 		struct vnode *vp, \
    563 		int command, \
    564 		caddr_t data, \
    565 		int fflag, \
    566 		struct ucred *cred, \
    567 		struct proc *p))) kernfs_enotsupp)
    568 #define	kernfs_select ((int (*) __P(( \
    569 		struct vnode *vp, \
    570 		int which, \
    571 		int fflags, \
    572 		struct ucred *cred, \
    573 		struct proc *p))) kernfs_enotsupp)
    574 #define kernfs_mmap ((int (*) __P(( \
    575 		struct vnode *vp, \
    576 		int fflags, \
    577 		struct ucred *cred, \
    578 		struct proc *p))) kernfs_enotsupp)
    579 #define kernfs_fsync ((int (*) __P(( \
    580 		struct vnode *vp, \
    581 		int fflags, \
    582 		struct ucred *cred, \
    583 		int waitfor, \
    584 		struct proc *p))) nullop)
    585 #define kernfs_seek ((int (*) __P(( \
    586 		struct vnode *vp, \
    587 		off_t oldoff, \
    588 		off_t newoff, \
    589 		struct ucred *cred))) nullop)
    590 #define kernfs_remove ((int (*) __P(( \
    591 		struct nameidata *ndp, \
    592 		struct proc *p))) kernfs_enotsupp)
    593 #define kernfs_link ((int (*) __P(( \
    594 		struct vnode *vp, \
    595 		struct nameidata *ndp, \
    596 		struct proc *p))) kernfs_enotsupp)
    597 #define kernfs_rename ((int (*) __P(( \
    598 		struct nameidata *fndp, \
    599 		struct nameidata *tdnp, \
    600 		struct proc *p))) kernfs_enotsupp)
    601 #define kernfs_mkdir ((int (*) __P(( \
    602 		struct nameidata *ndp, \
    603 		struct vattr *vap, \
    604 		struct proc *p))) kernfs_enotsupp)
    605 #define kernfs_rmdir ((int (*) __P(( \
    606 		struct nameidata *ndp, \
    607 		struct proc *p))) kernfs_enotsupp)
    608 #define kernfs_symlink ((int (*) __P(( \
    609 		struct nameidata *ndp, \
    610 		struct vattr *vap, \
    611 		char *target, \
    612 		struct proc *p))) kernfs_enotsupp)
    613 #define kernfs_readlink ((int (*) __P(( \
    614 		struct vnode *vp, \
    615 		struct uio *uio, \
    616 		struct ucred *cred))) kernfs_enotsupp)
    617 #define kernfs_abortop ((int (*) __P(( \
    618 		struct nameidata *ndp))) nullop)
    619 #ifdef KERNFS_DIAGNOSTIC
    620 int kernfs_reclaim(vp)
    621 struct vnode *vp;
    622 {
    623 	printf("kernfs_reclaim(%x)\n", vp);
    624 	return (0);
    625 }
    626 #else
    627 #define kernfs_reclaim ((int (*) __P(( \
    628 		struct vnode *vp))) nullop)
    629 #endif
    630 #define	kernfs_lock ((int (*) __P(( \
    631 		struct vnode *vp))) nullop)
    632 #define kernfs_unlock ((int (*) __P(( \
    633 		struct vnode *vp))) nullop)
    634 #define	kernfs_bmap ((int (*) __P(( \
    635 		struct vnode *vp, \
    636 		daddr_t bn, \
    637 		struct vnode **vpp, \
    638 		daddr_t *bnp))) kernfs_badop)
    639 #define	kernfs_strategy ((int (*) __P(( \
    640 		struct buf *bp))) kernfs_badop)
    641 #define kernfs_islocked ((int (*) __P(( \
    642 		struct vnode *vp))) nullop)
    643 #define kernfs_advlock ((int (*) __P(( \
    644 		struct vnode *vp, \
    645 		caddr_t id, \
    646 		int op, \
    647 		struct flock *fl, \
    648 		int flags))) kernfs_enotsupp)
    649 
    650 struct vnodeops kernfs_vnodeops = {
    651 	kernfs_lookup,	/* lookup */
    652 	kernfs_create,	/* create */
    653 	kernfs_mknod,	/* mknod */
    654 	kernfs_open,	/* open */
    655 	kernfs_close,	/* close */
    656 	kernfs_access,	/* access */
    657 	kernfs_getattr,	/* getattr */
    658 	kernfs_setattr,	/* setattr */
    659 	kernfs_read,	/* read */
    660 	kernfs_write,	/* write */
    661 	kernfs_ioctl,	/* ioctl */
    662 	kernfs_select,	/* select */
    663 	kernfs_mmap,	/* mmap */
    664 	kernfs_fsync,	/* fsync */
    665 	kernfs_seek,	/* seek */
    666 	kernfs_remove,	/* remove */
    667 	kernfs_link,	/* link */
    668 	kernfs_rename,	/* rename */
    669 	kernfs_mkdir,	/* mkdir */
    670 	kernfs_rmdir,	/* rmdir */
    671 	kernfs_symlink,	/* symlink */
    672 	kernfs_readdir,	/* readdir */
    673 	kernfs_readlink,	/* readlink */
    674 	kernfs_abortop,	/* abortop */
    675 	kernfs_inactive,	/* inactive */
    676 	kernfs_reclaim,	/* reclaim */
    677 	kernfs_lock,	/* lock */
    678 	kernfs_unlock,	/* unlock */
    679 	kernfs_bmap,	/* bmap */
    680 	kernfs_strategy,	/* strategy */
    681 	kernfs_print,	/* print */
    682 	kernfs_islocked,	/* islocked */
    683 	kernfs_advlock,	/* advlock */
    684 };
    685