Home | History | Annotate | Line # | Download | only in kernfs
kernfs_vnops.c revision 1.12.2.4
      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.12.2.4 1993/11/29 16:03:22 mycroft Exp $
     37  */
     38 
     39 /*
     40  * Kernel parameter filesystem
     41  */
     42 
     43 #include <sys/param.h>
     44 #include <sys/systm.h>
     45 #include <sys/kernel.h>
     46 #include <sys/types.h>
     47 #include <sys/time.h>
     48 #include <sys/proc.h>
     49 #include <sys/file.h>
     50 #include <sys/vnode.h>
     51 #include <sys/stat.h>
     52 #include <sys/mount.h>
     53 #include <sys/namei.h>
     54 #include <sys/buf.h>
     55 #include <miscfs/kernfs/kernfs.h>
     56 
     57 #include <ufs/dir.h>		/* For readdir() XXX */
     58 
     59 struct kernfs_target kernfs_targets[] = {
     60 /* NOTE: The name must be less than UIO_MX-16 chars in length */
     61 DIR_TARGET(".",		0,		KTT_NULL,	KTM_DIR_PERMS	)
     62 DIR_TARGET("..",	0,		KTT_NULL,	KTM_DIR_PERMS	)
     63 REG_TARGET("copyright",	copyright,	KTT_STRING,	KTM_RO_PERMS	)
     64 REG_TARGET("hostname",	0,		KTT_HOSTNAME,	KTM_RW_PERMS	)
     65 REG_TARGET("hz",	&hz,		KTT_INT,	KTM_RO_PERMS	)
     66 REG_TARGET("loadavg",	0,		KTT_AVENRUN,	KTM_RO_PERMS	)
     67 REG_TARGET("physmem",	&physmem,	KTT_INT,	KTM_RO_PERMS	)
     68 #ifdef KERNFS_HAVE_ROOTDIR
     69 DIR_TARGET("root",	0,		KTT_NULL,	KTM_DIR_PERMS	)
     70 #endif
     71 BLK_TARGET("rootdev",	0,		KTT_NULL,	KTM_RO_PERMS	)
     72 CHR_TARGET("rrootdev",	0,		KTT_NULL,	KTM_RO_PERMS	)
     73 REG_TARGET("time",	0,		KTT_TIME,	KTM_RO_PERMS	)
     74 REG_TARGET("version",	version,	KTT_STRING,	KTM_RO_PERMS	)
     75 };
     76 
     77 static int nkernfs_targets = sizeof(kernfs_targets) / sizeof(kernfs_targets[0]);
     78 
     79 static int
     80 kernfs_xread(kt, buf, len, lenp)
     81 	struct kernfs_target *kt;
     82 	char *buf;
     83 	int len;
     84 	int *lenp;
     85 {
     86 	int xlen;
     87 
     88 	switch (kt->kt_tag) {
     89 	case KTT_TIME: {
     90 		struct timeval tv;
     91 		microtime(&tv);
     92 		sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
     93 		break;
     94 	}
     95 
     96 	case KTT_INT: {
     97 		int *ip = kt->kt_data;
     98 		sprintf(buf, "%d\n", *ip);
     99 		break;
    100 	}
    101 
    102 	case KTT_STRING: {
    103 		char *cp = kt->kt_data;
    104 		int xlen = strlen(cp) + 1;
    105 
    106 		if (xlen >= len)
    107 			return (EINVAL);
    108 
    109 		bcopy(cp, buf, xlen);
    110 		break;
    111 	}
    112 
    113 	case KTT_HOSTNAME: {
    114 		char *cp = hostname;
    115 		int xlen = hostnamelen;
    116 
    117 		if (xlen + 2 > len)	/* extra space for null and newline */
    118 			return (EINVAL);
    119 
    120 		bcopy(cp, buf, xlen);	/* safer than sprintf */
    121 		buf[xlen] = '\n';
    122 		buf[xlen+1] = '\0';
    123 		break;
    124 	}
    125 
    126 	case KTT_AVENRUN:
    127 		sprintf(buf, "%d %d %d %d\n",
    128 				averunnable.ldavg[0],
    129 				averunnable.ldavg[1],
    130 				averunnable.ldavg[2],
    131 				FSCALE);
    132 		break;
    133 
    134 	default:
    135 		return (EINVAL);
    136 	}
    137 
    138 	*lenp = strlen(buf);
    139 	return (0);
    140 }
    141 
    142 static int
    143 kernfs_xwrite(kt, buf, len)
    144 	struct kernfs_target *kt;
    145 	char *buf;
    146 	int len;
    147 {
    148 	switch (kt->kt_tag) {
    149 	case KTT_HOSTNAME: {
    150 		if (buf[len-1] == '\n')
    151 			--len;
    152 		bcopy(buf, hostname, len);
    153 		/* kernfs_write set buf[value_passed_as_len] = \0.
    154 		 * therefore, buf len (hostnamelen) = len.
    155 		 */
    156 		hostnamelen = len;
    157 		hostname[hostnamelen] = '\0';	/* null end of string. */
    158 		return (0);
    159 	}
    160 
    161 	default:
    162 		return (EIO);
    163 	}
    164 }
    165 
    166 /*
    167  * vp is the current namei directory
    168  * ndp is the name to locate in that directory...
    169  */
    170 kernfs_lookup(dvp, ndp, p)
    171 	struct vnode *dvp;
    172 	struct nameidata *ndp;
    173 	struct proc *p;
    174 {
    175 	char *pname = ndp->ni_ptr;
    176 	int error = ENOENT;
    177 	int i;
    178 	struct vnode *fvp;
    179 
    180 #ifdef KERNFS_DIAGNOSTIC
    181 	printf("kernfs_lookup(%s)\n", pname);
    182 #endif
    183 	if (ndp->ni_namelen == 1 && *pname == '.') {
    184 		ndp->ni_dvp = dvp;
    185 		ndp->ni_vp = dvp;
    186 		VREF(dvp);
    187 		/*VOP_LOCK(dvp);*/
    188 		return (0);
    189 	}
    190 
    191 #ifdef KERNFS_HAVE_ROOTDIR
    192 	if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
    193 		ndp->ni_dvp = dvp;
    194 		ndp->ni_vp = rootdir;
    195 		VREF(rootdir);
    196 		VOP_LOCK(rootdir);
    197 		return (0);
    198 	}
    199 #endif
    200 
    201 	/*
    202 	 * /kern/rootdev is the root device
    203 	 */
    204 	if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
    205 		if (!rootvp) {
    206 			error = ENOENT;
    207 			goto bad;
    208 		}
    209 		ndp->ni_dvp = dvp;
    210 		ndp->ni_vp = rootvp;
    211 		VREF(rootvp);
    212 		VOP_LOCK(rootvp);
    213 		return (0);
    214 	}
    215 
    216 	/*
    217 	 * /kern/rrootdev is the raw root device
    218 	 */
    219 	if (ndp->ni_namelen == 8 && bcmp(pname, "rrootdev", 7) == 0) {
    220 		if (!rrootdevvp) {
    221 			error = ENOENT;
    222 			goto bad;
    223 		}
    224 		ndp->ni_dvp = dvp;
    225 		ndp->ni_vp = rrootdevvp;
    226 		VREF(rrootdevvp);
    227 		VOP_LOCK(rrootdevvp);
    228 		return (0);
    229 	}
    230 
    231 	for (i = 0; i < nkernfs_targets; i++) {
    232 		struct kernfs_target *kt = &kernfs_targets[i];
    233 		if (ndp->ni_namelen == strlen(kt->kt_name) &&
    234 		    bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
    235 			error = 0;
    236 			break;
    237 		}
    238 	}
    239 
    240 #ifdef KERNFS_DIAGNOSTIC
    241 	printf("kernfs_lookup: i = %d, error = %d\n", i, error);
    242 #endif
    243 
    244 	if (error)
    245 		goto bad;
    246 
    247 #ifdef KERNFS_DIAGNOSTIC
    248 	printf("kernfs_lookup: allocate new vnode\n");
    249 #endif
    250 	error = getnewvnode(VT_KERNFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
    251 	if (error)
    252 		goto bad;
    253 	VTOKERN(fvp)->kf_kt = &kernfs_targets[i];
    254 	fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
    255 	ndp->ni_dvp = dvp;
    256 	ndp->ni_vp = fvp;
    257 #ifdef KERNFS_DIAGNOSTIC
    258 	printf("kernfs_lookup: newvp = %x\n", fvp);
    259 #endif
    260 	return (0);
    261 
    262 bad:;
    263 	ndp->ni_dvp = dvp;
    264 	ndp->ni_vp = NULL;
    265 #ifdef KERNFS_DIAGNOSTIC
    266 	printf("kernfs_lookup: error = %d\n", error);
    267 #endif
    268 	return (error);
    269 }
    270 
    271 kernfs_open(vp, mode, cred, p)
    272 	struct vnode *vp;
    273 	int mode;
    274 	struct ucred *cred;
    275 	struct proc *p;
    276 {
    277 	/* if access succeeded, this always does, too */
    278 
    279 	return (0);
    280 }
    281 
    282 /*
    283  * Check mode permission on target pointer. Mode is READ, WRITE or EXEC.
    284  * The mode is shifted to select the owner/group/other fields. The
    285  * super user is granted all permissions.
    286  */
    287 kernfs_access(vp, mode, cred, p)
    288 	struct vnode *vp;
    289 	register int mode;
    290 	struct ucred *cred;
    291 	struct proc *p;
    292 {
    293 	struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
    294 	register gid_t *gp;
    295 	int i, error;
    296 
    297 #ifdef KERN_DIAGNOSTIC
    298 	if (!VOP_ISLOCKED(vp)) {
    299 		vprint("kernfs_access: not locked", vp);
    300 		panic("kernfs_access: not locked");
    301 	}
    302 #endif
    303 	/*
    304 	 * If you're the super-user, you always get access.
    305 	 */
    306 	if (cred->cr_uid == 0)
    307 		return (0);
    308 	/*
    309 	 * Access check is based on only one of owner, group, public.
    310 	 * If not owner, then check group. If not a member of the
    311 	 * group, then check public access.
    312 	 */
    313 	if (cred->cr_uid != /* kt->kt_uid XXX */ 0) {
    314 		mode >>= 3;
    315 		gp = cred->cr_groups;
    316 		for (i = 0; i < cred->cr_ngroups; i++, gp++)
    317 			if (/* kt->kt_gid XXX */ 0 == *gp)
    318 				goto found;
    319 		mode >>= 3;
    320 found:
    321 		;
    322 	}
    323 	if ((kt->kt_perms & mode) == mode)
    324 		return (0);
    325 	return (EACCES);
    326 }
    327 
    328 kernfs_getattr(vp, vap, cred, p)
    329 	struct vnode *vp;
    330 	struct vattr *vap;
    331 	struct ucred *cred;
    332 	struct proc *p;
    333 {
    334 	int error = 0;
    335 	char strbuf[KSTRING];
    336 	struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
    337 
    338 	bzero((caddr_t) vap, sizeof(*vap));
    339 	vattr_null(vap);
    340 	vap->va_uid = kt->kt_uid;
    341 	vap->va_gid = kt->kt_gid;
    342 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
    343 	/* vap->va_qsize = 0; */
    344 	vap->va_blocksize = DEV_BSIZE;
    345 	microtime(&vap->va_atime);
    346 	vap->va_mtime = vap->va_atime;
    347 	vap->va_ctime = vap->va_ctime;
    348 	vap->va_gen = 0;
    349 	vap->va_flags = 0;
    350 	vap->va_rdev = 0;
    351 	/* vap->va_qbytes = 0; */
    352 	vap->va_bytes = 0;
    353 	vap->va_type = kt->kt_vtype;
    354 	vap->va_mode = kt->kt_perms;
    355 
    356 	if (vp->v_flag & VROOT) {
    357 #ifdef KERNFS_DIAGNOSTIC
    358 		printf("kernfs_getattr: stat rootdir\n");
    359 #endif
    360 		vap->va_nlink = 2;
    361 		vap->va_fileid = 2;
    362 		vap->va_size = DEV_BSIZE;
    363 	} else {
    364 #ifdef KERNFS_DIAGNOSTIC
    365 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
    366 #endif
    367 		vap->va_nlink = 1;
    368 		vap->va_fileid = 3 + (kt - kernfs_targets) / sizeof(*kt);
    369 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
    370 	}
    371 
    372 	vp->v_type = vap->va_type;
    373 #ifdef KERNFS_DIAGNOSTIC
    374 	printf("kernfs_getattr: return error %d\n", error);
    375 #endif
    376 	return (error);
    377 }
    378 
    379 
    380 /*
    381  * Change the mode on a file.
    382  */
    383 kernfs_chmod1(vp, mode, p)
    384 	register struct vnode *vp;
    385 	register int mode;
    386 	struct proc *p;
    387 {
    388 	register struct ucred *cred = p->p_ucred;
    389 	register struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
    390 	int error;
    391 
    392 	if ((mode & kt->kt_maxperms) != mode)	/* can't set ro var to rw */
    393 		return (EPERM);
    394 
    395 	if (cred->cr_uid != kt->kt_uid &&
    396 	    (error = suser(cred, &p->p_acflag)))
    397 		return (error);
    398 	if (cred->cr_uid) {
    399 		if (vp->v_type != VDIR && (mode & S_ISVTX))
    400 			return (EFTYPE);
    401 		if (!groupmember(kt->kt_gid, cred) && (mode & S_ISGID))
    402 			return (EPERM);
    403 	}
    404 	kt->kt_perms &= ~07777;
    405 	kt->kt_perms |= mode & 07777;
    406 /*	ip->i_flag |= ICHG;*/
    407 	return (0);
    408 }
    409 
    410 /*
    411  * Perform chown operation on kernfs_target kt
    412  */
    413 kernfs_chown1(vp, uid, gid, p)
    414 	register struct vnode *vp;
    415 	uid_t uid;
    416 	gid_t gid;
    417 	struct proc *p;
    418 {
    419 	register struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
    420 	register struct ucred *cred = p->p_ucred;
    421 	uid_t ouid;
    422 	gid_t ogid;
    423 	int error = 0;
    424 
    425 	if (uid == (u_short)VNOVAL)
    426 		uid = kt->kt_uid;
    427 	if (gid == (u_short)VNOVAL)
    428 		gid = kt->kt_gid;
    429 	/*
    430 	 * If we don't own the file, are trying to change the owner
    431 	 * of the file, or are not a member of the target group,
    432 	 * the caller must be superuser or the call fails.
    433 	 */
    434 	if ((cred->cr_uid != kt->kt_uid || uid != kt->kt_uid ||
    435 	    !groupmember((gid_t)gid, cred)) &&
    436 	    (error = suser(cred, &p->p_acflag)))
    437 		return (error);
    438 	ouid = kt->kt_uid;
    439 	ogid = kt->kt_gid;
    440 
    441 	kt->kt_uid = uid;
    442 	kt->kt_gid = gid;
    443 
    444 /*	if (ouid != uid || ogid != gid)
    445 		ip->i_flag |= ICHG;*/
    446 	if (ouid != uid && cred->cr_uid != 0)
    447 		kt->kt_perms &= ~S_ISUID;
    448 	if (ogid != gid && cred->cr_uid != 0)
    449 		kt->kt_perms &= ~S_ISGID;
    450 	return (0);
    451 }
    452 
    453 /*
    454  * Set attribute vnode op. called from several syscalls
    455  */
    456 kernfs_setattr(vp, vap, cred, p)
    457 	struct vnode *vp;
    458 	struct vattr *vap;
    459 	struct ucred *cred;
    460 	struct proc *p;
    461 {
    462 	int error = 0;
    463 
    464 	/*
    465 	 * Check for unsetable attributes.
    466 	 */
    467 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
    468 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
    469 	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
    470 	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
    471 		return (EINVAL);
    472 	}
    473 	/*
    474 	 * Go through the fields and update iff not VNOVAL.
    475 	 */
    476 	if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
    477 		if (error = kernfs_chown1(vp, vap->va_uid, vap->va_gid, p))
    478 			return (error);
    479 	if (vap->va_size != VNOVAL) {
    480 		if (vp->v_type == VDIR)
    481 			return (EISDIR);
    482 		/* else just nod and smile... */
    483 	}
    484 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
    485 /*		if (cred->cr_uid != ip->i_uid &&
    486 		    (error = suser(cred, &p->p_acflag)))
    487 			return (error);
    488 		if (vap->va_atime.tv_sec != VNOVAL)
    489 			ip->i_flag |= IACC;
    490 		if (vap->va_mtime.tv_sec != VNOVAL)
    491 			ip->i_flag |= IUPD;
    492 		ip->i_flag |= ICHG;
    493 		if (error = iupdat(ip, &vap->va_atime, &vap->va_mtime, 1))
    494 			return (error);
    495 */
    496 	}
    497 	if (vap->va_mode != (u_short)VNOVAL)
    498 		error = kernfs_chmod1(vp, (int)vap->va_mode, p);
    499 	if (vap->va_flags != VNOVAL) {
    500 /*		if (cred->cr_uid != ip->i_uid &&
    501 		    (error = suser(cred, &p->p_acflag)))
    502 			return (error);
    503 		if (cred->cr_uid == 0) {
    504 			ip->i_flags = vap->va_flags;
    505 		} else {
    506 			ip->i_flags &= 0xffff0000;
    507 			ip->i_flags |= (vap->va_flags & 0xffff);
    508 		}
    509 		ip->i_flag |= ICHG;
    510 */
    511 	}
    512 	return (error);
    513 }
    514 
    515 static int
    516 kernfs_read(vp, uio, ioflag, cred)
    517 	struct vnode *vp;
    518 	struct uio *uio;
    519 	int ioflag;
    520 	struct ucred *cred;
    521 {
    522 	struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
    523 	char strbuf[KSTRING];
    524 	int off = uio->uio_offset;
    525 	int len = 0;
    526 	char *cp = strbuf;
    527 	int error;
    528 #ifdef KERNFS_DIAGNOSTIC
    529 	printf("kern_read %s\n", kt->kt_name);
    530 #endif
    531 
    532 	error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
    533 	if (error)
    534 		return (error);
    535 	cp = strbuf + off;
    536 	len -= off;
    537 	return (uiomove(cp, len, uio));
    538 }
    539 
    540 static int
    541 kernfs_write(vp, uio, ioflag, cred)
    542 	struct vnode *vp;
    543 	struct uio *uio;
    544 	int ioflag;
    545 	struct ucred *cred;
    546 {
    547 	struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
    548 	char strbuf[KSTRING];
    549 	int len = uio->uio_resid;
    550 	char *cp = strbuf;
    551 	int xlen;
    552 	int error;
    553 
    554 	if (uio->uio_offset != 0)
    555 		return (EINVAL);
    556 
    557 	xlen = min(uio->uio_resid, KSTRING-1);
    558 	error = uiomove(strbuf, xlen, uio);
    559 	if (error)
    560 		return (error);
    561 
    562 	if (uio->uio_resid != 0)
    563 		return (EIO);
    564 
    565 	strbuf[xlen] = '\0';
    566 	return (kernfs_xwrite(kt, strbuf, xlen));
    567 }
    568 
    569 kernfs_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
    570 	struct vnode *vp;
    571 	struct uio *uio;
    572 	struct ucred *cred;
    573 	int *eofflagp;
    574 	u_int *cookies;
    575 	int ncookies;
    576 {
    577 	struct filedesc *fdp;
    578 	int i;
    579 	int error;
    580 
    581 	i = uio->uio_offset / UIO_MX;
    582 	error = 0;
    583 	while (uio->uio_resid > 0 && (!cookies || ncookies > 0)) {
    584 #ifdef KERNFS_DIAGNOSTIC
    585 		printf("kernfs_readdir: i = %d\n", i);
    586 #endif
    587 		if (i >= nkernfs_targets) {
    588 			*eofflagp = 1;
    589 			break;
    590 		}
    591 		{
    592 			struct direct d;
    593 			struct direct *dp = &d;
    594 			struct kernfs_target *kt = &kernfs_targets[i];
    595 
    596 			bzero((caddr_t) dp, UIO_MX);
    597 
    598 			dp->d_namlen = strlen(kt->kt_name);
    599 			bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
    600 
    601 #ifdef KERNFS_DIAGNOSTIC
    602 			printf("kernfs_readdir: name = %s, len = %d\n",
    603 					dp->d_name, dp->d_namlen);
    604 #endif
    605 			/*
    606 			 * Fill in the remaining fields
    607 			 */
    608 			dp->d_reclen = UIO_MX;
    609 			dp->d_ino = i + 3;
    610 			/*
    611 			 * And ship to userland
    612 			 */
    613 			error = uiomove((caddr_t) dp, UIO_MX, uio);
    614 			if (error)
    615 				break;
    616 			if (cookies) {
    617 				*cookies = (i + 1) * UIO_MX;
    618 				ncookies--;
    619 			}
    620 		}
    621 		i++;
    622 	}
    623 
    624 	uio->uio_offset = i * UIO_MX;
    625 
    626 	return (error);
    627 }
    628 
    629 kernfs_inactive(vp, p)
    630 	struct vnode *vp;
    631 	struct proc *p;
    632 {
    633 	/*
    634 	 * Clear out the v_type field to avoid
    635 	 * nasty things happening in vgone().
    636 	 */
    637 	vp->v_type = VNON;
    638 #ifdef KERNFS_DIAGNOSTIC
    639 	printf("kernfs_inactive(%x)\n", vp);
    640 #endif
    641 	return (0);
    642 }
    643 
    644 /*
    645  * Print out the contents of a kernfs vnode.
    646  */
    647 /* ARGSUSED */
    648 void
    649 kernfs_print(vp)
    650 	struct vnode *vp;
    651 {
    652 	printf("tag VT_KERNFS, kernfs vnode\n");
    653 }
    654 
    655 /*
    656  * kernfs vnode unsupported operation
    657  */
    658 kernfs_enotsupp()
    659 {
    660 	return (EOPNOTSUPP);
    661 }
    662 
    663 /*
    664  * kernfs "should never get here" operation
    665  */
    666 kernfs_badop()
    667 {
    668 	panic("kernfs: bad op");
    669 	/* NOTREACHED */
    670 }
    671 
    672 /*
    673  * kernfs vnode null operation
    674  */
    675 kernfs_nullop()
    676 {
    677 	return (0);
    678 }
    679 
    680 #define kernfs_create ((int (*) __P(( \
    681 		struct nameidata *ndp, \
    682 		struct vattr *vap, \
    683 		struct proc *p))) kernfs_enotsupp)
    684 #define kernfs_mknod ((int (*) __P(( \
    685 		struct nameidata *ndp, \
    686 		struct vattr *vap, \
    687 		struct ucred *cred, \
    688 		struct proc *p))) kernfs_enotsupp)
    689 #define kernfs_close ((int (*) __P(( \
    690 		struct vnode *vp, \
    691 		int fflag, \
    692 		struct ucred *cred, \
    693 		struct proc *p))) nullop)
    694 #define	kernfs_ioctl ((int (*) __P(( \
    695 		struct vnode *vp, \
    696 		int command, \
    697 		caddr_t data, \
    698 		int fflag, \
    699 		struct ucred *cred, \
    700 		struct proc *p))) kernfs_enotsupp)
    701 #define	kernfs_select ((int (*) __P(( \
    702 		struct vnode *vp, \
    703 		int which, \
    704 		int fflags, \
    705 		struct ucred *cred, \
    706 		struct proc *p))) kernfs_enotsupp)
    707 #define kernfs_mmap ((int (*) __P(( \
    708 		struct vnode *vp, \
    709 		int fflags, \
    710 		struct ucred *cred, \
    711 		struct proc *p))) kernfs_enotsupp)
    712 #define kernfs_fsync ((int (*) __P(( \
    713 		struct vnode *vp, \
    714 		int fflags, \
    715 		struct ucred *cred, \
    716 		int waitfor, \
    717 		struct proc *p))) nullop)
    718 #define kernfs_seek ((int (*) __P(( \
    719 		struct vnode *vp, \
    720 		off_t oldoff, \
    721 		off_t newoff, \
    722 		struct ucred *cred))) nullop)
    723 #define kernfs_remove ((int (*) __P(( \
    724 		struct nameidata *ndp, \
    725 		struct proc *p))) kernfs_enotsupp)
    726 #define kernfs_link ((int (*) __P(( \
    727 		struct vnode *vp, \
    728 		struct nameidata *ndp, \
    729 		struct proc *p))) kernfs_enotsupp)
    730 #define kernfs_rename ((int (*) __P(( \
    731 		struct nameidata *fndp, \
    732 		struct nameidata *tdnp, \
    733 		struct proc *p))) kernfs_enotsupp)
    734 #define kernfs_mkdir ((int (*) __P(( \
    735 		struct nameidata *ndp, \
    736 		struct vattr *vap, \
    737 		struct proc *p))) kernfs_enotsupp)
    738 #define kernfs_rmdir ((int (*) __P(( \
    739 		struct nameidata *ndp, \
    740 		struct proc *p))) kernfs_enotsupp)
    741 #define kernfs_symlink ((int (*) __P(( \
    742 		struct nameidata *ndp, \
    743 		struct vattr *vap, \
    744 		char *target, \
    745 		struct proc *p))) kernfs_enotsupp)
    746 #define kernfs_readlink ((int (*) __P(( \
    747 		struct vnode *vp, \
    748 		struct uio *uio, \
    749 		struct ucred *cred))) kernfs_enotsupp)
    750 #define kernfs_abortop ((int (*) __P(( \
    751 		struct nameidata *ndp))) nullop)
    752 #ifdef KERNFS_DIAGNOSTIC
    753 int kernfs_reclaim(vp)
    754 struct vnode *vp;
    755 {
    756 	printf("kernfs_reclaim(%x)\n", vp);
    757 	return (0);
    758 }
    759 #else
    760 #define kernfs_reclaim ((int (*) __P(( \
    761 		struct vnode *vp))) nullop)
    762 #endif
    763 #define	kernfs_lock ((int (*) __P(( \
    764 		struct vnode *vp))) nullop)
    765 #define kernfs_unlock ((int (*) __P(( \
    766 		struct vnode *vp))) nullop)
    767 #define	kernfs_bmap ((int (*) __P(( \
    768 		struct vnode *vp, \
    769 		daddr_t bn, \
    770 		struct vnode **vpp, \
    771 		daddr_t *bnp))) kernfs_badop)
    772 #define	kernfs_strategy ((int (*) __P(( \
    773 		struct buf *bp))) kernfs_badop)
    774 #define kernfs_islocked ((int (*) __P(( \
    775 		struct vnode *vp))) nullop)
    776 #define kernfs_advlock ((int (*) __P(( \
    777 		struct vnode *vp, \
    778 		caddr_t id, \
    779 		int op, \
    780 		struct flock *fl, \
    781 		int flags))) kernfs_enotsupp)
    782 
    783 struct vnodeops kernfs_vnodeops = {
    784 	kernfs_lookup,	/* lookup */
    785 	kernfs_create,	/* create */
    786 	kernfs_mknod,	/* mknod */
    787 	kernfs_open,	/* open */
    788 	kernfs_close,	/* close */
    789 	kernfs_access,	/* access */
    790 	kernfs_getattr,	/* getattr */
    791 	kernfs_setattr,	/* setattr */
    792 	kernfs_read,	/* read */
    793 	kernfs_write,	/* write */
    794 	kernfs_ioctl,	/* ioctl */
    795 	kernfs_select,	/* select */
    796 	kernfs_mmap,	/* mmap */
    797 	kernfs_fsync,	/* fsync */
    798 	kernfs_seek,	/* seek */
    799 	kernfs_remove,	/* remove */
    800 	kernfs_link,	/* link */
    801 	kernfs_rename,	/* rename */
    802 	kernfs_mkdir,	/* mkdir */
    803 	kernfs_rmdir,	/* rmdir */
    804 	kernfs_symlink,	/* symlink */
    805 	kernfs_readdir,	/* readdir */
    806 	kernfs_readlink,	/* readlink */
    807 	kernfs_abortop,	/* abortop */
    808 	kernfs_inactive,	/* inactive */
    809 	kernfs_reclaim,	/* reclaim */
    810 	kernfs_lock,	/* lock */
    811 	kernfs_unlock,	/* unlock */
    812 	kernfs_bmap,	/* bmap */
    813 	kernfs_strategy,	/* strategy */
    814 	kernfs_print,	/* print */
    815 	kernfs_islocked,	/* islocked */
    816 	kernfs_advlock,	/* advlock */
    817 };
    818