Home | History | Annotate | Line # | Download | only in kernfs
kernfs_vnops.c revision 1.8
      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.8 1993/05/28 14:12:17 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 /*
    316  * Check mode permission on target pointer. Mode is READ, WRITE or EXEC.
    317  * The mode is shifted to select the owner/group/other fields. The
    318  * super user is granted all permissions.
    319  */
    320 kernfs_access(vp, mode, cred, p)
    321         struct vnode *vp;
    322         register int mode;
    323         struct ucred *cred;
    324         struct proc *p;
    325 {
    326         struct kern_target *kt = VTOKERN(vp)->kf_kt;
    327         register gid_t *gp;
    328         int i, error;
    329 
    330 #ifdef KERN_DIAGNOSTIC
    331         if (!VOP_ISLOCKED(vp)) {
    332                 vprint("kernfs_access: not locked", vp);
    333                 panic("kernfs_access: not locked");
    334         }
    335 #endif
    336         /*
    337          * If you're the super-user, you always get access.
    338          */
    339         if (cred->cr_uid == 0)
    340                 return (0);
    341         /*
    342          * Access check is based on only one of owner, group, public.
    343          * If not owner, then check group. If not a member of the
    344          * group, then check public access.
    345          */
    346         if (cred->cr_uid != /* kt->kt_uid XXX */ 0) {
    347                 mode >>= 3;
    348                 gp = cred->cr_groups;
    349                 for (i = 0; i < cred->cr_ngroups; i++, gp++)
    350                         if (/* kt->kt_gid XXX */ 0 == *gp)
    351                                 goto found;
    352                 mode >>= 3;
    353 found:
    354                 ;
    355         }
    356         if (((vp->v_flag & VROOT ? KTM_DIR_MODE : kt->kt_rw) & mode) == mode)
    357                 return (0);
    358         return (EACCES);
    359 }
    360 
    361 kernfs_getattr(vp, vap, cred, p)
    362 	struct vnode *vp;
    363 	struct vattr *vap;
    364 	struct ucred *cred;
    365 	struct proc *p;
    366 {
    367 	int error = 0;
    368 	char strbuf[KSTRING];
    369 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
    370 
    371 	bzero((caddr_t) vap, sizeof(*vap));
    372 	vattr_null(vap);
    373 	vap->va_uid = 0;
    374 	vap->va_gid = 0;
    375 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
    376 	/* vap->va_qsize = 0; */
    377 	vap->va_blocksize = DEV_BSIZE;
    378 	microtime(&vap->va_atime);
    379 	vap->va_mtime = vap->va_atime;
    380 	vap->va_ctime = vap->va_ctime;
    381 	vap->va_gen = 0;
    382 	vap->va_flags = 0;
    383 	vap->va_rdev = 0;
    384 	/* vap->va_qbytes = 0; */
    385 	vap->va_bytes = 0;
    386 
    387 	if (vp->v_flag & VROOT) {
    388 #ifdef KERNFS_DIAGNOSTIC
    389 		printf("kernfs_getattr: stat rootdir\n");
    390 #endif
    391 		vap->va_type = VDIR;
    392 		vap->va_mode = KTM_DIR_MODE;
    393 		vap->va_nlink = 2;
    394 		vap->va_fileid = 2;
    395 		vap->va_size = DEV_BSIZE;
    396 	} else {
    397 #ifdef KERNFS_DIAGNOSTIC
    398 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
    399 #endif
    400 		vap->va_type = kt->kt_vtype;
    401 		vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
    402 		vap->va_nlink = 1;
    403 		vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
    404 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
    405 	}
    406 
    407 	vp->v_type = vap->va_type;
    408 #ifdef KERNFS_DIAGNOSTIC
    409 	printf("kernfs_getattr: return error %d\n", error);
    410 #endif
    411 	return (error);
    412 }
    413 
    414 kernfs_setattr(vp, vap, cred, p)
    415 	struct vnode *vp;
    416 	struct vattr *vap;
    417 	struct ucred *cred;
    418 	struct proc *p;
    419 {
    420 
    421 	/*
    422 	 * Silently ignore attribute changes.
    423 	 * This allows for open with truncate to have no
    424 	 * effect until some data is written.  I want to
    425 	 * do it this way because all writes are atomic.
    426 	 */
    427 	return (0);
    428 }
    429 
    430 static int
    431 kernfs_read(vp, uio, ioflag, cred)
    432 	struct vnode *vp;
    433 	struct uio *uio;
    434 	int ioflag;
    435 	struct ucred *cred;
    436 {
    437 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
    438 	char strbuf[KSTRING];
    439 	int off = uio->uio_offset;
    440 	int len = 0;
    441 	char *cp = strbuf;
    442 	int error;
    443 #ifdef KERNFS_DIAGNOSTIC
    444 	printf("kern_read %s\n", kt->kt_name);
    445 #endif
    446 
    447 	error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
    448 	if (error)
    449 		return (error);
    450 	cp = strbuf + off;
    451 	len -= off;
    452 	return (uiomove(cp, len, uio));
    453 }
    454 
    455 static int
    456 kernfs_write(vp, uio, ioflag, cred)
    457 	struct vnode *vp;
    458 	struct uio *uio;
    459 	int ioflag;
    460 	struct ucred *cred;
    461 {
    462 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
    463 	char strbuf[KSTRING];
    464 	int len = uio->uio_resid;
    465 	char *cp = strbuf;
    466 	int xlen;
    467 	int error;
    468 
    469 	if (uio->uio_offset != 0)
    470 		return (EINVAL);
    471 
    472 	xlen = min(uio->uio_resid, KSTRING-1);
    473 	error = uiomove(strbuf, xlen, uio);
    474 	if (error)
    475 		return (error);
    476 
    477 	if (uio->uio_resid != 0)
    478 		return (EIO);
    479 
    480 	strbuf[xlen] = '\0';
    481 	return (kernfs_xwrite(kt, strbuf, xlen));
    482 }
    483 
    484 kernfs_readdir(vp, uio, cred, eofflagp)
    485 	struct vnode *vp;
    486 	struct uio *uio;
    487 	struct ucred *cred;
    488 	int *eofflagp;
    489 {
    490 	struct filedesc *fdp;
    491 	int i;
    492 	int error;
    493 
    494 	i = uio->uio_offset / UIO_MX;
    495 	error = 0;
    496 	while (uio->uio_resid > 0) {
    497 #ifdef KERNFS_DIAGNOSTIC
    498 		printf("kernfs_readdir: i = %d\n", i);
    499 #endif
    500 		if (i >= nkern_targets) {
    501 			*eofflagp = 1;
    502 			break;
    503 		}
    504 		{
    505 			struct direct d;
    506 			struct direct *dp = &d;
    507 			struct kern_target *kt = &kern_targets[i];
    508 
    509 			bzero((caddr_t) dp, UIO_MX);
    510 
    511 			dp->d_namlen = strlen(kt->kt_name);
    512 			bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
    513 
    514 #ifdef KERNFS_DIAGNOSTIC
    515 			printf("kernfs_readdir: name = %s, len = %d\n",
    516 					dp->d_name, dp->d_namlen);
    517 #endif
    518 			/*
    519 			 * Fill in the remaining fields
    520 			 */
    521 			dp->d_reclen = UIO_MX;
    522 			dp->d_ino = i + 3;
    523 			/*
    524 			 * And ship to userland
    525 			 */
    526 			error = uiomove((caddr_t) dp, UIO_MX, uio);
    527 			if (error)
    528 				break;
    529 		}
    530 		i++;
    531 	}
    532 
    533 	uio->uio_offset = i * UIO_MX;
    534 
    535 	return (error);
    536 }
    537 
    538 kernfs_inactive(vp, p)
    539 	struct vnode *vp;
    540 	struct proc *p;
    541 {
    542 	/*
    543 	 * Clear out the v_type field to avoid
    544 	 * nasty things happening in vgone().
    545 	 */
    546 	vp->v_type = VNON;
    547 #ifdef KERNFS_DIAGNOSTIC
    548 	printf("kernfs_inactive(%x)\n", vp);
    549 #endif
    550 	return (0);
    551 }
    552 
    553 /*
    554  * Print out the contents of a kernfs vnode.
    555  */
    556 /* ARGSUSED */
    557 kernfs_print(vp)
    558 	struct vnode *vp;
    559 {
    560 	printf("tag VT_NON, kernfs vnode\n");
    561 }
    562 
    563 /*
    564  * kernfs vnode unsupported operation
    565  */
    566 kernfs_enotsupp()
    567 {
    568 	return (EOPNOTSUPP);
    569 }
    570 
    571 /*
    572  * kernfs "should never get here" operation
    573  */
    574 kernfs_badop()
    575 {
    576 	panic("kernfs: bad op");
    577 	/* NOTREACHED */
    578 }
    579 
    580 /*
    581  * kernfs vnode null operation
    582  */
    583 kernfs_nullop()
    584 {
    585 	return (0);
    586 }
    587 
    588 #define kernfs_create ((int (*) __P(( \
    589 		struct nameidata *ndp, \
    590 		struct vattr *vap, \
    591 		struct proc *p))) kernfs_enotsupp)
    592 #define kernfs_mknod ((int (*) __P(( \
    593 		struct nameidata *ndp, \
    594 		struct vattr *vap, \
    595 		struct ucred *cred, \
    596 		struct proc *p))) kernfs_enotsupp)
    597 #define kernfs_close ((int (*) __P(( \
    598 		struct vnode *vp, \
    599 		int fflag, \
    600 		struct ucred *cred, \
    601 		struct proc *p))) nullop)
    602 #define	kernfs_ioctl ((int (*) __P(( \
    603 		struct vnode *vp, \
    604 		int command, \
    605 		caddr_t data, \
    606 		int fflag, \
    607 		struct ucred *cred, \
    608 		struct proc *p))) kernfs_enotsupp)
    609 #define	kernfs_select ((int (*) __P(( \
    610 		struct vnode *vp, \
    611 		int which, \
    612 		int fflags, \
    613 		struct ucred *cred, \
    614 		struct proc *p))) kernfs_enotsupp)
    615 #define kernfs_mmap ((int (*) __P(( \
    616 		struct vnode *vp, \
    617 		int fflags, \
    618 		struct ucred *cred, \
    619 		struct proc *p))) kernfs_enotsupp)
    620 #define kernfs_fsync ((int (*) __P(( \
    621 		struct vnode *vp, \
    622 		int fflags, \
    623 		struct ucred *cred, \
    624 		int waitfor, \
    625 		struct proc *p))) nullop)
    626 #define kernfs_seek ((int (*) __P(( \
    627 		struct vnode *vp, \
    628 		off_t oldoff, \
    629 		off_t newoff, \
    630 		struct ucred *cred))) nullop)
    631 #define kernfs_remove ((int (*) __P(( \
    632 		struct nameidata *ndp, \
    633 		struct proc *p))) kernfs_enotsupp)
    634 #define kernfs_link ((int (*) __P(( \
    635 		struct vnode *vp, \
    636 		struct nameidata *ndp, \
    637 		struct proc *p))) kernfs_enotsupp)
    638 #define kernfs_rename ((int (*) __P(( \
    639 		struct nameidata *fndp, \
    640 		struct nameidata *tdnp, \
    641 		struct proc *p))) kernfs_enotsupp)
    642 #define kernfs_mkdir ((int (*) __P(( \
    643 		struct nameidata *ndp, \
    644 		struct vattr *vap, \
    645 		struct proc *p))) kernfs_enotsupp)
    646 #define kernfs_rmdir ((int (*) __P(( \
    647 		struct nameidata *ndp, \
    648 		struct proc *p))) kernfs_enotsupp)
    649 #define kernfs_symlink ((int (*) __P(( \
    650 		struct nameidata *ndp, \
    651 		struct vattr *vap, \
    652 		char *target, \
    653 		struct proc *p))) kernfs_enotsupp)
    654 #define kernfs_readlink ((int (*) __P(( \
    655 		struct vnode *vp, \
    656 		struct uio *uio, \
    657 		struct ucred *cred))) kernfs_enotsupp)
    658 #define kernfs_abortop ((int (*) __P(( \
    659 		struct nameidata *ndp))) nullop)
    660 #ifdef KERNFS_DIAGNOSTIC
    661 int kernfs_reclaim(vp)
    662 struct vnode *vp;
    663 {
    664 	printf("kernfs_reclaim(%x)\n", vp);
    665 	return (0);
    666 }
    667 #else
    668 #define kernfs_reclaim ((int (*) __P(( \
    669 		struct vnode *vp))) nullop)
    670 #endif
    671 #define	kernfs_lock ((int (*) __P(( \
    672 		struct vnode *vp))) nullop)
    673 #define kernfs_unlock ((int (*) __P(( \
    674 		struct vnode *vp))) nullop)
    675 #define	kernfs_bmap ((int (*) __P(( \
    676 		struct vnode *vp, \
    677 		daddr_t bn, \
    678 		struct vnode **vpp, \
    679 		daddr_t *bnp))) kernfs_badop)
    680 #define	kernfs_strategy ((int (*) __P(( \
    681 		struct buf *bp))) kernfs_badop)
    682 #define kernfs_islocked ((int (*) __P(( \
    683 		struct vnode *vp))) nullop)
    684 #define kernfs_advlock ((int (*) __P(( \
    685 		struct vnode *vp, \
    686 		caddr_t id, \
    687 		int op, \
    688 		struct flock *fl, \
    689 		int flags))) kernfs_enotsupp)
    690 
    691 struct vnodeops kernfs_vnodeops = {
    692 	kernfs_lookup,	/* lookup */
    693 	kernfs_create,	/* create */
    694 	kernfs_mknod,	/* mknod */
    695 	kernfs_open,	/* open */
    696 	kernfs_close,	/* close */
    697 	kernfs_access,	/* access */
    698 	kernfs_getattr,	/* getattr */
    699 	kernfs_setattr,	/* setattr */
    700 	kernfs_read,	/* read */
    701 	kernfs_write,	/* write */
    702 	kernfs_ioctl,	/* ioctl */
    703 	kernfs_select,	/* select */
    704 	kernfs_mmap,	/* mmap */
    705 	kernfs_fsync,	/* fsync */
    706 	kernfs_seek,	/* seek */
    707 	kernfs_remove,	/* remove */
    708 	kernfs_link,	/* link */
    709 	kernfs_rename,	/* rename */
    710 	kernfs_mkdir,	/* mkdir */
    711 	kernfs_rmdir,	/* rmdir */
    712 	kernfs_symlink,	/* symlink */
    713 	kernfs_readdir,	/* readdir */
    714 	kernfs_readlink,	/* readlink */
    715 	kernfs_abortop,	/* abortop */
    716 	kernfs_inactive,	/* inactive */
    717 	kernfs_reclaim,	/* reclaim */
    718 	kernfs_lock,	/* lock */
    719 	kernfs_unlock,	/* unlock */
    720 	kernfs_bmap,	/* bmap */
    721 	kernfs_strategy,	/* strategy */
    722 	kernfs_print,	/* print */
    723 	kernfs_islocked,	/* islocked */
    724 	kernfs_advlock,	/* advlock */
    725 };
    726