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