ia64/xen-unstable

changeset 4030:2a8ffe96dc3d

bitkeeper revision 1.1236.12.14 (422e47e9xlByLicbmgGE7DC-Dy4qJg)

Merge firebug.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-2.0-testing.bk
into firebug.cl.cam.ac.uk:/local/scratch/cl349/netbsd/xen-unstable.bk
author cl349@firebug.cl.cam.ac.uk
date Wed Mar 09 00:48:41 2005 +0000 (2005-03-09)
parents 7d769527a546 0b4083c2bdfd
children 77fbd1da5611
files .rootkeys netbsd-2.0-xen-sparse/Makefile netbsd-2.0-xen-sparse/mkbuildtree netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN netbsd-2.0-xen-sparse/sys/arch/xen/xen/hypervisor.c netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs.h netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs_vnops.c
line diff
     1.1 --- a/.rootkeys	Wed Mar 09 00:43:35 2005 +0000
     1.2 +++ b/.rootkeys	Wed Mar 09 00:48:41 2005 +0000
     1.3 @@ -311,6 +311,8 @@ 413cb3b46JnvK1UurZAubeQoFg1W-w netbsd-2.
     1.4  413cb3b5rIKB3TbyhK3pbNyVkYysqA netbsd-2.0-xen-sparse/sys/arch/xen/xen/xen_debug.c
     1.5  413cb3b5eKxnzoodEqaWn2wrPnHWnA netbsd-2.0-xen-sparse/sys/arch/xen/xen/xencons.c
     1.6  413cb3b5F56TvQWAmO5TsuzhtzLFPQ netbsd-2.0-xen-sparse/sys/arch/xen/xen/xenkbc.c
     1.7 +422e4430vKaHLOOGS7X-SUUe3EBCgw netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs.h
     1.8 +422e4430-gOD358H8nGGnNWes08Nng netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs_vnops.c
     1.9  413cb3b53nyOv1OIeDSsCXhBFDXvJA netbsd-2.0-xen-sparse/sys/nfs/files.nfs
    1.10  413aa1d0oNP8HXLvfPuMe6cSroUfSA patches/linux-2.6.10/agpgart.patch
    1.11  3f776bd1Hy9rn69ntXBhPReUFw9IEA tools/Makefile
     2.1 --- a/netbsd-2.0-xen-sparse/Makefile	Wed Mar 09 00:43:35 2005 +0000
     2.2 +++ b/netbsd-2.0-xen-sparse/Makefile	Wed Mar 09 00:48:41 2005 +0000
     2.3 @@ -7,18 +7,19 @@
     2.4  TOPDIR		?= $(shell pwd)
     2.5  NETBSD_RELEASE	?= $(patsubst netbsd-%-xen%,%,$(notdir $(TOPDIR)))
     2.6  NETBSD_VER	?= $(patsubst netbsd-%-xen%,%,$(notdir $(TOPDIR)))
     2.7 +NETBSD_KERNEL	?= XEN
     2.8  
     2.9  clean:
    2.10 -	@mkdir -p compile/XEN
    2.11 -	cd compile/XEN && TOPDIR=$(TOPDIR) NETBSD_VER=$(NETBSD_VER) ../../nbmake-xen cleandir
    2.12 +	@mkdir -p compile/$(NETBSD_KERNEL)
    2.13 +	cd compile/$(NETBSD_KERNEL) && TOPDIR=$(TOPDIR) NETBSD_VER=$(NETBSD_VER) ../../nbmake-xen cleandir
    2.14  
    2.15  config:
    2.16 -	@mkdir -p compile/XEN
    2.17 -	cd compile/XEN && TOPDIR=$(TOPDIR) NETBSD_VER=$(NETBSD_VER) ../../nbconfig-xen XEN
    2.18 +	@mkdir -p compile/$(NETBSD_KERNEL)
    2.19 +	cd compile/$(NETBSD_KERNEL) && TOPDIR=$(TOPDIR) NETBSD_VER=$(NETBSD_VER) ../../nbconfig-xen $(NETBSD_KERNEL)
    2.20  
    2.21  netbsd:
    2.22 -	cd compile/XEN && TOPDIR=$(TOPDIR) NETBSD_VER=$(NETBSD_VER) ../../nbmake-xen dependall
    2.23 +	cd compile/$(NETBSD_KERNEL) && TOPDIR=$(TOPDIR) NETBSD_VER=$(NETBSD_VER) ../../nbmake-xen dependall
    2.24  
    2.25  install:
    2.26  	@mkdir -p $(dir $(INSTALL_PATH)/$(INSTALL_NAME))
    2.27 -	install -c compile/XEN/netbsd $(INSTALL_PATH)/$(INSTALL_NAME)
    2.28 +	install -c compile/$(NETBSD_KERNEL)/netbsd $(INSTALL_PATH)/$(INSTALL_NAME)
     3.1 --- a/netbsd-2.0-xen-sparse/mkbuildtree	Wed Mar 09 00:43:35 2005 +0000
     3.2 +++ b/netbsd-2.0-xen-sparse/mkbuildtree	Wed Mar 09 00:48:41 2005 +0000
     3.3 @@ -85,6 +85,9 @@ popd >/dev/null
     3.4  # Get absolute path to the source directory
     3.5  AS=`pwd`
     3.6  
     3.7 +# Get name of sparse directory
     3.8 +SDN=$(basename $AS)
     3.9 +
    3.10  # Get path to source, relative to destination
    3.11  abs_to_rel ${AD} ${AS}
    3.12  RS=$DESTPATH
    3.13 @@ -96,12 +99,23 @@ for i in `find . -type f -o -type l` ; d
    3.14  cd ${AD}
    3.15  
    3.16  # Remove old symlinks
    3.17 -for i in `find . -type l`; do rm -f $i; done
    3.18 +find sys -type l | while read f
    3.19 +do
    3.20 +  case $(readlink $f) in
    3.21 +  */$SDN/*)
    3.22 +    rm -f $f
    3.23 +    ;;
    3.24 +  esac
    3.25 +done
    3.26  
    3.27 -# Create symlinks of files and directories which exist in the sparse source
    3.28 -relative_lndir ${RS}
    3.29 -rm -f mkbuildtree
    3.30 -
    3.31 +if [ -f ${AD}/BUILDING ]; then
    3.32 +  # Create symlinks of files and directories which exist in the sparse source
    3.33 +  (cd sys && relative_lndir ../${RS}/sys)
    3.34 +else
    3.35 +  # Create symlinks of files and directories which exist in the sparse source
    3.36 +  relative_lndir ${RS}
    3.37 +  rm -f mkbuildtree
    3.38 +fi
    3.39  
    3.40  # Create links to the shared definitions of the Xen interface
    3.41  rm -rf ${AD}/sys/arch/xen/include/xen-public
     4.1 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN	Wed Mar 09 00:43:35 2005 +0000
     4.2 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN	Wed Mar 09 00:48:41 2005 +0000
     4.3 @@ -153,7 +153,7 @@ include	"arch/xen/conf/GENERIC.local"
     4.4  pseudo-device	ccd		4	# concatenated/striped disk devices
     4.5  #pseudo-device	cgd		4	# cryptographic disk devices
     4.6  #pseudo-device	md		1	# memory disk device (ramdisk)
     4.7 -#pseudo-device	vnd		4	# disk-like interface to files
     4.8 +pseudo-device	vnd		4	# disk-like interface to files
     4.9  
    4.10  pseudo-device	bpfilter	8	# Berkeley packet filter
    4.11  pseudo-device	ipfilter		# IP filter (firewall) and NAT
     5.1 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/xen/hypervisor.c	Wed Mar 09 00:43:35 2005 +0000
     5.2 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/xen/hypervisor.c	Wed Mar 09 00:48:41 2005 +0000
     5.3 @@ -52,7 +52,6 @@
     5.4  #include <machine/hypervisor.h>
     5.5  #include <machine/evtchn.h>
     5.6  
     5.7 -#ifdef DOM0OPS
     5.8  #include <sys/dirent.h>
     5.9  #include <sys/stat.h>
    5.10  #include <sys/tree.h>
    5.11 @@ -60,7 +59,6 @@
    5.12  #include <miscfs/specfs/specdev.h>
    5.13  #include <miscfs/kernfs/kernfs.h>
    5.14  #include <machine/kernfs_machdep.h>
    5.15 -#endif
    5.16  
    5.17  #if NXENNET > 0
    5.18  #include <net/if.h>
    5.19 @@ -187,9 +185,9 @@ hypervisor_attach(parent, self, aux)
    5.20  	hac.hac_xennpx.xa_device = "npx";
    5.21  	config_found(self, &hac.hac_xennpx, hypervisor_print);
    5.22  #endif
    5.23 +	xenkernfs_init();
    5.24  #ifdef DOM0OPS
    5.25  	if (xen_start_info.flags & SIF_PRIVILEGED) {
    5.26 -		xenkernfs_init();
    5.27  		xenprivcmd_init();
    5.28  		xenmachmem_init();
    5.29  		xenvfr_init();
    5.30 @@ -222,8 +220,7 @@ hypervisor_notify_via_evtchn(unsigned in
    5.31  	(void)HYPERVISOR_event_channel_op(&op);
    5.32  }
    5.33  
    5.34 -#ifdef DOM0OPS
    5.35 -
    5.36 +#define	READ_MODE	(S_IRUSR|S_IRGRP|S_IROTH)
    5.37  #define DIR_MODE	(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
    5.38  
    5.39  kernfs_parentdir_t *kernxen_pkt;
    5.40 @@ -237,5 +234,9 @@ xenkernfs_init()
    5.41  	KERNFS_INITENTRY(dkt, DT_DIR, "xen", NULL, KFSsubdir, VDIR, DIR_MODE);
    5.42  	kernfs_addentry(NULL, dkt);
    5.43  	kernxen_pkt = KERNFS_ENTOPARENTDIR(dkt);
    5.44 +
    5.45 +	KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
    5.46 +	KERNFS_INITENTRY(dkt, DT_REG, "cmdline", xen_start_info.cmd_line,
    5.47 +	    KFSstring, VREG, READ_MODE);
    5.48 +	kernfs_addentry(kernxen_pkt, dkt);
    5.49  }
    5.50 -#endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs.h	Wed Mar 09 00:48:41 2005 +0000
     6.3 @@ -0,0 +1,205 @@
     6.4 +/*	$NetBSD: kernfs.h,v 1.20.2.3 2004/05/23 10:46:05 tron Exp $	*/
     6.5 +
     6.6 +/*
     6.7 + * Copyright (c) 1992, 1993
     6.8 + *	The Regents of the University of California.  All rights reserved.
     6.9 + *
    6.10 + * This code is derived from software donated to Berkeley by
    6.11 + * Jan-Simon Pendry.
    6.12 + *
    6.13 + * Redistribution and use in source and binary forms, with or without
    6.14 + * modification, are permitted provided that the following conditions
    6.15 + * are met:
    6.16 + * 1. Redistributions of source code must retain the above copyright
    6.17 + *    notice, this list of conditions and the following disclaimer.
    6.18 + * 2. Redistributions in binary form must reproduce the above copyright
    6.19 + *    notice, this list of conditions and the following disclaimer in the
    6.20 + *    documentation and/or other materials provided with the distribution.
    6.21 + * 3. Neither the name of the University nor the names of its contributors
    6.22 + *    may be used to endorse or promote products derived from this software
    6.23 + *    without specific prior written permission.
    6.24 + *
    6.25 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    6.26 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    6.27 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    6.28 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    6.29 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    6.30 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    6.31 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    6.32 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    6.33 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    6.34 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    6.35 + * SUCH DAMAGE.
    6.36 + *
    6.37 + *	@(#)kernfs.h	8.6 (Berkeley) 3/29/95
    6.38 + */
    6.39 +
    6.40 +#define	_PATH_KERNFS	"/kern"		/* Default mountpoint */
    6.41 +
    6.42 +#ifdef _KERNEL
    6.43 +#include <sys/queue.h>
    6.44 +
    6.45 +/*
    6.46 + * The different types of node in a kernfs filesystem
    6.47 + */
    6.48 +typedef enum {
    6.49 +	KFSkern,		/* the filesystem itself (.) */
    6.50 +	KFSroot,		/* the filesystem root (..) */
    6.51 +	KFSnull,		/* none aplicable */
    6.52 +	KFStime,		/* boottime */
    6.53 +	KFSint,			/* integer */
    6.54 +	KFSstring,		/* string */
    6.55 +	KFShostname,	/* hostname */
    6.56 +	KFSavenrun,		/* loadavg */
    6.57 +	KFSdevice,		/* device file (rootdev/rrootdev) */
    6.58 +	KFSmsgbuf,		/* msgbuf */
    6.59 +	KFSipsecsadir,	/* ipsec security association (top dir) */
    6.60 +	KFSipsecspdir,	/* ipsec security policy (top dir) */
    6.61 +	KFSipsecsa,		/* ipsec security association entry */
    6.62 +	KFSipsecsp,		/* ipsec security policy entry */
    6.63 +	KFSsubdir,		/* directory */
    6.64 +	KFSlasttype,		/* last used type */
    6.65 +	KFSmaxtype = (1<<6) - 1	/* last possible type */
    6.66 +} kfstype;
    6.67 +
    6.68 +/*
    6.69 + * Control data for the kern file system.
    6.70 + */
    6.71 +struct kern_target {
    6.72 +	u_char		kt_type;
    6.73 +	u_char		kt_namlen;
    6.74 +	const char	*kt_name;
    6.75 +	void		*kt_data;
    6.76 +	kfstype		kt_tag;
    6.77 +	u_char		kt_vtype;
    6.78 +	mode_t		kt_mode;
    6.79 +};
    6.80 +
    6.81 +struct dyn_kern_target {
    6.82 +	struct kern_target		dkt_kt;
    6.83 +	SIMPLEQ_ENTRY(dyn_kern_target)	dkt_queue;
    6.84 +};
    6.85 +
    6.86 +struct kernfs_subdir {
    6.87 +	SIMPLEQ_HEAD(,dyn_kern_target)	ks_entries;
    6.88 +	unsigned int			ks_nentries;
    6.89 +	unsigned int			ks_dirs;
    6.90 +	const struct kern_target	*ks_parent;
    6.91 +};
    6.92 +
    6.93 +struct kernfs_node {
    6.94 +	LIST_ENTRY(kernfs_node) kfs_hash; /* hash chain */
    6.95 +	TAILQ_ENTRY(kernfs_node) kfs_list; /* flat list */
    6.96 +	struct vnode	*kfs_vnode;	/* vnode associated with this pfsnode */
    6.97 +	kfstype		kfs_type;	/* type of procfs node */
    6.98 +	mode_t		kfs_mode;	/* mode bits for stat() */
    6.99 +	long		kfs_fileno;	/* unique file id */
   6.100 +	u_int32_t	kfs_value;	/* SA id or SP id (KFSint) */
   6.101 +	const struct kern_target *kfs_kt;
   6.102 +	void		*kfs_v;		/* pointer to secasvar/secpolicy/mbuf */
   6.103 +	long		kfs_cookie;	/* fileno cookie */
   6.104 +};
   6.105 +
   6.106 +struct kernfs_mount {
   6.107 +	TAILQ_HEAD(, kernfs_node) nodelist;
   6.108 +	long fileno_cookie;
   6.109 +};
   6.110 +
   6.111 +#define UIO_MX	32
   6.112 +
   6.113 +#define KERNFS_FILENO(kt, typ, cookie) \
   6.114 +	((kt >= &kern_targets[0] && kt < &kern_targets[static_nkern_targets]) \
   6.115 +	    ? 2 + ((kt) - &kern_targets[0]) \
   6.116 +	      : (((cookie + 1) << 6) | (typ)))
   6.117 +#define KERNFS_TYPE_FILENO(typ, cookie) \
   6.118 +	(((cookie + 1) << 6) | (typ))
   6.119 +
   6.120 +#define VFSTOKERNFS(mp)	((struct kernfs_mount *)((mp)->mnt_data))
   6.121 +#define	VTOKERN(vp)	((struct kernfs_node *)(vp)->v_data)
   6.122 +#define KERNFSTOV(kfs)	((kfs)->kfs_vnode)
   6.123 +
   6.124 +extern const struct kern_target kern_targets[];
   6.125 +extern int nkern_targets;
   6.126 +extern const int static_nkern_targets;
   6.127 +extern int (**kernfs_vnodeop_p) __P((void *));
   6.128 +extern struct vfsops kernfs_vfsops;
   6.129 +extern dev_t rrootdev;
   6.130 +
   6.131 +struct secasvar;
   6.132 +struct secpolicy;
   6.133 +
   6.134 +int kernfs_root __P((struct mount *, struct vnode **));
   6.135 +
   6.136 +void kernfs_hashinit __P((void));
   6.137 +void kernfs_hashreinit __P((void));
   6.138 +void kernfs_hashdone __P((void));
   6.139 +int kernfs_freevp __P((struct vnode *));
   6.140 +int kernfs_allocvp __P((struct mount *, struct vnode **, kfstype,
   6.141 +	const struct kern_target *, u_int32_t));
   6.142 +
   6.143 +void kernfs_revoke_sa __P((struct secasvar *));
   6.144 +void kernfs_revoke_sp __P((struct secpolicy *));
   6.145 +
   6.146 +/*
   6.147 + * Data types for the kernfs file operations.
   6.148 + */
   6.149 +typedef enum {
   6.150 +	KERNFS_XREAD,
   6.151 +	KERNFS_XWRITE,
   6.152 +	KERNFS_FILEOP_CLOSE,
   6.153 +	KERNFS_FILEOP_GETATTR,
   6.154 +	KERNFS_FILEOP_IOCTL,
   6.155 +	KERNFS_FILEOP_MMAP,
   6.156 +	KERNFS_FILEOP_OPEN,
   6.157 +	KERNFS_FILEOP_READ,
   6.158 +	KERNFS_FILEOP_WRITE,
   6.159 +} kfsfileop;
   6.160 +
   6.161 +struct kernfs_fileop {
   6.162 +	kfstype				kf_type;
   6.163 +	kfsfileop			kf_fileop;
   6.164 +	union {
   6.165 +		void			*_kf_genop;
   6.166 +		int			(*_kf_vop)(void *);
   6.167 +		int			(*_kf_xread)
   6.168 +			(const struct kernfs_node *, int, char **, size_t,
   6.169 +			 size_t *);
   6.170 +		int			(*_kf_xwrite)
   6.171 +			(const struct kernfs_node *, char *, size_t);
   6.172 +	} _kf_opfn;
   6.173 +	SPLAY_ENTRY(kernfs_fileop)	kf_node;
   6.174 +};
   6.175 +#define	kf_genop	_kf_opfn
   6.176 +#define	kf_vop		_kf_opfn._kf_vop
   6.177 +#define	kf_xwrite	_kf_opfn._kf_xwrite
   6.178 +#define	kf_xread	_kf_opfn._kf_xread
   6.179 +
   6.180 +typedef struct kern_target kernfs_parentdir_t;
   6.181 +typedef struct dyn_kern_target kernfs_entry_t;
   6.182 +
   6.183 +/*
   6.184 + * Functions for adding kernfs datatypes and nodes.
   6.185 + */
   6.186 +kfstype kernfs_alloctype(int, const struct kernfs_fileop *);
   6.187 +#define	KERNFS_ALLOCTYPE(kf) kernfs_alloctype(sizeof((kf)) / \
   6.188 +	sizeof((kf)[0]), (kf))
   6.189 +#define	KERNFS_ALLOCENTRY(dkt, m_type, m_flags)				\
   6.190 +	dkt = (struct dyn_kern_target *)malloc(				\
   6.191 +		sizeof(struct dyn_kern_target), (m_type), (m_flags))
   6.192 +#define	KERNFS_INITENTRY(dkt, type, name, data, tag, vtype, mode) do {	\
   6.193 +	(dkt)->dkt_kt.kt_type = (type);					\
   6.194 +	(dkt)->dkt_kt.kt_namlen = strlen((name));			\
   6.195 +	(dkt)->dkt_kt.kt_name = (name);					\
   6.196 +	(dkt)->dkt_kt.kt_data = (data);					\
   6.197 +	(dkt)->dkt_kt.kt_tag = (tag);					\
   6.198 +	(dkt)->dkt_kt.kt_vtype = (vtype);				\
   6.199 +	(dkt)->dkt_kt.kt_mode = (mode);					\
   6.200 +} while (/*CONSTCOND*/0)
   6.201 +#define	KERNFS_ENTOPARENTDIR(dkt) &(dkt)->dkt_kt
   6.202 +int kernfs_addentry __P((kernfs_parentdir_t *, kernfs_entry_t *));
   6.203 +
   6.204 +#ifdef SYSCTL_SETUP_PROTO
   6.205 +SYSCTL_SETUP_PROTO(sysctl_vfs_kernfs_setup);
   6.206 +#endif /* SYSCTL_SETUP_PROTO */
   6.207 +
   6.208 +#endif /* _KERNEL */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs_vnops.c	Wed Mar 09 00:48:41 2005 +0000
     7.3 @@ -0,0 +1,1583 @@
     7.4 +/*	$NetBSD: kernfs_vnops.c,v 1.98.2.3 2004/05/15 13:35:27 tron Exp $	*/
     7.5 +
     7.6 +/*
     7.7 + * Copyright (c) 1992, 1993
     7.8 + *	The Regents of the University of California.  All rights reserved.
     7.9 + *
    7.10 + * This code is derived from software donated to Berkeley by
    7.11 + * Jan-Simon Pendry.
    7.12 + *
    7.13 + * Redistribution and use in source and binary forms, with or without
    7.14 + * modification, are permitted provided that the following conditions
    7.15 + * are met:
    7.16 + * 1. Redistributions of source code must retain the above copyright
    7.17 + *    notice, this list of conditions and the following disclaimer.
    7.18 + * 2. Redistributions in binary form must reproduce the above copyright
    7.19 + *    notice, this list of conditions and the following disclaimer in the
    7.20 + *    documentation and/or other materials provided with the distribution.
    7.21 + * 3. Neither the name of the University nor the names of its contributors
    7.22 + *    may be used to endorse or promote products derived from this software
    7.23 + *    without specific prior written permission.
    7.24 + *
    7.25 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    7.26 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    7.27 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    7.28 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    7.29 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    7.30 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    7.31 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    7.32 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    7.33 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    7.34 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    7.35 + * SUCH DAMAGE.
    7.36 + *
    7.37 + *	@(#)kernfs_vnops.c	8.15 (Berkeley) 5/21/95
    7.38 + */
    7.39 +
    7.40 +/*
    7.41 + * Kernel parameter filesystem (/kern)
    7.42 + */
    7.43 +
    7.44 +#include <sys/cdefs.h>
    7.45 +__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.98.2.3 2004/05/15 13:35:27 tron Exp $");
    7.46 +
    7.47 +#ifdef _KERNEL_OPT
    7.48 +#include "opt_ipsec.h"
    7.49 +#endif
    7.50 +
    7.51 +#include <sys/param.h>
    7.52 +#include <sys/systm.h>
    7.53 +#include <sys/kernel.h>
    7.54 +#include <sys/vmmeter.h>
    7.55 +#include <sys/time.h>
    7.56 +#include <sys/proc.h>
    7.57 +#include <sys/vnode.h>
    7.58 +#include <sys/malloc.h>
    7.59 +#include <sys/file.h>
    7.60 +#include <sys/stat.h>
    7.61 +#include <sys/mount.h>
    7.62 +#include <sys/namei.h>
    7.63 +#include <sys/buf.h>
    7.64 +#include <sys/dirent.h>
    7.65 +#include <sys/msgbuf.h>
    7.66 +
    7.67 +#include <miscfs/genfs/genfs.h>
    7.68 +#include <miscfs/kernfs/kernfs.h>
    7.69 +
    7.70 +#ifdef IPSEC
    7.71 +#include <sys/mbuf.h>
    7.72 +#include <net/route.h>
    7.73 +#include <netinet/in.h>
    7.74 +#include <netinet6/ipsec.h>
    7.75 +#include <netkey/key.h>
    7.76 +#endif
    7.77 +
    7.78 +#include <uvm/uvm_extern.h>
    7.79 +
    7.80 +#define KSTRING	256		/* Largest I/O available via this filesystem */
    7.81 +#define	UIO_MX 32
    7.82 +
    7.83 +#define	READ_MODE	(S_IRUSR|S_IRGRP|S_IROTH)
    7.84 +#define	WRITE_MODE	(S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
    7.85 +#define	UREAD_MODE	(S_IRUSR)
    7.86 +#define	DIR_MODE	(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
    7.87 +#define	UDIR_MODE	(S_IRUSR|S_IXUSR)
    7.88 +
    7.89 +#define N(s) sizeof(s)-1, s
    7.90 +const struct kern_target kern_targets[] = {
    7.91 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
    7.92 +     /*        name            data          tag           type  ro/rw */
    7.93 +     { DT_DIR, N("."),         0,            KFSkern,        VDIR, DIR_MODE   },
    7.94 +     { DT_DIR, N(".."),        0,            KFSroot,        VDIR, DIR_MODE   },
    7.95 +     { DT_REG, N("boottime"),  &boottime.tv_sec, KFSint,     VREG, READ_MODE  },
    7.96 +			/* XXX cast away const */
    7.97 +     { DT_REG, N("copyright"), (void *)copyright,
    7.98 +     					     KFSstring,      VREG, READ_MODE  },
    7.99 +     { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },
   7.100 +     { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },
   7.101 +#ifdef IPSEC
   7.102 +     { DT_DIR, N("ipsecsa"),   0,	     KFSipsecsadir,  VDIR, UDIR_MODE  },
   7.103 +     { DT_DIR, N("ipsecsp"),   0,	     KFSipsecspdir,  VDIR, UDIR_MODE  },
   7.104 +#endif
   7.105 +     { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },
   7.106 +     { DT_REG, N("msgbuf"),    0,	     KFSmsgbuf,      VREG, READ_MODE  },
   7.107 +     { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },
   7.108 +     { DT_REG, N("physmem"),   &physmem,     KFSint,         VREG, READ_MODE  },
   7.109 +#if 0
   7.110 +     { DT_DIR, N("root"),      0,            KFSnull,        VDIR, DIR_MODE   },
   7.111 +#endif
   7.112 +     { DT_BLK, N("rootdev"),   &rootdev,     KFSdevice,      VBLK, READ_MODE  },
   7.113 +     { DT_CHR, N("rrootdev"),  &rrootdev,    KFSdevice,      VCHR, READ_MODE  },
   7.114 +     { DT_REG, N("time"),      0,            KFStime,        VREG, READ_MODE  },
   7.115 +			/* XXX cast away const */
   7.116 +     { DT_REG, N("version"),   (void *)version,
   7.117 +     					     KFSstring,      VREG, READ_MODE  },
   7.118 +};
   7.119 +const struct kern_target subdir_targets[] = {
   7.120 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
   7.121 +     /*        name            data          tag           type  ro/rw */
   7.122 +     { DT_DIR, N("."),         0,            KFSsubdir,      VDIR, DIR_MODE   },
   7.123 +     { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
   7.124 +};
   7.125 +#ifdef IPSEC
   7.126 +const struct kern_target ipsecsa_targets[] = {
   7.127 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
   7.128 +     /*        name            data          tag           type  ro/rw */
   7.129 +     { DT_DIR, N("."),         0,            KFSipsecsadir,  VDIR, DIR_MODE   },
   7.130 +     { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
   7.131 +};
   7.132 +const struct kern_target ipsecsp_targets[] = {
   7.133 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
   7.134 +     /*        name            data          tag           type  ro/rw */
   7.135 +     { DT_DIR, N("."),         0,            KFSipsecspdir,  VDIR, DIR_MODE   },
   7.136 +     { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
   7.137 +};
   7.138 +const struct kern_target ipsecsa_kt =
   7.139 +     { DT_DIR, N(""),          0,            KFSipsecsa,     VREG, UREAD_MODE };
   7.140 +const struct kern_target ipsecsp_kt =
   7.141 +     { DT_DIR, N(""),          0,            KFSipsecsp,     VREG, UREAD_MODE };
   7.142 +#endif
   7.143 +#undef N
   7.144 +SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
   7.145 +	SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
   7.146 +int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
   7.147 +const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
   7.148 +#ifdef IPSEC
   7.149 +int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
   7.150 +int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
   7.151 +int nkern_dirs = 4; /* 2 extra subdirs */
   7.152 +#else
   7.153 +int nkern_dirs = 2;
   7.154 +#endif
   7.155 +
   7.156 +int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
   7.157 +int kernfs_try_xread(kfstype, const struct kernfs_node *, int, char **,
   7.158 +    size_t, size_t *, int);
   7.159 +int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
   7.160 +    size_t, int);
   7.161 +
   7.162 +static int kernfs_default_xread(void *v);
   7.163 +static int kernfs_default_xwrite(void *v);
   7.164 +static int kernfs_default_fileop_getattr(void *);
   7.165 +
   7.166 +/* must include all fileop's */
   7.167 +const struct kernfs_fileop kernfs_default_fileops[] = {
   7.168 +  { .kf_fileop = KERNFS_XREAD },
   7.169 +  { .kf_fileop = KERNFS_XWRITE },
   7.170 +  { .kf_fileop = KERNFS_FILEOP_OPEN },
   7.171 +  { .kf_fileop = KERNFS_FILEOP_GETATTR,
   7.172 +    .kf_genop = {kernfs_default_fileop_getattr} },
   7.173 +  { .kf_fileop = KERNFS_FILEOP_IOCTL },
   7.174 +  { .kf_fileop = KERNFS_FILEOP_MMAP },
   7.175 +  { .kf_fileop = KERNFS_FILEOP_CLOSE },
   7.176 +  { .kf_fileop = KERNFS_FILEOP_READ, .kf_genop = {kernfs_default_xread} },
   7.177 +  { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_genop = {kernfs_default_xwrite} },
   7.178 +};
   7.179 +
   7.180 +int	kernfs_lookup	__P((void *));
   7.181 +#define	kernfs_create	genfs_eopnotsupp
   7.182 +#define	kernfs_mknod	genfs_eopnotsupp
   7.183 +int	kernfs_open	__P((void *));
   7.184 +int	kernfs_close	__P((void *));
   7.185 +int	kernfs_access	__P((void *));
   7.186 +int	kernfs_getattr	__P((void *));
   7.187 +int	kernfs_setattr	__P((void *));
   7.188 +int	kernfs_read	__P((void *));
   7.189 +int	kernfs_write	__P((void *));
   7.190 +#define	kernfs_fcntl	genfs_fcntl
   7.191 +int	kernfs_ioctl	__P((void *));
   7.192 +#define	kernfs_poll	genfs_poll
   7.193 +#define kernfs_revoke	genfs_revoke
   7.194 +int	kernfs_mmap	__P((void *));
   7.195 +#define	kernfs_fsync	genfs_nullop
   7.196 +#define	kernfs_seek	genfs_nullop
   7.197 +#define	kernfs_remove	genfs_eopnotsupp
   7.198 +int	kernfs_link	__P((void *));
   7.199 +#define	kernfs_rename	genfs_eopnotsupp
   7.200 +#define	kernfs_mkdir	genfs_eopnotsupp
   7.201 +#define	kernfs_rmdir	genfs_eopnotsupp
   7.202 +int	kernfs_symlink	__P((void *));
   7.203 +int	kernfs_readdir	__P((void *));
   7.204 +#define	kernfs_readlink	genfs_eopnotsupp
   7.205 +#define	kernfs_abortop	genfs_abortop
   7.206 +int	kernfs_inactive	__P((void *));
   7.207 +int	kernfs_reclaim	__P((void *));
   7.208 +#define	kernfs_lock	genfs_lock
   7.209 +#define	kernfs_unlock	genfs_unlock
   7.210 +#define	kernfs_bmap	genfs_badop
   7.211 +#define	kernfs_strategy	genfs_badop
   7.212 +int	kernfs_print	__P((void *));
   7.213 +#define	kernfs_islocked	genfs_islocked
   7.214 +int	kernfs_pathconf	__P((void *));
   7.215 +#define	kernfs_advlock	genfs_einval
   7.216 +#define	kernfs_blkatoff	genfs_eopnotsupp
   7.217 +#define	kernfs_valloc	genfs_eopnotsupp
   7.218 +#define	kernfs_vfree	genfs_nullop
   7.219 +#define	kernfs_truncate	genfs_eopnotsupp
   7.220 +#define	kernfs_update	genfs_nullop
   7.221 +#define	kernfs_bwrite	genfs_eopnotsupp
   7.222 +#define	kernfs_putpages	genfs_putpages
   7.223 +
   7.224 +static int	kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *));
   7.225 +static int	kernfs_xwrite __P((const struct kernfs_node *, char *, size_t));
   7.226 +
   7.227 +int (**kernfs_vnodeop_p) __P((void *));
   7.228 +const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
   7.229 +	{ &vop_default_desc, vn_default_error },
   7.230 +	{ &vop_lookup_desc, kernfs_lookup },		/* lookup */
   7.231 +	{ &vop_create_desc, kernfs_create },		/* create */
   7.232 +	{ &vop_mknod_desc, kernfs_mknod },		/* mknod */
   7.233 +	{ &vop_open_desc, kernfs_open },		/* open */
   7.234 +	{ &vop_close_desc, kernfs_close },		/* close */
   7.235 +	{ &vop_access_desc, kernfs_access },		/* access */
   7.236 +	{ &vop_getattr_desc, kernfs_getattr },		/* getattr */
   7.237 +	{ &vop_setattr_desc, kernfs_setattr },		/* setattr */
   7.238 +	{ &vop_read_desc, kernfs_read },		/* read */
   7.239 +	{ &vop_write_desc, kernfs_write },		/* write */
   7.240 +	{ &vop_fcntl_desc, kernfs_fcntl },		/* fcntl */
   7.241 +	{ &vop_ioctl_desc, kernfs_ioctl },		/* ioctl */
   7.242 +	{ &vop_poll_desc, kernfs_poll },		/* poll */
   7.243 +	{ &vop_revoke_desc, kernfs_revoke },		/* revoke */
   7.244 +	{ &vop_mmap_desc, kernfs_mmap },		/* mmap */
   7.245 +	{ &vop_fsync_desc, kernfs_fsync },		/* fsync */
   7.246 +	{ &vop_seek_desc, kernfs_seek },		/* seek */
   7.247 +	{ &vop_remove_desc, kernfs_remove },		/* remove */
   7.248 +	{ &vop_link_desc, kernfs_link },		/* link */
   7.249 +	{ &vop_rename_desc, kernfs_rename },		/* rename */
   7.250 +	{ &vop_mkdir_desc, kernfs_mkdir },		/* mkdir */
   7.251 +	{ &vop_rmdir_desc, kernfs_rmdir },		/* rmdir */
   7.252 +	{ &vop_symlink_desc, kernfs_symlink },		/* symlink */
   7.253 +	{ &vop_readdir_desc, kernfs_readdir },		/* readdir */
   7.254 +	{ &vop_readlink_desc, kernfs_readlink },	/* readlink */
   7.255 +	{ &vop_abortop_desc, kernfs_abortop },		/* abortop */
   7.256 +	{ &vop_inactive_desc, kernfs_inactive },	/* inactive */
   7.257 +	{ &vop_reclaim_desc, kernfs_reclaim },		/* reclaim */
   7.258 +	{ &vop_lock_desc, kernfs_lock },		/* lock */
   7.259 +	{ &vop_unlock_desc, kernfs_unlock },		/* unlock */
   7.260 +	{ &vop_bmap_desc, kernfs_bmap },		/* bmap */
   7.261 +	{ &vop_strategy_desc, kernfs_strategy },	/* strategy */
   7.262 +	{ &vop_print_desc, kernfs_print },		/* print */
   7.263 +	{ &vop_islocked_desc, kernfs_islocked },	/* islocked */
   7.264 +	{ &vop_pathconf_desc, kernfs_pathconf },	/* pathconf */
   7.265 +	{ &vop_advlock_desc, kernfs_advlock },		/* advlock */
   7.266 +	{ &vop_blkatoff_desc, kernfs_blkatoff },	/* blkatoff */
   7.267 +	{ &vop_valloc_desc, kernfs_valloc },		/* valloc */
   7.268 +	{ &vop_vfree_desc, kernfs_vfree },		/* vfree */
   7.269 +	{ &vop_truncate_desc, kernfs_truncate },	/* truncate */
   7.270 +	{ &vop_update_desc, kernfs_update },		/* update */
   7.271 +	{ &vop_bwrite_desc, kernfs_bwrite },		/* bwrite */
   7.272 +	{ &vop_putpages_desc, kernfs_putpages },	/* putpages */
   7.273 +	{ NULL, NULL }
   7.274 +};
   7.275 +const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
   7.276 +	{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
   7.277 +
   7.278 +static __inline int
   7.279 +kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
   7.280 +{
   7.281 +	if (a->kf_type < b->kf_type)
   7.282 +		return -1;
   7.283 +	if (a->kf_type > b->kf_type)
   7.284 +		return 1;
   7.285 +	if (a->kf_fileop < b->kf_fileop)
   7.286 +		return -1;
   7.287 +	if (a->kf_fileop > b->kf_fileop)
   7.288 +		return 1;
   7.289 +	return (0);
   7.290 +}
   7.291 +
   7.292 +SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
   7.293 +	SPLAY_INITIALIZER(kfsfileoptree);
   7.294 +SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
   7.295 +SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
   7.296 +
   7.297 +kfstype
   7.298 +kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
   7.299 +{
   7.300 +	static u_char nextfreetype = KFSlasttype;
   7.301 +	struct kernfs_fileop *dkf, *fkf, skf;
   7.302 +	int i;
   7.303 +
   7.304 +	/* XXX need to keep track of dkf's memory if we support
   7.305 +           deallocating types */
   7.306 +	dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
   7.307 +	memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
   7.308 +
   7.309 +	for (i = 0; i < sizeof(kernfs_default_fileops) /
   7.310 +		     sizeof(kernfs_default_fileops[0]); i++) {
   7.311 +		dkf[i].kf_type = nextfreetype;
   7.312 +		SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
   7.313 +	}
   7.314 +
   7.315 +	for (i = 0; i < nkf; i++) {
   7.316 +		skf.kf_type = nextfreetype;
   7.317 +		skf.kf_fileop = kf[i].kf_fileop;
   7.318 +		if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
   7.319 +			fkf->kf_genop = kf[i].kf_genop;
   7.320 +	}
   7.321 +
   7.322 +	return nextfreetype++;
   7.323 +}
   7.324 +
   7.325 +int
   7.326 +kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
   7.327 +{
   7.328 +	const struct kernfs_fileop *kf;
   7.329 +	struct kernfs_fileop skf;
   7.330 +
   7.331 +	skf.kf_type = type;
   7.332 +	skf.kf_fileop = fileop;
   7.333 +	kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
   7.334 +	if (kf == NULL)
   7.335 +		kf = &kernfs_default_fileops[fileop];
   7.336 +	if (kf->kf_vop)
   7.337 +		return kf->kf_vop(v);
   7.338 +	return error;
   7.339 +}
   7.340 +
   7.341 +int
   7.342 +kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, int off,
   7.343 +    char **bufp, size_t len, size_t *wrlen, int error)
   7.344 +{
   7.345 +	const struct kernfs_fileop *kf;
   7.346 +	struct kernfs_fileop skf;
   7.347 +
   7.348 +	skf.kf_type = type;
   7.349 +	skf.kf_fileop = KERNFS_XREAD;
   7.350 +	kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
   7.351 +	if (kf == NULL)
   7.352 +		kf = &kernfs_default_fileops[KERNFS_XREAD];
   7.353 +	if (kf->kf_xread)
   7.354 +		return kf->kf_xread(kfs, off, bufp, len, wrlen);
   7.355 +	*wrlen = 0;
   7.356 +	return error;
   7.357 +}
   7.358 +
   7.359 +int
   7.360 +kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *buf,
   7.361 +    size_t len, int error)
   7.362 +{
   7.363 +	const struct kernfs_fileop *kf;
   7.364 +	struct kernfs_fileop skf;
   7.365 +
   7.366 +	skf.kf_type = type;
   7.367 +	skf.kf_fileop = KERNFS_XWRITE;
   7.368 +	kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
   7.369 +	if (kf == NULL)
   7.370 +		kf = &kernfs_default_fileops[KERNFS_XWRITE];
   7.371 +	if (kf->kf_xwrite)
   7.372 +		return kf->kf_xwrite(kfs, buf, len);
   7.373 +	return error;
   7.374 +}
   7.375 +
   7.376 +int
   7.377 +kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
   7.378 +{
   7.379 +	struct kernfs_subdir *ks, *parent;
   7.380 +
   7.381 +	if (pkt == NULL) {
   7.382 +		SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
   7.383 +		nkern_targets++;
   7.384 +		if (dkt->dkt_kt.kt_vtype == VDIR)
   7.385 +			nkern_dirs++;
   7.386 +	} else {
   7.387 +		parent = (struct kernfs_subdir *)pkt->kt_data;
   7.388 +		SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
   7.389 +		parent->ks_nentries++;
   7.390 +		if (dkt->dkt_kt.kt_vtype == VDIR)
   7.391 +			parent->ks_dirs++;
   7.392 +	}
   7.393 +	if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
   7.394 +		ks = malloc(sizeof(struct kernfs_subdir),
   7.395 +		    M_TEMP, M_WAITOK);
   7.396 +		SIMPLEQ_INIT(&ks->ks_entries);
   7.397 +		ks->ks_nentries = 2; /* . and .. */
   7.398 +		ks->ks_dirs = 2;
   7.399 +		ks->ks_parent = pkt ? pkt : &kern_targets[0];
   7.400 +		dkt->dkt_kt.kt_data = ks;
   7.401 +	}
   7.402 +	return 0;
   7.403 +}
   7.404 +
   7.405 +static int
   7.406 +kernfs_xread(kfs, off, bufp, len, wrlen)
   7.407 +	struct kernfs_node *kfs;
   7.408 +	int off;
   7.409 +	char **bufp;
   7.410 +	size_t len;
   7.411 +	size_t *wrlen;
   7.412 +{
   7.413 +	const struct kern_target *kt;
   7.414 +#ifdef IPSEC
   7.415 +	struct mbuf *m;
   7.416 +#endif
   7.417 +
   7.418 +	kt = kfs->kfs_kt;
   7.419 +
   7.420 +	switch (kfs->kfs_type) {
   7.421 +	case KFStime: {
   7.422 +		struct timeval tv;
   7.423 +
   7.424 +		microtime(&tv);
   7.425 +		snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
   7.426 +		break;
   7.427 +	}
   7.428 +
   7.429 +	case KFSint: {
   7.430 +		int *ip = kt->kt_data;
   7.431 +
   7.432 +		snprintf(*bufp, len, "%d\n", *ip);
   7.433 +		break;
   7.434 +	}
   7.435 +
   7.436 +	case KFSstring: {
   7.437 +		char *cp = kt->kt_data;
   7.438 +
   7.439 +		*bufp = cp;
   7.440 +		break;
   7.441 +	}
   7.442 +
   7.443 +	case KFSmsgbuf: {
   7.444 +		long n;
   7.445 +
   7.446 +		/*
   7.447 +		 * deal with cases where the message buffer has
   7.448 +		 * become corrupted.
   7.449 +		 */
   7.450 +		if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
   7.451 +			msgbufenabled = 0;
   7.452 +			return (ENXIO);
   7.453 +		}
   7.454 +
   7.455 +		/*
   7.456 +		 * Note that reads of /kern/msgbuf won't necessarily yield
   7.457 +		 * consistent results, if the message buffer is modified
   7.458 +		 * while the read is in progress.  The worst that can happen
   7.459 +		 * is that incorrect data will be read.  There's no way
   7.460 +		 * that this can crash the system unless the values in the
   7.461 +		 * message buffer header are corrupted, but that'll cause
   7.462 +		 * the system to die anyway.
   7.463 +		 */
   7.464 +		if (off >= msgbufp->msg_bufs) {
   7.465 +			*wrlen = 0;
   7.466 +			return (0);
   7.467 +		}
   7.468 +		n = msgbufp->msg_bufx + off;
   7.469 +		if (n >= msgbufp->msg_bufs)
   7.470 +			n -= msgbufp->msg_bufs;
   7.471 +		len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
   7.472 +		*bufp = msgbufp->msg_bufc + n;
   7.473 +		*wrlen = len;
   7.474 +		return (0);
   7.475 +	}
   7.476 +
   7.477 +	case KFShostname: {
   7.478 +		char *cp = hostname;
   7.479 +		int xlen = hostnamelen;
   7.480 +
   7.481 +		if (xlen >= (len - 2))
   7.482 +			return (EINVAL);
   7.483 +
   7.484 +		memcpy(*bufp, cp, xlen);
   7.485 +		(*bufp)[xlen] = '\n';
   7.486 +		(*bufp)[xlen+1] = '\0';
   7.487 +		len = strlen(*bufp);
   7.488 +		break;
   7.489 +	}
   7.490 +
   7.491 +	case KFSavenrun:
   7.492 +		averunnable.fscale = FSCALE;
   7.493 +		snprintf(*bufp, len, "%d %d %d %ld\n",
   7.494 +		    averunnable.ldavg[0], averunnable.ldavg[1],
   7.495 +		    averunnable.ldavg[2], averunnable.fscale);
   7.496 +		break;
   7.497 +
   7.498 +#ifdef IPSEC
   7.499 +	case KFSipsecsa:
   7.500 +		/*
   7.501 +		 * Note that SA configuration could be changed during the
   7.502 +		 * read operation, resulting in garbled output.
   7.503 +		 */
   7.504 +		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
   7.505 +		if (!m)
   7.506 +			return (ENOBUFS);
   7.507 +		if (off >= m->m_pkthdr.len) {
   7.508 +			*wrlen = 0;
   7.509 +			m_freem(m);
   7.510 +			return (0);
   7.511 +		}
   7.512 +		if (len > m->m_pkthdr.len - off)
   7.513 +			len = m->m_pkthdr.len - off;
   7.514 +		m_copydata(m, off, len, *bufp);
   7.515 +		*wrlen = len;
   7.516 +		m_freem(m);
   7.517 +		return (0);
   7.518 +
   7.519 +	case KFSipsecsp:
   7.520 +		/*
   7.521 +		 * Note that SP configuration could be changed during the
   7.522 +		 * read operation, resulting in garbled output.
   7.523 +		 */
   7.524 +		if (!kfs->kfs_v) {
   7.525 +			struct secpolicy *sp;
   7.526 +
   7.527 +			sp = key_getspbyid(kfs->kfs_value);
   7.528 +			if (sp)
   7.529 +				kfs->kfs_v = sp;
   7.530 +			else
   7.531 +				return (ENOENT);
   7.532 +		}
   7.533 +		m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
   7.534 +		    SADB_X_SPDGET, 0, 0);
   7.535 +		if (!m)
   7.536 +			return (ENOBUFS);
   7.537 +		if (off >= m->m_pkthdr.len) {
   7.538 +			*wrlen = 0;
   7.539 +			m_freem(m);
   7.540 +			return (0);
   7.541 +		}
   7.542 +		if (len > m->m_pkthdr.len - off)
   7.543 +			len = m->m_pkthdr.len - off;
   7.544 +		m_copydata(m, off, len, *bufp);
   7.545 +		*wrlen = len;
   7.546 +		m_freem(m);
   7.547 +		return (0);
   7.548 +#endif
   7.549 +
   7.550 +	default:
   7.551 +		return kernfs_try_xread(kfs->kfs_type, kfs, off, bufp, len,
   7.552 +		    wrlen, 0);
   7.553 +	}
   7.554 +
   7.555 +	len = strlen(*bufp);
   7.556 +	if (len <= off)
   7.557 +		*wrlen = 0;
   7.558 +	else {
   7.559 +		*bufp += off;
   7.560 +		*wrlen = len - off;
   7.561 +	}
   7.562 +	return (0);
   7.563 +}
   7.564 +
   7.565 +static int
   7.566 +kernfs_xwrite(kfs, buf, len)
   7.567 +	const struct kernfs_node *kfs;
   7.568 +	char *buf;
   7.569 +	size_t len;
   7.570 +{
   7.571 +
   7.572 +	switch (kfs->kfs_type) {
   7.573 +	case KFShostname:
   7.574 +		if (buf[len-1] == '\n')
   7.575 +			--len;
   7.576 +		memcpy(hostname, buf, len);
   7.577 +		hostname[len] = '\0';
   7.578 +		hostnamelen = (size_t) len;
   7.579 +		return (0);
   7.580 +
   7.581 +	default:
   7.582 +		return kernfs_try_xwrite(kfs->kfs_type, kfs, buf, len, EIO);
   7.583 +	}
   7.584 +}
   7.585 +
   7.586 +
   7.587 +/*
   7.588 + * vp is the current namei directory
   7.589 + * ndp is the name to locate in that directory...
   7.590 + */
   7.591 +int
   7.592 +kernfs_lookup(v)
   7.593 +	void *v;
   7.594 +{
   7.595 +	struct vop_lookup_args /* {
   7.596 +		struct vnode * a_dvp;
   7.597 +		struct vnode ** a_vpp;
   7.598 +		struct componentname * a_cnp;
   7.599 +	} */ *ap = v;
   7.600 +	struct componentname *cnp = ap->a_cnp;
   7.601 +	struct vnode **vpp = ap->a_vpp;
   7.602 +	struct vnode *dvp = ap->a_dvp;
   7.603 +	const char *pname = cnp->cn_nameptr;
   7.604 +	const struct kernfs_node *kfs;
   7.605 +	const struct kern_target *kt;
   7.606 +	const struct dyn_kern_target *dkt;
   7.607 +	const struct kernfs_subdir *ks;
   7.608 +	int error, i, wantpunlock;
   7.609 +#ifdef IPSEC
   7.610 +	char *ep;
   7.611 +	u_int32_t id;
   7.612 +#endif
   7.613 +
   7.614 +	*vpp = NULLVP;
   7.615 +	cnp->cn_flags &= ~PDIRUNLOCK;
   7.616 +
   7.617 +	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
   7.618 +		return (EROFS);
   7.619 +
   7.620 +	if (cnp->cn_namelen == 1 && *pname == '.') {
   7.621 +		*vpp = dvp;
   7.622 +		VREF(dvp);
   7.623 +		return (0);
   7.624 +	}
   7.625 +
   7.626 +	wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
   7.627 +	kfs = VTOKERN(dvp);
   7.628 +	switch (kfs->kfs_type) {
   7.629 +	case KFSkern:
   7.630 +		/*
   7.631 +		 * Shouldn't get here with .. in the root node.
   7.632 +		 */
   7.633 +		if (cnp->cn_flags & ISDOTDOT)
   7.634 +			return (EIO);
   7.635 +
   7.636 +		for (i = 0; i < static_nkern_targets; i++) {
   7.637 +			kt = &kern_targets[i];
   7.638 +			if (cnp->cn_namelen == kt->kt_namlen &&
   7.639 +			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
   7.640 +				goto found;
   7.641 +		}
   7.642 +		SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
   7.643 +			if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
   7.644 +			    memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
   7.645 +				kt = &dkt->dkt_kt;
   7.646 +				goto found;
   7.647 +			}
   7.648 +		}
   7.649 +		break;
   7.650 +
   7.651 +	found:
   7.652 +		error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
   7.653 +		if ((error == 0) && wantpunlock) {
   7.654 +			VOP_UNLOCK(dvp, 0);
   7.655 +			cnp->cn_flags |= PDIRUNLOCK;
   7.656 +		}
   7.657 +		return (error);
   7.658 +
   7.659 +	case KFSsubdir:
   7.660 +		ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
   7.661 +		if (cnp->cn_flags & ISDOTDOT) {
   7.662 +			kt = ks->ks_parent;
   7.663 +			goto found;
   7.664 +		}
   7.665 +
   7.666 +		SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
   7.667 +			if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
   7.668 +			    memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
   7.669 +				kt = &dkt->dkt_kt;
   7.670 +				goto found;
   7.671 +			}
   7.672 +		}
   7.673 +		break;
   7.674 +
   7.675 +#ifdef IPSEC
   7.676 +	case KFSipsecsadir:
   7.677 +		if (cnp->cn_flags & ISDOTDOT) {
   7.678 +			kt = &kern_targets[0];
   7.679 +			goto found;
   7.680 +		}
   7.681 +
   7.682 +		for (i = 2; i < nipsecsa_targets; i++) {
   7.683 +			kt = &ipsecsa_targets[i];
   7.684 +			if (cnp->cn_namelen == kt->kt_namlen &&
   7.685 +			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
   7.686 +				goto found;
   7.687 +		}
   7.688 +
   7.689 +		ep = NULL;
   7.690 +		id = strtoul(pname, &ep, 10);
   7.691 +		if (!ep || *ep || ep == pname)
   7.692 +			break;
   7.693 +
   7.694 +		error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
   7.695 +		if ((error == 0) && wantpunlock) {
   7.696 +			VOP_UNLOCK(dvp, 0);
   7.697 +			cnp->cn_flags |= PDIRUNLOCK;
   7.698 +		}
   7.699 +		return (error);
   7.700 +
   7.701 +	case KFSipsecspdir:
   7.702 +		if (cnp->cn_flags & ISDOTDOT) {
   7.703 +			kt = &kern_targets[0];
   7.704 +			goto found;
   7.705 +		}
   7.706 +
   7.707 +		for (i = 2; i < nipsecsp_targets; i++) {
   7.708 +			kt = &ipsecsp_targets[i];
   7.709 +			if (cnp->cn_namelen == kt->kt_namlen &&
   7.710 +			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
   7.711 +				goto found;
   7.712 +		}
   7.713 +
   7.714 +		ep = NULL;
   7.715 +		id = strtoul(pname, &ep, 10);
   7.716 +		if (!ep || *ep || ep == pname)
   7.717 +			break;
   7.718 +
   7.719 +		error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
   7.720 +		if ((error == 0) && wantpunlock) {
   7.721 +			VOP_UNLOCK(dvp, 0);
   7.722 +			cnp->cn_flags |= PDIRUNLOCK;
   7.723 +		}
   7.724 +		return (error);
   7.725 +#endif
   7.726 +
   7.727 +	default:
   7.728 +		return (ENOTDIR);
   7.729 +	}
   7.730 +
   7.731 +	return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
   7.732 +}
   7.733 +
   7.734 +int
   7.735 +kernfs_open(v)
   7.736 +	void *v;
   7.737 +{
   7.738 +	struct vop_open_args /* {
   7.739 +		struct vnode *a_vp;
   7.740 +		int a_mode;
   7.741 +		struct ucred *a_cred;
   7.742 +		struct proc *a_p;
   7.743 +	} */ *ap = v;
   7.744 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   7.745 +#ifdef IPSEC
   7.746 +	struct mbuf *m;
   7.747 +	struct secpolicy *sp;
   7.748 +#endif
   7.749 +
   7.750 +	switch (kfs->kfs_type) {
   7.751 +#ifdef IPSEC
   7.752 +	case KFSipsecsa:
   7.753 +		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
   7.754 +		if (m) {
   7.755 +			m_freem(m);
   7.756 +			return (0);
   7.757 +		} else
   7.758 +			return (ENOENT);
   7.759 +
   7.760 +	case KFSipsecsp:
   7.761 +		sp = key_getspbyid(kfs->kfs_value);
   7.762 +		if (sp) {
   7.763 +			kfs->kfs_v = sp;
   7.764 +			return (0);
   7.765 +		} else
   7.766 +			return (ENOENT);
   7.767 +#endif
   7.768 +
   7.769 +	default:
   7.770 +		return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
   7.771 +		    v, 0);
   7.772 +	}
   7.773 +}
   7.774 +
   7.775 +int
   7.776 +kernfs_close(v)
   7.777 +	void *v;
   7.778 +{
   7.779 +	struct vop_close_args /* {
   7.780 +		struct vnode *a_vp;
   7.781 +		int a_fflag;
   7.782 +		struct ucred *a_cred;
   7.783 +		struct proc *a_p;
   7.784 +	} */ *ap = v;
   7.785 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   7.786 +
   7.787 +	switch (kfs->kfs_type) {
   7.788 +#ifdef IPSEC
   7.789 +	case KFSipsecsp:
   7.790 +		key_freesp((struct secpolicy *)kfs->kfs_v);
   7.791 +		break;
   7.792 +#endif
   7.793 +
   7.794 +	default:
   7.795 +		return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
   7.796 +		    v, 0);
   7.797 +	}
   7.798 +
   7.799 +	return (0);
   7.800 +}
   7.801 +
   7.802 +int
   7.803 +kernfs_access(v)
   7.804 +	void *v;
   7.805 +{
   7.806 +	struct vop_access_args /* {
   7.807 +		struct vnode *a_vp;
   7.808 +		int a_mode;
   7.809 +		struct ucred *a_cred;
   7.810 +		struct proc *a_p;
   7.811 +	} */ *ap = v;
   7.812 +	struct vattr va;
   7.813 +	int error;
   7.814 +
   7.815 +	if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
   7.816 +		return (error);
   7.817 +
   7.818 +	return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
   7.819 +	    ap->a_mode, ap->a_cred));
   7.820 +}
   7.821 +
   7.822 +static int
   7.823 +kernfs_default_fileop_getattr(v)
   7.824 +	void *v;
   7.825 +{
   7.826 +	struct vop_getattr_args /* {
   7.827 +		struct vnode *a_vp;
   7.828 +		struct vattr *a_vap;
   7.829 +		struct ucred *a_cred;
   7.830 +		struct proc *a_p;
   7.831 +	} */ *ap = v;
   7.832 +	struct vattr *vap = ap->a_vap;
   7.833 +
   7.834 +	vap->va_nlink = 1;
   7.835 +	vap->va_bytes = vap->va_size = 0;
   7.836 +
   7.837 +	return 0;
   7.838 +}
   7.839 +
   7.840 +int
   7.841 +kernfs_getattr(v)
   7.842 +	void *v;
   7.843 +{
   7.844 +	struct vop_getattr_args /* {
   7.845 +		struct vnode *a_vp;
   7.846 +		struct vattr *a_vap;
   7.847 +		struct ucred *a_cred;
   7.848 +		struct proc *a_p;
   7.849 +	} */ *ap = v;
   7.850 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   7.851 +	struct kernfs_subdir *ks;
   7.852 +	struct vattr *vap = ap->a_vap;
   7.853 +	int error = 0;
   7.854 +	char strbuf[KSTRING], *buf;
   7.855 +	size_t nread, total;
   7.856 +
   7.857 +	VATTR_NULL(vap);
   7.858 +	vap->va_type = ap->a_vp->v_type;
   7.859 +	vap->va_uid = 0;
   7.860 +	vap->va_gid = 0;
   7.861 +	vap->va_mode = kfs->kfs_mode;
   7.862 +	vap->va_fileid = kfs->kfs_fileno;
   7.863 +	vap->va_flags = 0;
   7.864 +	vap->va_size = 0;
   7.865 +	vap->va_blocksize = DEV_BSIZE;
   7.866 +	/*
   7.867 +	 * Make all times be current TOD, except for the "boottime" node.
   7.868 +	 * Avoid microtime(9), it's slow.
   7.869 +	 * We don't guard the read from time(9) with splclock(9) since we
   7.870 +	 * don't actually need to be THAT sure the access is atomic. 
   7.871 +	 */
   7.872 +	if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 && 
   7.873 +	    !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
   7.874 +		TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
   7.875 +	} else {
   7.876 +		TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
   7.877 +	}
   7.878 +	vap->va_atime = vap->va_mtime = vap->va_ctime;
   7.879 +	vap->va_gen = 0;
   7.880 +	vap->va_flags = 0;
   7.881 +	vap->va_rdev = 0;
   7.882 +	vap->va_bytes = 0;
   7.883 +
   7.884 +	switch (kfs->kfs_type) {
   7.885 +	case KFSkern:
   7.886 +		vap->va_nlink = nkern_dirs;
   7.887 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   7.888 +		break;
   7.889 +
   7.890 +	case KFSroot:
   7.891 +		vap->va_nlink = 1;
   7.892 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   7.893 +		break;
   7.894 +
   7.895 +	case KFSsubdir:
   7.896 +		ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
   7.897 +		vap->va_nlink = ks->ks_dirs;
   7.898 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   7.899 +		break;
   7.900 +
   7.901 +	case KFSnull:
   7.902 +	case KFStime:
   7.903 +	case KFSint:
   7.904 +	case KFSstring:
   7.905 +	case KFShostname:
   7.906 +	case KFSavenrun:
   7.907 +	case KFSdevice:
   7.908 +	case KFSmsgbuf:
   7.909 +#ifdef IPSEC
   7.910 +	case KFSipsecsa:
   7.911 +	case KFSipsecsp:
   7.912 +#endif
   7.913 +		vap->va_nlink = 1;
   7.914 +		total = 0;
   7.915 +		do {
   7.916 +			buf = strbuf;
   7.917 +			error = kernfs_xread(kfs, total, &buf,
   7.918 +			    sizeof(strbuf), &nread);
   7.919 +			total += nread;
   7.920 +		} while (error == 0 && nread != 0);
   7.921 +		vap->va_bytes = vap->va_size = total;
   7.922 +		break;
   7.923 +
   7.924 +#ifdef IPSEC
   7.925 +	case KFSipsecsadir:
   7.926 +	case KFSipsecspdir:
   7.927 +		vap->va_nlink = 2;
   7.928 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   7.929 +		break;
   7.930 +#endif
   7.931 +
   7.932 +	default:
   7.933 +		error = kernfs_try_fileop(kfs->kfs_type,
   7.934 +		    KERNFS_FILEOP_GETATTR, v, EINVAL);
   7.935 +		break;
   7.936 +	}
   7.937 +
   7.938 +	return (error);
   7.939 +}
   7.940 +
   7.941 +/*ARGSUSED*/
   7.942 +int
   7.943 +kernfs_setattr(v)
   7.944 +	void *v;
   7.945 +{
   7.946 +
   7.947 +	/*
   7.948 +	 * Silently ignore attribute changes.
   7.949 +	 * This allows for open with truncate to have no
   7.950 +	 * effect until some data is written.  I want to
   7.951 +	 * do it this way because all writes are atomic.
   7.952 +	 */
   7.953 +	return (0);
   7.954 +}
   7.955 +
   7.956 +static int
   7.957 +kernfs_default_xread(v)
   7.958 +	void *v;
   7.959 +{
   7.960 +	struct vop_read_args /* {
   7.961 +		struct vnode *a_vp;
   7.962 +		struct uio *a_uio;
   7.963 +		int  a_ioflag;
   7.964 +		struct ucred *a_cred;
   7.965 +	} */ *ap = v;
   7.966 +	struct uio *uio = ap->a_uio;
   7.967 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   7.968 +	char strbuf[KSTRING], *buf;
   7.969 +	off_t off;
   7.970 +	size_t len;
   7.971 +	int error;
   7.972 +
   7.973 +	if (ap->a_vp->v_type == VDIR)
   7.974 +		return (EOPNOTSUPP);
   7.975 +
   7.976 +	off = uio->uio_offset;
   7.977 +	buf = strbuf;
   7.978 +	if ((error = kernfs_xread(kfs, off, &buf, sizeof(strbuf), &len)) == 0)
   7.979 +		error = uiomove(buf, len, uio);
   7.980 +	return (error);
   7.981 +}
   7.982 +
   7.983 +int
   7.984 +kernfs_read(v)
   7.985 +	void *v;
   7.986 +{
   7.987 +	struct vop_read_args /* {
   7.988 +		struct vnode *a_vp;
   7.989 +		struct uio *a_uio;
   7.990 +		int  a_ioflag;
   7.991 +		struct ucred *a_cred;
   7.992 +	} */ *ap = v;
   7.993 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   7.994 +
   7.995 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v, 0);
   7.996 +}
   7.997 +
   7.998 +static int
   7.999 +kernfs_default_xwrite(v)
  7.1000 +	void *v;
  7.1001 +{
  7.1002 +	struct vop_write_args /* {
  7.1003 +		struct vnode *a_vp;
  7.1004 +		struct uio *a_uio;
  7.1005 +		int  a_ioflag;
  7.1006 +		struct ucred *a_cred;
  7.1007 +	} */ *ap = v;
  7.1008 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  7.1009 +	struct uio *uio = ap->a_uio;
  7.1010 +	int error, xlen;
  7.1011 +	char strbuf[KSTRING];
  7.1012 +
  7.1013 +	if (uio->uio_offset != 0)
  7.1014 +		return (EINVAL);
  7.1015 +
  7.1016 +	xlen = min(uio->uio_resid, KSTRING-1);
  7.1017 +	if ((error = uiomove(strbuf, xlen, uio)) != 0)
  7.1018 +		return (error);
  7.1019 +
  7.1020 +	if (uio->uio_resid != 0)
  7.1021 +		return (EIO);
  7.1022 +
  7.1023 +	strbuf[xlen] = '\0';
  7.1024 +	xlen = strlen(strbuf);
  7.1025 +	return (kernfs_xwrite(kfs, strbuf, xlen));
  7.1026 +}
  7.1027 +
  7.1028 +int
  7.1029 +kernfs_write(v)
  7.1030 +	void *v;
  7.1031 +{
  7.1032 +	struct vop_write_args /* {
  7.1033 +		struct vnode *a_vp;
  7.1034 +		struct uio *a_uio;
  7.1035 +		int  a_ioflag;
  7.1036 +		struct ucred *a_cred;
  7.1037 +	} */ *ap = v;
  7.1038 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  7.1039 +
  7.1040 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 0);
  7.1041 +}
  7.1042 +
  7.1043 +int
  7.1044 +kernfs_ioctl(v)
  7.1045 +	void *v;
  7.1046 +{
  7.1047 +	struct vop_ioctl_args /* {
  7.1048 +		const struct vnodeop_desc *a_desc;
  7.1049 +		struct vnode *a_vp;
  7.1050 +		u_long a_command;
  7.1051 +		void *a_data;
  7.1052 +		int a_fflag;
  7.1053 +		struct ucred *a_cred;
  7.1054 +		struct proc *a_p;
  7.1055 +	} */ *ap = v;
  7.1056 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  7.1057 +
  7.1058 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
  7.1059 +	    EPASSTHROUGH);
  7.1060 +}
  7.1061 +
  7.1062 +int
  7.1063 +kernfs_mmap(v)
  7.1064 +	void *v;
  7.1065 +{
  7.1066 +	struct vop_mmap_args /* {
  7.1067 +		const struct vnodeop_desc *a_desc;
  7.1068 +		struct vnode *a_vp;
  7.1069 +		int a_fflags;
  7.1070 +		struct ucred *a_cred;
  7.1071 +		struct proc *a_p;
  7.1072 +	} */ *ap = v;
  7.1073 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  7.1074 +
  7.1075 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_MMAP, v, 0);
  7.1076 +}
  7.1077 +
  7.1078 +static int
  7.1079 +kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
  7.1080 +    u_int32_t value, struct vop_readdir_args *ap)
  7.1081 +{
  7.1082 +	struct kernfs_node *kfs;
  7.1083 +	struct vnode *vp;
  7.1084 +	int error;
  7.1085 +
  7.1086 +	if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
  7.1087 +	    value)) != 0)
  7.1088 +		return error;
  7.1089 +	if (kt->kt_tag == KFSdevice) {
  7.1090 +		struct vattr va;
  7.1091 +		if ((error = VOP_GETATTR(vp, &va, ap->a_cred,
  7.1092 +		    ap->a_uio->uio_segflg == UIO_USERSPACE ?
  7.1093 +		    ap->a_uio->uio_procp : &proc0)) != 0)
  7.1094 +			return (error);
  7.1095 +		d->d_fileno = va.va_fileid;
  7.1096 +	} else {
  7.1097 +		kfs = VTOKERN(vp);
  7.1098 +		d->d_fileno = kfs->kfs_fileno;
  7.1099 +	}
  7.1100 +	vput(vp);
  7.1101 +	return 0;
  7.1102 +}
  7.1103 +
  7.1104 +static int
  7.1105 +kernfs_setdirentfileno(struct dirent *d, off_t entry,
  7.1106 +    struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
  7.1107 +    const struct kern_target *kt, struct vop_readdir_args *ap)
  7.1108 +{
  7.1109 +	const struct kern_target *ikt;
  7.1110 +	int error;
  7.1111 +
  7.1112 +	switch (entry) {
  7.1113 +	case 0:
  7.1114 +		d->d_fileno = thisdir_kfs->kfs_fileno;
  7.1115 +		return 0;
  7.1116 +	case 1:
  7.1117 +		ikt = parent_kt;
  7.1118 +		break;
  7.1119 +	default:
  7.1120 +		ikt = kt;
  7.1121 +		break;
  7.1122 +	}
  7.1123 +	if (ikt != thisdir_kfs->kfs_kt) {
  7.1124 +		if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
  7.1125 +			return error;
  7.1126 +	} else
  7.1127 +		d->d_fileno = thisdir_kfs->kfs_fileno;
  7.1128 +	return 0;
  7.1129 +}
  7.1130 +
  7.1131 +int
  7.1132 +kernfs_readdir(v)
  7.1133 +	void *v;
  7.1134 +{
  7.1135 +	struct vop_readdir_args /* {
  7.1136 +		struct vnode *a_vp;
  7.1137 +		struct uio *a_uio;
  7.1138 +		struct ucred *a_cred;
  7.1139 +		int *a_eofflag;
  7.1140 +		off_t **a_cookies;
  7.1141 +		int a_*ncookies;
  7.1142 +	} */ *ap = v;
  7.1143 +	struct uio *uio = ap->a_uio;
  7.1144 +	struct dirent d;
  7.1145 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  7.1146 +	const struct kern_target *kt;
  7.1147 +	const struct dyn_kern_target *dkt = NULL;
  7.1148 +	const struct kernfs_subdir *ks;
  7.1149 +	off_t i, j;
  7.1150 +	int error;
  7.1151 +	off_t *cookies = NULL;
  7.1152 +	int ncookies = 0, n;
  7.1153 +#ifdef IPSEC
  7.1154 +	struct secasvar *sav, *sav2;
  7.1155 +	struct secpolicy *sp;
  7.1156 +#endif
  7.1157 +
  7.1158 +	if (uio->uio_resid < UIO_MX)
  7.1159 +		return (EINVAL);
  7.1160 +	if (uio->uio_offset < 0)
  7.1161 +		return (EINVAL);
  7.1162 +
  7.1163 +	error = 0;
  7.1164 +	i = uio->uio_offset;
  7.1165 +	memset(&d, 0, sizeof(d));
  7.1166 +	d.d_reclen = UIO_MX;
  7.1167 +	ncookies = uio->uio_resid / UIO_MX;
  7.1168 +
  7.1169 +	switch (kfs->kfs_type) {
  7.1170 +	case KFSkern:
  7.1171 +		if (i >= nkern_targets)
  7.1172 +			return (0);
  7.1173 +
  7.1174 +		if (ap->a_ncookies) {
  7.1175 +			ncookies = min(ncookies, (nkern_targets - i));
  7.1176 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  7.1177 +			    M_WAITOK);
  7.1178 +			*ap->a_cookies = cookies;
  7.1179 +		}
  7.1180 +
  7.1181 +		n = 0;
  7.1182 +		for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
  7.1183 +			if (i < static_nkern_targets)
  7.1184 +				kt = &kern_targets[i];
  7.1185 +			else {
  7.1186 +				if (dkt == NULL) {
  7.1187 +					dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
  7.1188 +					for (j = static_nkern_targets; j < i &&
  7.1189 +						     dkt != NULL; j++)
  7.1190 +						dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  7.1191 +					if (j != i)
  7.1192 +						break;
  7.1193 +				} else {
  7.1194 +					dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  7.1195 +					if (dkt == NULL)
  7.1196 +						break;
  7.1197 +				}
  7.1198 +				kt = &dkt->dkt_kt;
  7.1199 +			}
  7.1200 +			if (kt->kt_tag == KFSdevice) {
  7.1201 +				dev_t *dp = kt->kt_data;
  7.1202 +				struct vnode *fvp;
  7.1203 +
  7.1204 +				if (*dp == NODEV ||
  7.1205 +				    !vfinddev(*dp, kt->kt_vtype, &fvp))
  7.1206 +					continue;
  7.1207 +			}
  7.1208 +			d.d_namlen = kt->kt_namlen;
  7.1209 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  7.1210 +			    &kern_targets[0], kt, ap)) != 0)
  7.1211 +				break;
  7.1212 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  7.1213 +			d.d_type = kt->kt_type;
  7.1214 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  7.1215 +				break;
  7.1216 +			if (cookies)
  7.1217 +				*cookies++ = i + 1;
  7.1218 +			n++;
  7.1219 +		}
  7.1220 +		ncookies = n;
  7.1221 +		break;
  7.1222 +
  7.1223 +	case KFSroot:
  7.1224 +		if (i >= 2)
  7.1225 +			return 0;
  7.1226 +
  7.1227 +		if (ap->a_ncookies) {
  7.1228 +			ncookies = min(ncookies, (2 - i));
  7.1229 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  7.1230 +			    M_WAITOK);
  7.1231 +			*ap->a_cookies = cookies;
  7.1232 +		}
  7.1233 +
  7.1234 +		n = 0;
  7.1235 +		for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
  7.1236 +			kt = &kern_targets[i];
  7.1237 +			d.d_namlen = kt->kt_namlen;
  7.1238 +			d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
  7.1239 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  7.1240 +			d.d_type = kt->kt_type;
  7.1241 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  7.1242 +				break;
  7.1243 +			if (cookies)
  7.1244 +				*cookies++ = i + 1;
  7.1245 +			n++;
  7.1246 +		}
  7.1247 +		ncookies = n;
  7.1248 +		break;
  7.1249 +
  7.1250 +	case KFSsubdir:
  7.1251 +		ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
  7.1252 +		if (i >= ks->ks_nentries)
  7.1253 +			return (0);
  7.1254 +
  7.1255 +		if (ap->a_ncookies) {
  7.1256 +			ncookies = min(ncookies, (ks->ks_nentries - i));
  7.1257 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  7.1258 +			    M_WAITOK);
  7.1259 +			*ap->a_cookies = cookies;
  7.1260 +		}
  7.1261 +
  7.1262 +		dkt = SIMPLEQ_FIRST(&ks->ks_entries);
  7.1263 +		for (j = 0; j < i && dkt != NULL; j++)
  7.1264 +			dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  7.1265 +		n = 0;
  7.1266 +		for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
  7.1267 +			if (i < 2)
  7.1268 +				kt = &subdir_targets[i];
  7.1269 +			else {
  7.1270 +				/* check if ks_nentries lied to us */
  7.1271 +				if (dkt == NULL)
  7.1272 +					break;
  7.1273 +				kt = &dkt->dkt_kt;
  7.1274 +				dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  7.1275 +			}
  7.1276 +			if (kt->kt_tag == KFSdevice) {
  7.1277 +				dev_t *dp = kt->kt_data;
  7.1278 +				struct vnode *fvp;
  7.1279 +
  7.1280 +				if (*dp == NODEV ||
  7.1281 +				    !vfinddev(*dp, kt->kt_vtype, &fvp))
  7.1282 +					continue;
  7.1283 +			}
  7.1284 +			d.d_namlen = kt->kt_namlen;
  7.1285 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  7.1286 +			    ks->ks_parent, kt, ap)) != 0)
  7.1287 +				break;
  7.1288 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  7.1289 +			d.d_type = kt->kt_type;
  7.1290 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  7.1291 +				break;
  7.1292 +			if (cookies)
  7.1293 +				*cookies++ = i + 1;
  7.1294 +			n++;
  7.1295 +		}
  7.1296 +		ncookies = n;
  7.1297 +		break;
  7.1298 +
  7.1299 +#ifdef IPSEC
  7.1300 +	case KFSipsecsadir:
  7.1301 +		/* count SA in the system */
  7.1302 +		n = 0;
  7.1303 +		TAILQ_FOREACH(sav, &satailq, tailq) {
  7.1304 +			for (sav2 = TAILQ_FIRST(&satailq);
  7.1305 +			    sav2 != sav;
  7.1306 +			    sav2 = TAILQ_NEXT(sav2, tailq)) {
  7.1307 +				if (sav->spi == sav2->spi) {
  7.1308 +					/* multiple SA with same SPI */
  7.1309 +					break;
  7.1310 +				}
  7.1311 +			}
  7.1312 +			if (sav == sav2 || sav->spi != sav2->spi)
  7.1313 +				n++;
  7.1314 +		}
  7.1315 +
  7.1316 +		if (i >= nipsecsa_targets + n)
  7.1317 +			return (0);
  7.1318 +
  7.1319 +		if (ap->a_ncookies) {
  7.1320 +			ncookies = min(ncookies, (n - i));
  7.1321 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  7.1322 +			    M_WAITOK);
  7.1323 +			*ap->a_cookies = cookies;
  7.1324 +		}
  7.1325 +
  7.1326 +		n = 0;
  7.1327 +		for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
  7.1328 +			kt = &ipsecsa_targets[i];
  7.1329 +			d.d_namlen = kt->kt_namlen;
  7.1330 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  7.1331 +			    &kern_targets[0], kt, ap)) != 0)
  7.1332 +				break;
  7.1333 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  7.1334 +			d.d_type = kt->kt_type;
  7.1335 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  7.1336 +				break;
  7.1337 +			if (cookies)
  7.1338 +				*cookies++ = i + 1;
  7.1339 +			n++;
  7.1340 +		}
  7.1341 +		if (error) {
  7.1342 +			ncookies = n;
  7.1343 +			break;
  7.1344 +		}
  7.1345 +
  7.1346 +		TAILQ_FOREACH(sav, &satailq, tailq) {
  7.1347 +			for (sav2 = TAILQ_FIRST(&satailq);
  7.1348 +			    sav2 != sav;
  7.1349 +			    sav2 = TAILQ_NEXT(sav2, tailq)) {
  7.1350 +				if (sav->spi == sav2->spi) {
  7.1351 +					/* multiple SA with same SPI */
  7.1352 +					break;
  7.1353 +				}
  7.1354 +			}
  7.1355 +			if (sav != sav2 && sav->spi == sav2->spi)
  7.1356 +				continue;
  7.1357 +			if (uio->uio_resid < UIO_MX)
  7.1358 +				break;
  7.1359 +			if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
  7.1360 +			    sav->spi, ap)) != 0)
  7.1361 +				break;
  7.1362 +			d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
  7.1363 +			    "%u", ntohl(sav->spi));
  7.1364 +			d.d_type = DT_REG;
  7.1365 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  7.1366 +				break;
  7.1367 +			if (cookies)
  7.1368 +				*cookies++ = i + 1;
  7.1369 +			n++;
  7.1370 +			i++;
  7.1371 +		}
  7.1372 +		ncookies = n;
  7.1373 +		break;
  7.1374 +
  7.1375 +	case KFSipsecspdir:
  7.1376 +		/* count SP in the system */
  7.1377 +		n = 0;
  7.1378 +		TAILQ_FOREACH(sp, &sptailq, tailq)
  7.1379 +			n++;
  7.1380 +
  7.1381 +		if (i >= nipsecsp_targets + n)
  7.1382 +			return (0);
  7.1383 +
  7.1384 +		if (ap->a_ncookies) {
  7.1385 +			ncookies = min(ncookies, (n - i));
  7.1386 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  7.1387 +			    M_WAITOK);
  7.1388 +			*ap->a_cookies = cookies;
  7.1389 +		}
  7.1390 +
  7.1391 +		n = 0;
  7.1392 +		for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
  7.1393 +			kt = &ipsecsp_targets[i];
  7.1394 +			d.d_namlen = kt->kt_namlen;
  7.1395 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  7.1396 +			    &kern_targets[0], kt, ap)) != 0)
  7.1397 +				break;
  7.1398 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  7.1399 +			d.d_type = kt->kt_type;
  7.1400 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  7.1401 +				break;
  7.1402 +			if (cookies)
  7.1403 +				*cookies++ = i + 1;
  7.1404 +			n++;
  7.1405 +		}
  7.1406 +		if (error) {
  7.1407 +			ncookies = n;
  7.1408 +			break;
  7.1409 +		}
  7.1410 +
  7.1411 +		TAILQ_FOREACH(sp, &sptailq, tailq) {
  7.1412 +			if (uio->uio_resid < UIO_MX)
  7.1413 +				break;
  7.1414 +			if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
  7.1415 +			    sp->id, ap)) != 0)
  7.1416 +				break;
  7.1417 +			d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
  7.1418 +			    "%u", sp->id);
  7.1419 +			d.d_type = DT_REG;
  7.1420 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  7.1421 +				break;
  7.1422 +			if (cookies)
  7.1423 +				*cookies++ = i + 1;
  7.1424 +			n++;
  7.1425 +			i++;
  7.1426 +		}
  7.1427 +		ncookies = n;
  7.1428 +		break;
  7.1429 +#endif
  7.1430 +
  7.1431 +	default:
  7.1432 +		error = ENOTDIR;
  7.1433 +		break;
  7.1434 +	}
  7.1435 +
  7.1436 +	if (ap->a_ncookies) {
  7.1437 +		if (error) {
  7.1438 +			if (cookies)
  7.1439 +				free(*ap->a_cookies, M_TEMP);
  7.1440 +			*ap->a_ncookies = 0;
  7.1441 +			*ap->a_cookies = NULL;
  7.1442 +		} else
  7.1443 +			*ap->a_ncookies = ncookies;
  7.1444 +	}
  7.1445 +
  7.1446 +	uio->uio_offset = i;
  7.1447 +	return (error);
  7.1448 +}
  7.1449 +
  7.1450 +int
  7.1451 +kernfs_inactive(v)
  7.1452 +	void *v;
  7.1453 +{
  7.1454 +	struct vop_inactive_args /* {
  7.1455 +		struct vnode *a_vp;
  7.1456 +		struct proc *a_p;
  7.1457 +	} */ *ap = v;
  7.1458 +	struct vnode *vp = ap->a_vp;
  7.1459 +	const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  7.1460 +#ifdef IPSEC
  7.1461 +	struct mbuf *m;
  7.1462 +	struct secpolicy *sp;
  7.1463 +#endif
  7.1464 +
  7.1465 +	VOP_UNLOCK(vp, 0);
  7.1466 +	switch (kfs->kfs_type) {
  7.1467 +#ifdef IPSEC
  7.1468 +	case KFSipsecsa:
  7.1469 +		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
  7.1470 +		if (m)
  7.1471 +			m_freem(m);
  7.1472 +		else
  7.1473 +			vgone(vp);
  7.1474 +		break;
  7.1475 +	case KFSipsecsp:
  7.1476 +		sp = key_getspbyid(kfs->kfs_value);
  7.1477 +		if (sp)
  7.1478 +			key_freesp(sp);
  7.1479 +		else {
  7.1480 +			/* should never happen as we hold a refcnt */
  7.1481 +			vgone(vp);
  7.1482 +		}
  7.1483 +		break;
  7.1484 +#endif
  7.1485 +	default:
  7.1486 +		break;
  7.1487 +	}
  7.1488 +	return (0);
  7.1489 +}
  7.1490 +
  7.1491 +int
  7.1492 +kernfs_reclaim(v)
  7.1493 +	void *v;
  7.1494 +{
  7.1495 +	struct vop_reclaim_args /* {
  7.1496 +		struct vnode *a_vp;
  7.1497 +	} */ *ap = v;
  7.1498 +
  7.1499 +	return (kernfs_freevp(ap->a_vp));
  7.1500 +}
  7.1501 +
  7.1502 +/*
  7.1503 + * Return POSIX pathconf information applicable to special devices.
  7.1504 + */
  7.1505 +int
  7.1506 +kernfs_pathconf(v)
  7.1507 +	void *v;
  7.1508 +{
  7.1509 +	struct vop_pathconf_args /* {
  7.1510 +		struct vnode *a_vp;
  7.1511 +		int a_name;
  7.1512 +		register_t *a_retval;
  7.1513 +	} */ *ap = v;
  7.1514 +
  7.1515 +	switch (ap->a_name) {
  7.1516 +	case _PC_LINK_MAX:
  7.1517 +		*ap->a_retval = LINK_MAX;
  7.1518 +		return (0);
  7.1519 +	case _PC_MAX_CANON:
  7.1520 +		*ap->a_retval = MAX_CANON;
  7.1521 +		return (0);
  7.1522 +	case _PC_MAX_INPUT:
  7.1523 +		*ap->a_retval = MAX_INPUT;
  7.1524 +		return (0);
  7.1525 +	case _PC_PIPE_BUF:
  7.1526 +		*ap->a_retval = PIPE_BUF;
  7.1527 +		return (0);
  7.1528 +	case _PC_CHOWN_RESTRICTED:
  7.1529 +		*ap->a_retval = 1;
  7.1530 +		return (0);
  7.1531 +	case _PC_VDISABLE:
  7.1532 +		*ap->a_retval = _POSIX_VDISABLE;
  7.1533 +		return (0);
  7.1534 +	case _PC_SYNC_IO:
  7.1535 +		*ap->a_retval = 1;
  7.1536 +		return (0);
  7.1537 +	default:
  7.1538 +		return (EINVAL);
  7.1539 +	}
  7.1540 +	/* NOTREACHED */
  7.1541 +}
  7.1542 +
  7.1543 +/*
  7.1544 + * Print out the contents of a /dev/fd vnode.
  7.1545 + */
  7.1546 +/* ARGSUSED */
  7.1547 +int
  7.1548 +kernfs_print(v)
  7.1549 +	void *v;
  7.1550 +{
  7.1551 +
  7.1552 +	printf("tag VT_KERNFS, kernfs vnode\n");
  7.1553 +	return (0);
  7.1554 +}
  7.1555 +
  7.1556 +int
  7.1557 +kernfs_link(v) 
  7.1558 +	void *v;
  7.1559 +{
  7.1560 +	struct vop_link_args /* {
  7.1561 +		struct vnode *a_dvp;
  7.1562 +		struct vnode *a_vp;  
  7.1563 +		struct componentname *a_cnp;
  7.1564 +	} */ *ap = v;
  7.1565 + 
  7.1566 +	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  7.1567 +	vput(ap->a_dvp);
  7.1568 +	return (EROFS);
  7.1569 +}
  7.1570 +
  7.1571 +int
  7.1572 +kernfs_symlink(v)
  7.1573 +	void *v;
  7.1574 +{
  7.1575 +	struct vop_symlink_args /* {
  7.1576 +		struct vnode *a_dvp;
  7.1577 +		struct vnode **a_vpp;
  7.1578 +		struct componentname *a_cnp;
  7.1579 +		struct vattr *a_vap;
  7.1580 +		char *a_target;
  7.1581 +	} */ *ap = v;
  7.1582 +  
  7.1583 +	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  7.1584 +	vput(ap->a_dvp);
  7.1585 +	return (EROFS);
  7.1586 +}