Home | History | Annotate | Line # | Download | only in kernfs
kernfs_vnops.c revision 1.20
      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.20 1994/02/14 19:46:18 ws 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_qsize = 0; */
    389 	vap->va_blocksize = DEV_BSIZE;
    390 	microtime(&vap->va_atime);
    391 	vap->va_mtime = vap->va_atime;
    392 	vap->va_ctime = vap->va_ctime;
    393 	vap->va_gen = 0;
    394 	vap->va_flags = 0;
    395 	vap->va_rdev = 0;
    396 	/* vap->va_qbytes = 0; */
    397 	vap->va_bytes = 0;
    398 
    399 	if (vp->v_flag & VROOT) {
    400 #ifdef KERNFS_DIAGNOSTIC
    401 		printf("kernfs_getattr: stat rootdir\n");
    402 #endif
    403 		vap->va_type = VDIR;
    404 		vap->va_mode = KTM_DIR_MODE;
    405 		vap->va_nlink = 2;
    406 		vap->va_fileid = 2;
    407 		vap->va_size = DEV_BSIZE;
    408 	} else {
    409 #ifdef KERNFS_DIAGNOSTIC
    410 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
    411 #endif
    412 		vap->va_type = kt->kt_vtype;
    413 		vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
    414 		vap->va_nlink = 1;
    415 		vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
    416 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
    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