ia64/xen-unstable

changeset 4027:35896cd211c3

bitkeeper revision 1.1159.258.31 (422e4564B542sr1LgKTQ3FWQwTZcZQ)

Add support for read file operation handlers.
Also fix fallback to default handlers.
Signed-off-by: Christian Limpach <cl@NetBSD.org>
author cl349@firebug.cl.cam.ac.uk
date Wed Mar 09 00:37:56 2005 +0000 (2005-03-09)
parents 7d30a5399140
children 0b4083c2bdfd
files .rootkeys 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:30:50 2005 +0000
     1.2 +++ b/.rootkeys	Wed Mar 09 00:37:56 2005 +0000
     1.3 @@ -289,6 +289,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  413aa1d0ewvSv-ohnNnQQNGsbPTTNA patches/linux-2.6.10/drm.patch
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs.h	Wed Mar 09 00:37:56 2005 +0000
     2.3 @@ -0,0 +1,205 @@
     2.4 +/*	$NetBSD: kernfs.h,v 1.20.2.3 2004/05/23 10:46:05 tron Exp $	*/
     2.5 +
     2.6 +/*
     2.7 + * Copyright (c) 1992, 1993
     2.8 + *	The Regents of the University of California.  All rights reserved.
     2.9 + *
    2.10 + * This code is derived from software donated to Berkeley by
    2.11 + * Jan-Simon Pendry.
    2.12 + *
    2.13 + * Redistribution and use in source and binary forms, with or without
    2.14 + * modification, are permitted provided that the following conditions
    2.15 + * are met:
    2.16 + * 1. Redistributions of source code must retain the above copyright
    2.17 + *    notice, this list of conditions and the following disclaimer.
    2.18 + * 2. Redistributions in binary form must reproduce the above copyright
    2.19 + *    notice, this list of conditions and the following disclaimer in the
    2.20 + *    documentation and/or other materials provided with the distribution.
    2.21 + * 3. Neither the name of the University nor the names of its contributors
    2.22 + *    may be used to endorse or promote products derived from this software
    2.23 + *    without specific prior written permission.
    2.24 + *
    2.25 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    2.26 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    2.27 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    2.28 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    2.29 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    2.30 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    2.31 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    2.32 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    2.33 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    2.34 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    2.35 + * SUCH DAMAGE.
    2.36 + *
    2.37 + *	@(#)kernfs.h	8.6 (Berkeley) 3/29/95
    2.38 + */
    2.39 +
    2.40 +#define	_PATH_KERNFS	"/kern"		/* Default mountpoint */
    2.41 +
    2.42 +#ifdef _KERNEL
    2.43 +#include <sys/queue.h>
    2.44 +
    2.45 +/*
    2.46 + * The different types of node in a kernfs filesystem
    2.47 + */
    2.48 +typedef enum {
    2.49 +	KFSkern,		/* the filesystem itself (.) */
    2.50 +	KFSroot,		/* the filesystem root (..) */
    2.51 +	KFSnull,		/* none aplicable */
    2.52 +	KFStime,		/* boottime */
    2.53 +	KFSint,			/* integer */
    2.54 +	KFSstring,		/* string */
    2.55 +	KFShostname,	/* hostname */
    2.56 +	KFSavenrun,		/* loadavg */
    2.57 +	KFSdevice,		/* device file (rootdev/rrootdev) */
    2.58 +	KFSmsgbuf,		/* msgbuf */
    2.59 +	KFSipsecsadir,	/* ipsec security association (top dir) */
    2.60 +	KFSipsecspdir,	/* ipsec security policy (top dir) */
    2.61 +	KFSipsecsa,		/* ipsec security association entry */
    2.62 +	KFSipsecsp,		/* ipsec security policy entry */
    2.63 +	KFSsubdir,		/* directory */
    2.64 +	KFSlasttype,		/* last used type */
    2.65 +	KFSmaxtype = (1<<6) - 1	/* last possible type */
    2.66 +} kfstype;
    2.67 +
    2.68 +/*
    2.69 + * Control data for the kern file system.
    2.70 + */
    2.71 +struct kern_target {
    2.72 +	u_char		kt_type;
    2.73 +	u_char		kt_namlen;
    2.74 +	const char	*kt_name;
    2.75 +	void		*kt_data;
    2.76 +	kfstype		kt_tag;
    2.77 +	u_char		kt_vtype;
    2.78 +	mode_t		kt_mode;
    2.79 +};
    2.80 +
    2.81 +struct dyn_kern_target {
    2.82 +	struct kern_target		dkt_kt;
    2.83 +	SIMPLEQ_ENTRY(dyn_kern_target)	dkt_queue;
    2.84 +};
    2.85 +
    2.86 +struct kernfs_subdir {
    2.87 +	SIMPLEQ_HEAD(,dyn_kern_target)	ks_entries;
    2.88 +	unsigned int			ks_nentries;
    2.89 +	unsigned int			ks_dirs;
    2.90 +	const struct kern_target	*ks_parent;
    2.91 +};
    2.92 +
    2.93 +struct kernfs_node {
    2.94 +	LIST_ENTRY(kernfs_node) kfs_hash; /* hash chain */
    2.95 +	TAILQ_ENTRY(kernfs_node) kfs_list; /* flat list */
    2.96 +	struct vnode	*kfs_vnode;	/* vnode associated with this pfsnode */
    2.97 +	kfstype		kfs_type;	/* type of procfs node */
    2.98 +	mode_t		kfs_mode;	/* mode bits for stat() */
    2.99 +	long		kfs_fileno;	/* unique file id */
   2.100 +	u_int32_t	kfs_value;	/* SA id or SP id (KFSint) */
   2.101 +	const struct kern_target *kfs_kt;
   2.102 +	void		*kfs_v;		/* pointer to secasvar/secpolicy/mbuf */
   2.103 +	long		kfs_cookie;	/* fileno cookie */
   2.104 +};
   2.105 +
   2.106 +struct kernfs_mount {
   2.107 +	TAILQ_HEAD(, kernfs_node) nodelist;
   2.108 +	long fileno_cookie;
   2.109 +};
   2.110 +
   2.111 +#define UIO_MX	32
   2.112 +
   2.113 +#define KERNFS_FILENO(kt, typ, cookie) \
   2.114 +	((kt >= &kern_targets[0] && kt < &kern_targets[static_nkern_targets]) \
   2.115 +	    ? 2 + ((kt) - &kern_targets[0]) \
   2.116 +	      : (((cookie + 1) << 6) | (typ)))
   2.117 +#define KERNFS_TYPE_FILENO(typ, cookie) \
   2.118 +	(((cookie + 1) << 6) | (typ))
   2.119 +
   2.120 +#define VFSTOKERNFS(mp)	((struct kernfs_mount *)((mp)->mnt_data))
   2.121 +#define	VTOKERN(vp)	((struct kernfs_node *)(vp)->v_data)
   2.122 +#define KERNFSTOV(kfs)	((kfs)->kfs_vnode)
   2.123 +
   2.124 +extern const struct kern_target kern_targets[];
   2.125 +extern int nkern_targets;
   2.126 +extern const int static_nkern_targets;
   2.127 +extern int (**kernfs_vnodeop_p) __P((void *));
   2.128 +extern struct vfsops kernfs_vfsops;
   2.129 +extern dev_t rrootdev;
   2.130 +
   2.131 +struct secasvar;
   2.132 +struct secpolicy;
   2.133 +
   2.134 +int kernfs_root __P((struct mount *, struct vnode **));
   2.135 +
   2.136 +void kernfs_hashinit __P((void));
   2.137 +void kernfs_hashreinit __P((void));
   2.138 +void kernfs_hashdone __P((void));
   2.139 +int kernfs_freevp __P((struct vnode *));
   2.140 +int kernfs_allocvp __P((struct mount *, struct vnode **, kfstype,
   2.141 +	const struct kern_target *, u_int32_t));
   2.142 +
   2.143 +void kernfs_revoke_sa __P((struct secasvar *));
   2.144 +void kernfs_revoke_sp __P((struct secpolicy *));
   2.145 +
   2.146 +/*
   2.147 + * Data types for the kernfs file operations.
   2.148 + */
   2.149 +typedef enum {
   2.150 +	KERNFS_XREAD,
   2.151 +	KERNFS_XWRITE,
   2.152 +	KERNFS_FILEOP_CLOSE,
   2.153 +	KERNFS_FILEOP_GETATTR,
   2.154 +	KERNFS_FILEOP_IOCTL,
   2.155 +	KERNFS_FILEOP_MMAP,
   2.156 +	KERNFS_FILEOP_OPEN,
   2.157 +	KERNFS_FILEOP_READ,
   2.158 +	KERNFS_FILEOP_WRITE,
   2.159 +} kfsfileop;
   2.160 +
   2.161 +struct kernfs_fileop {
   2.162 +	kfstype				kf_type;
   2.163 +	kfsfileop			kf_fileop;
   2.164 +	union {
   2.165 +		void			*_kf_genop;
   2.166 +		int			(*_kf_vop)(void *);
   2.167 +		int			(*_kf_xread)
   2.168 +			(const struct kernfs_node *, int, char **, size_t,
   2.169 +			 size_t *);
   2.170 +		int			(*_kf_xwrite)
   2.171 +			(const struct kernfs_node *, char *, size_t);
   2.172 +	} _kf_opfn;
   2.173 +	SPLAY_ENTRY(kernfs_fileop)	kf_node;
   2.174 +};
   2.175 +#define	kf_genop	_kf_opfn
   2.176 +#define	kf_vop		_kf_opfn._kf_vop
   2.177 +#define	kf_xwrite	_kf_opfn._kf_xwrite
   2.178 +#define	kf_xread	_kf_opfn._kf_xread
   2.179 +
   2.180 +typedef struct kern_target kernfs_parentdir_t;
   2.181 +typedef struct dyn_kern_target kernfs_entry_t;
   2.182 +
   2.183 +/*
   2.184 + * Functions for adding kernfs datatypes and nodes.
   2.185 + */
   2.186 +kfstype kernfs_alloctype(int, const struct kernfs_fileop *);
   2.187 +#define	KERNFS_ALLOCTYPE(kf) kernfs_alloctype(sizeof((kf)) / \
   2.188 +	sizeof((kf)[0]), (kf))
   2.189 +#define	KERNFS_ALLOCENTRY(dkt, m_type, m_flags)				\
   2.190 +	dkt = (struct dyn_kern_target *)malloc(				\
   2.191 +		sizeof(struct dyn_kern_target), (m_type), (m_flags))
   2.192 +#define	KERNFS_INITENTRY(dkt, type, name, data, tag, vtype, mode) do {	\
   2.193 +	(dkt)->dkt_kt.kt_type = (type);					\
   2.194 +	(dkt)->dkt_kt.kt_namlen = strlen((name));			\
   2.195 +	(dkt)->dkt_kt.kt_name = (name);					\
   2.196 +	(dkt)->dkt_kt.kt_data = (data);					\
   2.197 +	(dkt)->dkt_kt.kt_tag = (tag);					\
   2.198 +	(dkt)->dkt_kt.kt_vtype = (vtype);				\
   2.199 +	(dkt)->dkt_kt.kt_mode = (mode);					\
   2.200 +} while (/*CONSTCOND*/0)
   2.201 +#define	KERNFS_ENTOPARENTDIR(dkt) &(dkt)->dkt_kt
   2.202 +int kernfs_addentry __P((kernfs_parentdir_t *, kernfs_entry_t *));
   2.203 +
   2.204 +#ifdef SYSCTL_SETUP_PROTO
   2.205 +SYSCTL_SETUP_PROTO(sysctl_vfs_kernfs_setup);
   2.206 +#endif /* SYSCTL_SETUP_PROTO */
   2.207 +
   2.208 +#endif /* _KERNEL */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs_vnops.c	Wed Mar 09 00:37:56 2005 +0000
     3.3 @@ -0,0 +1,1583 @@
     3.4 +/*	$NetBSD: kernfs_vnops.c,v 1.98.2.3 2004/05/15 13:35:27 tron Exp $	*/
     3.5 +
     3.6 +/*
     3.7 + * Copyright (c) 1992, 1993
     3.8 + *	The Regents of the University of California.  All rights reserved.
     3.9 + *
    3.10 + * This code is derived from software donated to Berkeley by
    3.11 + * Jan-Simon Pendry.
    3.12 + *
    3.13 + * Redistribution and use in source and binary forms, with or without
    3.14 + * modification, are permitted provided that the following conditions
    3.15 + * are met:
    3.16 + * 1. Redistributions of source code must retain the above copyright
    3.17 + *    notice, this list of conditions and the following disclaimer.
    3.18 + * 2. Redistributions in binary form must reproduce the above copyright
    3.19 + *    notice, this list of conditions and the following disclaimer in the
    3.20 + *    documentation and/or other materials provided with the distribution.
    3.21 + * 3. Neither the name of the University nor the names of its contributors
    3.22 + *    may be used to endorse or promote products derived from this software
    3.23 + *    without specific prior written permission.
    3.24 + *
    3.25 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    3.26 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    3.27 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    3.28 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    3.29 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    3.30 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    3.31 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    3.32 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    3.33 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    3.34 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    3.35 + * SUCH DAMAGE.
    3.36 + *
    3.37 + *	@(#)kernfs_vnops.c	8.15 (Berkeley) 5/21/95
    3.38 + */
    3.39 +
    3.40 +/*
    3.41 + * Kernel parameter filesystem (/kern)
    3.42 + */
    3.43 +
    3.44 +#include <sys/cdefs.h>
    3.45 +__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.98.2.3 2004/05/15 13:35:27 tron Exp $");
    3.46 +
    3.47 +#ifdef _KERNEL_OPT
    3.48 +#include "opt_ipsec.h"
    3.49 +#endif
    3.50 +
    3.51 +#include <sys/param.h>
    3.52 +#include <sys/systm.h>
    3.53 +#include <sys/kernel.h>
    3.54 +#include <sys/vmmeter.h>
    3.55 +#include <sys/time.h>
    3.56 +#include <sys/proc.h>
    3.57 +#include <sys/vnode.h>
    3.58 +#include <sys/malloc.h>
    3.59 +#include <sys/file.h>
    3.60 +#include <sys/stat.h>
    3.61 +#include <sys/mount.h>
    3.62 +#include <sys/namei.h>
    3.63 +#include <sys/buf.h>
    3.64 +#include <sys/dirent.h>
    3.65 +#include <sys/msgbuf.h>
    3.66 +
    3.67 +#include <miscfs/genfs/genfs.h>
    3.68 +#include <miscfs/kernfs/kernfs.h>
    3.69 +
    3.70 +#ifdef IPSEC
    3.71 +#include <sys/mbuf.h>
    3.72 +#include <net/route.h>
    3.73 +#include <netinet/in.h>
    3.74 +#include <netinet6/ipsec.h>
    3.75 +#include <netkey/key.h>
    3.76 +#endif
    3.77 +
    3.78 +#include <uvm/uvm_extern.h>
    3.79 +
    3.80 +#define KSTRING	256		/* Largest I/O available via this filesystem */
    3.81 +#define	UIO_MX 32
    3.82 +
    3.83 +#define	READ_MODE	(S_IRUSR|S_IRGRP|S_IROTH)
    3.84 +#define	WRITE_MODE	(S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
    3.85 +#define	UREAD_MODE	(S_IRUSR)
    3.86 +#define	DIR_MODE	(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
    3.87 +#define	UDIR_MODE	(S_IRUSR|S_IXUSR)
    3.88 +
    3.89 +#define N(s) sizeof(s)-1, s
    3.90 +const struct kern_target kern_targets[] = {
    3.91 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
    3.92 +     /*        name            data          tag           type  ro/rw */
    3.93 +     { DT_DIR, N("."),         0,            KFSkern,        VDIR, DIR_MODE   },
    3.94 +     { DT_DIR, N(".."),        0,            KFSroot,        VDIR, DIR_MODE   },
    3.95 +     { DT_REG, N("boottime"),  &boottime.tv_sec, KFSint,     VREG, READ_MODE  },
    3.96 +			/* XXX cast away const */
    3.97 +     { DT_REG, N("copyright"), (void *)copyright,
    3.98 +     					     KFSstring,      VREG, READ_MODE  },
    3.99 +     { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },
   3.100 +     { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },
   3.101 +#ifdef IPSEC
   3.102 +     { DT_DIR, N("ipsecsa"),   0,	     KFSipsecsadir,  VDIR, UDIR_MODE  },
   3.103 +     { DT_DIR, N("ipsecsp"),   0,	     KFSipsecspdir,  VDIR, UDIR_MODE  },
   3.104 +#endif
   3.105 +     { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },
   3.106 +     { DT_REG, N("msgbuf"),    0,	     KFSmsgbuf,      VREG, READ_MODE  },
   3.107 +     { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },
   3.108 +     { DT_REG, N("physmem"),   &physmem,     KFSint,         VREG, READ_MODE  },
   3.109 +#if 0
   3.110 +     { DT_DIR, N("root"),      0,            KFSnull,        VDIR, DIR_MODE   },
   3.111 +#endif
   3.112 +     { DT_BLK, N("rootdev"),   &rootdev,     KFSdevice,      VBLK, READ_MODE  },
   3.113 +     { DT_CHR, N("rrootdev"),  &rrootdev,    KFSdevice,      VCHR, READ_MODE  },
   3.114 +     { DT_REG, N("time"),      0,            KFStime,        VREG, READ_MODE  },
   3.115 +			/* XXX cast away const */
   3.116 +     { DT_REG, N("version"),   (void *)version,
   3.117 +     					     KFSstring,      VREG, READ_MODE  },
   3.118 +};
   3.119 +const struct kern_target subdir_targets[] = {
   3.120 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
   3.121 +     /*        name            data          tag           type  ro/rw */
   3.122 +     { DT_DIR, N("."),         0,            KFSsubdir,      VDIR, DIR_MODE   },
   3.123 +     { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
   3.124 +};
   3.125 +#ifdef IPSEC
   3.126 +const struct kern_target ipsecsa_targets[] = {
   3.127 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
   3.128 +     /*        name            data          tag           type  ro/rw */
   3.129 +     { DT_DIR, N("."),         0,            KFSipsecsadir,  VDIR, DIR_MODE   },
   3.130 +     { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
   3.131 +};
   3.132 +const struct kern_target ipsecsp_targets[] = {
   3.133 +/* NOTE: The name must be less than UIO_MX-16 chars in length */
   3.134 +     /*        name            data          tag           type  ro/rw */
   3.135 +     { DT_DIR, N("."),         0,            KFSipsecspdir,  VDIR, DIR_MODE   },
   3.136 +     { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
   3.137 +};
   3.138 +const struct kern_target ipsecsa_kt =
   3.139 +     { DT_DIR, N(""),          0,            KFSipsecsa,     VREG, UREAD_MODE };
   3.140 +const struct kern_target ipsecsp_kt =
   3.141 +     { DT_DIR, N(""),          0,            KFSipsecsp,     VREG, UREAD_MODE };
   3.142 +#endif
   3.143 +#undef N
   3.144 +SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
   3.145 +	SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
   3.146 +int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
   3.147 +const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
   3.148 +#ifdef IPSEC
   3.149 +int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
   3.150 +int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
   3.151 +int nkern_dirs = 4; /* 2 extra subdirs */
   3.152 +#else
   3.153 +int nkern_dirs = 2;
   3.154 +#endif
   3.155 +
   3.156 +int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
   3.157 +int kernfs_try_xread(kfstype, const struct kernfs_node *, int, char **,
   3.158 +    size_t, size_t *, int);
   3.159 +int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
   3.160 +    size_t, int);
   3.161 +
   3.162 +static int kernfs_default_xread(void *v);
   3.163 +static int kernfs_default_xwrite(void *v);
   3.164 +static int kernfs_default_fileop_getattr(void *);
   3.165 +
   3.166 +/* must include all fileop's */
   3.167 +const struct kernfs_fileop kernfs_default_fileops[] = {
   3.168 +  { .kf_fileop = KERNFS_XREAD },
   3.169 +  { .kf_fileop = KERNFS_XWRITE },
   3.170 +  { .kf_fileop = KERNFS_FILEOP_OPEN },
   3.171 +  { .kf_fileop = KERNFS_FILEOP_GETATTR,
   3.172 +    .kf_genop = {kernfs_default_fileop_getattr} },
   3.173 +  { .kf_fileop = KERNFS_FILEOP_IOCTL },
   3.174 +  { .kf_fileop = KERNFS_FILEOP_MMAP },
   3.175 +  { .kf_fileop = KERNFS_FILEOP_CLOSE },
   3.176 +  { .kf_fileop = KERNFS_FILEOP_READ, .kf_genop = {kernfs_default_xread} },
   3.177 +  { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_genop = {kernfs_default_xwrite} },
   3.178 +};
   3.179 +
   3.180 +int	kernfs_lookup	__P((void *));
   3.181 +#define	kernfs_create	genfs_eopnotsupp
   3.182 +#define	kernfs_mknod	genfs_eopnotsupp
   3.183 +int	kernfs_open	__P((void *));
   3.184 +int	kernfs_close	__P((void *));
   3.185 +int	kernfs_access	__P((void *));
   3.186 +int	kernfs_getattr	__P((void *));
   3.187 +int	kernfs_setattr	__P((void *));
   3.188 +int	kernfs_read	__P((void *));
   3.189 +int	kernfs_write	__P((void *));
   3.190 +#define	kernfs_fcntl	genfs_fcntl
   3.191 +int	kernfs_ioctl	__P((void *));
   3.192 +#define	kernfs_poll	genfs_poll
   3.193 +#define kernfs_revoke	genfs_revoke
   3.194 +int	kernfs_mmap	__P((void *));
   3.195 +#define	kernfs_fsync	genfs_nullop
   3.196 +#define	kernfs_seek	genfs_nullop
   3.197 +#define	kernfs_remove	genfs_eopnotsupp
   3.198 +int	kernfs_link	__P((void *));
   3.199 +#define	kernfs_rename	genfs_eopnotsupp
   3.200 +#define	kernfs_mkdir	genfs_eopnotsupp
   3.201 +#define	kernfs_rmdir	genfs_eopnotsupp
   3.202 +int	kernfs_symlink	__P((void *));
   3.203 +int	kernfs_readdir	__P((void *));
   3.204 +#define	kernfs_readlink	genfs_eopnotsupp
   3.205 +#define	kernfs_abortop	genfs_abortop
   3.206 +int	kernfs_inactive	__P((void *));
   3.207 +int	kernfs_reclaim	__P((void *));
   3.208 +#define	kernfs_lock	genfs_lock
   3.209 +#define	kernfs_unlock	genfs_unlock
   3.210 +#define	kernfs_bmap	genfs_badop
   3.211 +#define	kernfs_strategy	genfs_badop
   3.212 +int	kernfs_print	__P((void *));
   3.213 +#define	kernfs_islocked	genfs_islocked
   3.214 +int	kernfs_pathconf	__P((void *));
   3.215 +#define	kernfs_advlock	genfs_einval
   3.216 +#define	kernfs_blkatoff	genfs_eopnotsupp
   3.217 +#define	kernfs_valloc	genfs_eopnotsupp
   3.218 +#define	kernfs_vfree	genfs_nullop
   3.219 +#define	kernfs_truncate	genfs_eopnotsupp
   3.220 +#define	kernfs_update	genfs_nullop
   3.221 +#define	kernfs_bwrite	genfs_eopnotsupp
   3.222 +#define	kernfs_putpages	genfs_putpages
   3.223 +
   3.224 +static int	kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *));
   3.225 +static int	kernfs_xwrite __P((const struct kernfs_node *, char *, size_t));
   3.226 +
   3.227 +int (**kernfs_vnodeop_p) __P((void *));
   3.228 +const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
   3.229 +	{ &vop_default_desc, vn_default_error },
   3.230 +	{ &vop_lookup_desc, kernfs_lookup },		/* lookup */
   3.231 +	{ &vop_create_desc, kernfs_create },		/* create */
   3.232 +	{ &vop_mknod_desc, kernfs_mknod },		/* mknod */
   3.233 +	{ &vop_open_desc, kernfs_open },		/* open */
   3.234 +	{ &vop_close_desc, kernfs_close },		/* close */
   3.235 +	{ &vop_access_desc, kernfs_access },		/* access */
   3.236 +	{ &vop_getattr_desc, kernfs_getattr },		/* getattr */
   3.237 +	{ &vop_setattr_desc, kernfs_setattr },		/* setattr */
   3.238 +	{ &vop_read_desc, kernfs_read },		/* read */
   3.239 +	{ &vop_write_desc, kernfs_write },		/* write */
   3.240 +	{ &vop_fcntl_desc, kernfs_fcntl },		/* fcntl */
   3.241 +	{ &vop_ioctl_desc, kernfs_ioctl },		/* ioctl */
   3.242 +	{ &vop_poll_desc, kernfs_poll },		/* poll */
   3.243 +	{ &vop_revoke_desc, kernfs_revoke },		/* revoke */
   3.244 +	{ &vop_mmap_desc, kernfs_mmap },		/* mmap */
   3.245 +	{ &vop_fsync_desc, kernfs_fsync },		/* fsync */
   3.246 +	{ &vop_seek_desc, kernfs_seek },		/* seek */
   3.247 +	{ &vop_remove_desc, kernfs_remove },		/* remove */
   3.248 +	{ &vop_link_desc, kernfs_link },		/* link */
   3.249 +	{ &vop_rename_desc, kernfs_rename },		/* rename */
   3.250 +	{ &vop_mkdir_desc, kernfs_mkdir },		/* mkdir */
   3.251 +	{ &vop_rmdir_desc, kernfs_rmdir },		/* rmdir */
   3.252 +	{ &vop_symlink_desc, kernfs_symlink },		/* symlink */
   3.253 +	{ &vop_readdir_desc, kernfs_readdir },		/* readdir */
   3.254 +	{ &vop_readlink_desc, kernfs_readlink },	/* readlink */
   3.255 +	{ &vop_abortop_desc, kernfs_abortop },		/* abortop */
   3.256 +	{ &vop_inactive_desc, kernfs_inactive },	/* inactive */
   3.257 +	{ &vop_reclaim_desc, kernfs_reclaim },		/* reclaim */
   3.258 +	{ &vop_lock_desc, kernfs_lock },		/* lock */
   3.259 +	{ &vop_unlock_desc, kernfs_unlock },		/* unlock */
   3.260 +	{ &vop_bmap_desc, kernfs_bmap },		/* bmap */
   3.261 +	{ &vop_strategy_desc, kernfs_strategy },	/* strategy */
   3.262 +	{ &vop_print_desc, kernfs_print },		/* print */
   3.263 +	{ &vop_islocked_desc, kernfs_islocked },	/* islocked */
   3.264 +	{ &vop_pathconf_desc, kernfs_pathconf },	/* pathconf */
   3.265 +	{ &vop_advlock_desc, kernfs_advlock },		/* advlock */
   3.266 +	{ &vop_blkatoff_desc, kernfs_blkatoff },	/* blkatoff */
   3.267 +	{ &vop_valloc_desc, kernfs_valloc },		/* valloc */
   3.268 +	{ &vop_vfree_desc, kernfs_vfree },		/* vfree */
   3.269 +	{ &vop_truncate_desc, kernfs_truncate },	/* truncate */
   3.270 +	{ &vop_update_desc, kernfs_update },		/* update */
   3.271 +	{ &vop_bwrite_desc, kernfs_bwrite },		/* bwrite */
   3.272 +	{ &vop_putpages_desc, kernfs_putpages },	/* putpages */
   3.273 +	{ NULL, NULL }
   3.274 +};
   3.275 +const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
   3.276 +	{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
   3.277 +
   3.278 +static __inline int
   3.279 +kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
   3.280 +{
   3.281 +	if (a->kf_type < b->kf_type)
   3.282 +		return -1;
   3.283 +	if (a->kf_type > b->kf_type)
   3.284 +		return 1;
   3.285 +	if (a->kf_fileop < b->kf_fileop)
   3.286 +		return -1;
   3.287 +	if (a->kf_fileop > b->kf_fileop)
   3.288 +		return 1;
   3.289 +	return (0);
   3.290 +}
   3.291 +
   3.292 +SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
   3.293 +	SPLAY_INITIALIZER(kfsfileoptree);
   3.294 +SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
   3.295 +SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
   3.296 +
   3.297 +kfstype
   3.298 +kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
   3.299 +{
   3.300 +	static u_char nextfreetype = KFSlasttype;
   3.301 +	struct kernfs_fileop *dkf, *fkf, skf;
   3.302 +	int i;
   3.303 +
   3.304 +	/* XXX need to keep track of dkf's memory if we support
   3.305 +           deallocating types */
   3.306 +	dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
   3.307 +	memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
   3.308 +
   3.309 +	for (i = 0; i < sizeof(kernfs_default_fileops) /
   3.310 +		     sizeof(kernfs_default_fileops[0]); i++) {
   3.311 +		dkf[i].kf_type = nextfreetype;
   3.312 +		SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
   3.313 +	}
   3.314 +
   3.315 +	for (i = 0; i < nkf; i++) {
   3.316 +		skf.kf_type = nextfreetype;
   3.317 +		skf.kf_fileop = kf[i].kf_fileop;
   3.318 +		if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
   3.319 +			fkf->kf_genop = kf[i].kf_genop;
   3.320 +	}
   3.321 +
   3.322 +	return nextfreetype++;
   3.323 +}
   3.324 +
   3.325 +int
   3.326 +kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
   3.327 +{
   3.328 +	const struct kernfs_fileop *kf;
   3.329 +	struct kernfs_fileop skf;
   3.330 +
   3.331 +	skf.kf_type = type;
   3.332 +	skf.kf_fileop = fileop;
   3.333 +	kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
   3.334 +	if (kf == NULL)
   3.335 +		kf = &kernfs_default_fileops[fileop];
   3.336 +	if (kf->kf_vop)
   3.337 +		return kf->kf_vop(v);
   3.338 +	return error;
   3.339 +}
   3.340 +
   3.341 +int
   3.342 +kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, int off,
   3.343 +    char **bufp, size_t len, size_t *wrlen, int error)
   3.344 +{
   3.345 +	const struct kernfs_fileop *kf;
   3.346 +	struct kernfs_fileop skf;
   3.347 +
   3.348 +	skf.kf_type = type;
   3.349 +	skf.kf_fileop = KERNFS_XREAD;
   3.350 +	kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
   3.351 +	if (kf == NULL)
   3.352 +		kf = &kernfs_default_fileops[KERNFS_XREAD];
   3.353 +	if (kf->kf_xread)
   3.354 +		return kf->kf_xread(kfs, off, bufp, len, wrlen);
   3.355 +	*wrlen = 0;
   3.356 +	return error;
   3.357 +}
   3.358 +
   3.359 +int
   3.360 +kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *buf,
   3.361 +    size_t len, int error)
   3.362 +{
   3.363 +	const struct kernfs_fileop *kf;
   3.364 +	struct kernfs_fileop skf;
   3.365 +
   3.366 +	skf.kf_type = type;
   3.367 +	skf.kf_fileop = KERNFS_XWRITE;
   3.368 +	kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
   3.369 +	if (kf == NULL)
   3.370 +		kf = &kernfs_default_fileops[KERNFS_XWRITE];
   3.371 +	if (kf->kf_xwrite)
   3.372 +		return kf->kf_xwrite(kfs, buf, len);
   3.373 +	return error;
   3.374 +}
   3.375 +
   3.376 +int
   3.377 +kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
   3.378 +{
   3.379 +	struct kernfs_subdir *ks, *parent;
   3.380 +
   3.381 +	if (pkt == NULL) {
   3.382 +		SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
   3.383 +		nkern_targets++;
   3.384 +		if (dkt->dkt_kt.kt_vtype == VDIR)
   3.385 +			nkern_dirs++;
   3.386 +	} else {
   3.387 +		parent = (struct kernfs_subdir *)pkt->kt_data;
   3.388 +		SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
   3.389 +		parent->ks_nentries++;
   3.390 +		if (dkt->dkt_kt.kt_vtype == VDIR)
   3.391 +			parent->ks_dirs++;
   3.392 +	}
   3.393 +	if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
   3.394 +		ks = malloc(sizeof(struct kernfs_subdir),
   3.395 +		    M_TEMP, M_WAITOK);
   3.396 +		SIMPLEQ_INIT(&ks->ks_entries);
   3.397 +		ks->ks_nentries = 2; /* . and .. */
   3.398 +		ks->ks_dirs = 2;
   3.399 +		ks->ks_parent = pkt ? pkt : &kern_targets[0];
   3.400 +		dkt->dkt_kt.kt_data = ks;
   3.401 +	}
   3.402 +	return 0;
   3.403 +}
   3.404 +
   3.405 +static int
   3.406 +kernfs_xread(kfs, off, bufp, len, wrlen)
   3.407 +	struct kernfs_node *kfs;
   3.408 +	int off;
   3.409 +	char **bufp;
   3.410 +	size_t len;
   3.411 +	size_t *wrlen;
   3.412 +{
   3.413 +	const struct kern_target *kt;
   3.414 +#ifdef IPSEC
   3.415 +	struct mbuf *m;
   3.416 +#endif
   3.417 +
   3.418 +	kt = kfs->kfs_kt;
   3.419 +
   3.420 +	switch (kfs->kfs_type) {
   3.421 +	case KFStime: {
   3.422 +		struct timeval tv;
   3.423 +
   3.424 +		microtime(&tv);
   3.425 +		snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
   3.426 +		break;
   3.427 +	}
   3.428 +
   3.429 +	case KFSint: {
   3.430 +		int *ip = kt->kt_data;
   3.431 +
   3.432 +		snprintf(*bufp, len, "%d\n", *ip);
   3.433 +		break;
   3.434 +	}
   3.435 +
   3.436 +	case KFSstring: {
   3.437 +		char *cp = kt->kt_data;
   3.438 +
   3.439 +		*bufp = cp;
   3.440 +		break;
   3.441 +	}
   3.442 +
   3.443 +	case KFSmsgbuf: {
   3.444 +		long n;
   3.445 +
   3.446 +		/*
   3.447 +		 * deal with cases where the message buffer has
   3.448 +		 * become corrupted.
   3.449 +		 */
   3.450 +		if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
   3.451 +			msgbufenabled = 0;
   3.452 +			return (ENXIO);
   3.453 +		}
   3.454 +
   3.455 +		/*
   3.456 +		 * Note that reads of /kern/msgbuf won't necessarily yield
   3.457 +		 * consistent results, if the message buffer is modified
   3.458 +		 * while the read is in progress.  The worst that can happen
   3.459 +		 * is that incorrect data will be read.  There's no way
   3.460 +		 * that this can crash the system unless the values in the
   3.461 +		 * message buffer header are corrupted, but that'll cause
   3.462 +		 * the system to die anyway.
   3.463 +		 */
   3.464 +		if (off >= msgbufp->msg_bufs) {
   3.465 +			*wrlen = 0;
   3.466 +			return (0);
   3.467 +		}
   3.468 +		n = msgbufp->msg_bufx + off;
   3.469 +		if (n >= msgbufp->msg_bufs)
   3.470 +			n -= msgbufp->msg_bufs;
   3.471 +		len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
   3.472 +		*bufp = msgbufp->msg_bufc + n;
   3.473 +		*wrlen = len;
   3.474 +		return (0);
   3.475 +	}
   3.476 +
   3.477 +	case KFShostname: {
   3.478 +		char *cp = hostname;
   3.479 +		int xlen = hostnamelen;
   3.480 +
   3.481 +		if (xlen >= (len - 2))
   3.482 +			return (EINVAL);
   3.483 +
   3.484 +		memcpy(*bufp, cp, xlen);
   3.485 +		(*bufp)[xlen] = '\n';
   3.486 +		(*bufp)[xlen+1] = '\0';
   3.487 +		len = strlen(*bufp);
   3.488 +		break;
   3.489 +	}
   3.490 +
   3.491 +	case KFSavenrun:
   3.492 +		averunnable.fscale = FSCALE;
   3.493 +		snprintf(*bufp, len, "%d %d %d %ld\n",
   3.494 +		    averunnable.ldavg[0], averunnable.ldavg[1],
   3.495 +		    averunnable.ldavg[2], averunnable.fscale);
   3.496 +		break;
   3.497 +
   3.498 +#ifdef IPSEC
   3.499 +	case KFSipsecsa:
   3.500 +		/*
   3.501 +		 * Note that SA configuration could be changed during the
   3.502 +		 * read operation, resulting in garbled output.
   3.503 +		 */
   3.504 +		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
   3.505 +		if (!m)
   3.506 +			return (ENOBUFS);
   3.507 +		if (off >= m->m_pkthdr.len) {
   3.508 +			*wrlen = 0;
   3.509 +			m_freem(m);
   3.510 +			return (0);
   3.511 +		}
   3.512 +		if (len > m->m_pkthdr.len - off)
   3.513 +			len = m->m_pkthdr.len - off;
   3.514 +		m_copydata(m, off, len, *bufp);
   3.515 +		*wrlen = len;
   3.516 +		m_freem(m);
   3.517 +		return (0);
   3.518 +
   3.519 +	case KFSipsecsp:
   3.520 +		/*
   3.521 +		 * Note that SP configuration could be changed during the
   3.522 +		 * read operation, resulting in garbled output.
   3.523 +		 */
   3.524 +		if (!kfs->kfs_v) {
   3.525 +			struct secpolicy *sp;
   3.526 +
   3.527 +			sp = key_getspbyid(kfs->kfs_value);
   3.528 +			if (sp)
   3.529 +				kfs->kfs_v = sp;
   3.530 +			else
   3.531 +				return (ENOENT);
   3.532 +		}
   3.533 +		m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
   3.534 +		    SADB_X_SPDGET, 0, 0);
   3.535 +		if (!m)
   3.536 +			return (ENOBUFS);
   3.537 +		if (off >= m->m_pkthdr.len) {
   3.538 +			*wrlen = 0;
   3.539 +			m_freem(m);
   3.540 +			return (0);
   3.541 +		}
   3.542 +		if (len > m->m_pkthdr.len - off)
   3.543 +			len = m->m_pkthdr.len - off;
   3.544 +		m_copydata(m, off, len, *bufp);
   3.545 +		*wrlen = len;
   3.546 +		m_freem(m);
   3.547 +		return (0);
   3.548 +#endif
   3.549 +
   3.550 +	default:
   3.551 +		return kernfs_try_xread(kfs->kfs_type, kfs, off, bufp, len,
   3.552 +		    wrlen, 0);
   3.553 +	}
   3.554 +
   3.555 +	len = strlen(*bufp);
   3.556 +	if (len <= off)
   3.557 +		*wrlen = 0;
   3.558 +	else {
   3.559 +		*bufp += off;
   3.560 +		*wrlen = len - off;
   3.561 +	}
   3.562 +	return (0);
   3.563 +}
   3.564 +
   3.565 +static int
   3.566 +kernfs_xwrite(kfs, buf, len)
   3.567 +	const struct kernfs_node *kfs;
   3.568 +	char *buf;
   3.569 +	size_t len;
   3.570 +{
   3.571 +
   3.572 +	switch (kfs->kfs_type) {
   3.573 +	case KFShostname:
   3.574 +		if (buf[len-1] == '\n')
   3.575 +			--len;
   3.576 +		memcpy(hostname, buf, len);
   3.577 +		hostname[len] = '\0';
   3.578 +		hostnamelen = (size_t) len;
   3.579 +		return (0);
   3.580 +
   3.581 +	default:
   3.582 +		return kernfs_try_xwrite(kfs->kfs_type, kfs, buf, len, EIO);
   3.583 +	}
   3.584 +}
   3.585 +
   3.586 +
   3.587 +/*
   3.588 + * vp is the current namei directory
   3.589 + * ndp is the name to locate in that directory...
   3.590 + */
   3.591 +int
   3.592 +kernfs_lookup(v)
   3.593 +	void *v;
   3.594 +{
   3.595 +	struct vop_lookup_args /* {
   3.596 +		struct vnode * a_dvp;
   3.597 +		struct vnode ** a_vpp;
   3.598 +		struct componentname * a_cnp;
   3.599 +	} */ *ap = v;
   3.600 +	struct componentname *cnp = ap->a_cnp;
   3.601 +	struct vnode **vpp = ap->a_vpp;
   3.602 +	struct vnode *dvp = ap->a_dvp;
   3.603 +	const char *pname = cnp->cn_nameptr;
   3.604 +	const struct kernfs_node *kfs;
   3.605 +	const struct kern_target *kt;
   3.606 +	const struct dyn_kern_target *dkt;
   3.607 +	const struct kernfs_subdir *ks;
   3.608 +	int error, i, wantpunlock;
   3.609 +#ifdef IPSEC
   3.610 +	char *ep;
   3.611 +	u_int32_t id;
   3.612 +#endif
   3.613 +
   3.614 +	*vpp = NULLVP;
   3.615 +	cnp->cn_flags &= ~PDIRUNLOCK;
   3.616 +
   3.617 +	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
   3.618 +		return (EROFS);
   3.619 +
   3.620 +	if (cnp->cn_namelen == 1 && *pname == '.') {
   3.621 +		*vpp = dvp;
   3.622 +		VREF(dvp);
   3.623 +		return (0);
   3.624 +	}
   3.625 +
   3.626 +	wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
   3.627 +	kfs = VTOKERN(dvp);
   3.628 +	switch (kfs->kfs_type) {
   3.629 +	case KFSkern:
   3.630 +		/*
   3.631 +		 * Shouldn't get here with .. in the root node.
   3.632 +		 */
   3.633 +		if (cnp->cn_flags & ISDOTDOT)
   3.634 +			return (EIO);
   3.635 +
   3.636 +		for (i = 0; i < static_nkern_targets; i++) {
   3.637 +			kt = &kern_targets[i];
   3.638 +			if (cnp->cn_namelen == kt->kt_namlen &&
   3.639 +			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
   3.640 +				goto found;
   3.641 +		}
   3.642 +		SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
   3.643 +			if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
   3.644 +			    memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
   3.645 +				kt = &dkt->dkt_kt;
   3.646 +				goto found;
   3.647 +			}
   3.648 +		}
   3.649 +		break;
   3.650 +
   3.651 +	found:
   3.652 +		error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
   3.653 +		if ((error == 0) && wantpunlock) {
   3.654 +			VOP_UNLOCK(dvp, 0);
   3.655 +			cnp->cn_flags |= PDIRUNLOCK;
   3.656 +		}
   3.657 +		return (error);
   3.658 +
   3.659 +	case KFSsubdir:
   3.660 +		ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
   3.661 +		if (cnp->cn_flags & ISDOTDOT) {
   3.662 +			kt = ks->ks_parent;
   3.663 +			goto found;
   3.664 +		}
   3.665 +
   3.666 +		SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
   3.667 +			if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
   3.668 +			    memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
   3.669 +				kt = &dkt->dkt_kt;
   3.670 +				goto found;
   3.671 +			}
   3.672 +		}
   3.673 +		break;
   3.674 +
   3.675 +#ifdef IPSEC
   3.676 +	case KFSipsecsadir:
   3.677 +		if (cnp->cn_flags & ISDOTDOT) {
   3.678 +			kt = &kern_targets[0];
   3.679 +			goto found;
   3.680 +		}
   3.681 +
   3.682 +		for (i = 2; i < nipsecsa_targets; i++) {
   3.683 +			kt = &ipsecsa_targets[i];
   3.684 +			if (cnp->cn_namelen == kt->kt_namlen &&
   3.685 +			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
   3.686 +				goto found;
   3.687 +		}
   3.688 +
   3.689 +		ep = NULL;
   3.690 +		id = strtoul(pname, &ep, 10);
   3.691 +		if (!ep || *ep || ep == pname)
   3.692 +			break;
   3.693 +
   3.694 +		error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
   3.695 +		if ((error == 0) && wantpunlock) {
   3.696 +			VOP_UNLOCK(dvp, 0);
   3.697 +			cnp->cn_flags |= PDIRUNLOCK;
   3.698 +		}
   3.699 +		return (error);
   3.700 +
   3.701 +	case KFSipsecspdir:
   3.702 +		if (cnp->cn_flags & ISDOTDOT) {
   3.703 +			kt = &kern_targets[0];
   3.704 +			goto found;
   3.705 +		}
   3.706 +
   3.707 +		for (i = 2; i < nipsecsp_targets; i++) {
   3.708 +			kt = &ipsecsp_targets[i];
   3.709 +			if (cnp->cn_namelen == kt->kt_namlen &&
   3.710 +			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
   3.711 +				goto found;
   3.712 +		}
   3.713 +
   3.714 +		ep = NULL;
   3.715 +		id = strtoul(pname, &ep, 10);
   3.716 +		if (!ep || *ep || ep == pname)
   3.717 +			break;
   3.718 +
   3.719 +		error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
   3.720 +		if ((error == 0) && wantpunlock) {
   3.721 +			VOP_UNLOCK(dvp, 0);
   3.722 +			cnp->cn_flags |= PDIRUNLOCK;
   3.723 +		}
   3.724 +		return (error);
   3.725 +#endif
   3.726 +
   3.727 +	default:
   3.728 +		return (ENOTDIR);
   3.729 +	}
   3.730 +
   3.731 +	return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
   3.732 +}
   3.733 +
   3.734 +int
   3.735 +kernfs_open(v)
   3.736 +	void *v;
   3.737 +{
   3.738 +	struct vop_open_args /* {
   3.739 +		struct vnode *a_vp;
   3.740 +		int a_mode;
   3.741 +		struct ucred *a_cred;
   3.742 +		struct proc *a_p;
   3.743 +	} */ *ap = v;
   3.744 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   3.745 +#ifdef IPSEC
   3.746 +	struct mbuf *m;
   3.747 +	struct secpolicy *sp;
   3.748 +#endif
   3.749 +
   3.750 +	switch (kfs->kfs_type) {
   3.751 +#ifdef IPSEC
   3.752 +	case KFSipsecsa:
   3.753 +		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
   3.754 +		if (m) {
   3.755 +			m_freem(m);
   3.756 +			return (0);
   3.757 +		} else
   3.758 +			return (ENOENT);
   3.759 +
   3.760 +	case KFSipsecsp:
   3.761 +		sp = key_getspbyid(kfs->kfs_value);
   3.762 +		if (sp) {
   3.763 +			kfs->kfs_v = sp;
   3.764 +			return (0);
   3.765 +		} else
   3.766 +			return (ENOENT);
   3.767 +#endif
   3.768 +
   3.769 +	default:
   3.770 +		return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
   3.771 +		    v, 0);
   3.772 +	}
   3.773 +}
   3.774 +
   3.775 +int
   3.776 +kernfs_close(v)
   3.777 +	void *v;
   3.778 +{
   3.779 +	struct vop_close_args /* {
   3.780 +		struct vnode *a_vp;
   3.781 +		int a_fflag;
   3.782 +		struct ucred *a_cred;
   3.783 +		struct proc *a_p;
   3.784 +	} */ *ap = v;
   3.785 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   3.786 +
   3.787 +	switch (kfs->kfs_type) {
   3.788 +#ifdef IPSEC
   3.789 +	case KFSipsecsp:
   3.790 +		key_freesp((struct secpolicy *)kfs->kfs_v);
   3.791 +		break;
   3.792 +#endif
   3.793 +
   3.794 +	default:
   3.795 +		return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
   3.796 +		    v, 0);
   3.797 +	}
   3.798 +
   3.799 +	return (0);
   3.800 +}
   3.801 +
   3.802 +int
   3.803 +kernfs_access(v)
   3.804 +	void *v;
   3.805 +{
   3.806 +	struct vop_access_args /* {
   3.807 +		struct vnode *a_vp;
   3.808 +		int a_mode;
   3.809 +		struct ucred *a_cred;
   3.810 +		struct proc *a_p;
   3.811 +	} */ *ap = v;
   3.812 +	struct vattr va;
   3.813 +	int error;
   3.814 +
   3.815 +	if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
   3.816 +		return (error);
   3.817 +
   3.818 +	return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
   3.819 +	    ap->a_mode, ap->a_cred));
   3.820 +}
   3.821 +
   3.822 +static int
   3.823 +kernfs_default_fileop_getattr(v)
   3.824 +	void *v;
   3.825 +{
   3.826 +	struct vop_getattr_args /* {
   3.827 +		struct vnode *a_vp;
   3.828 +		struct vattr *a_vap;
   3.829 +		struct ucred *a_cred;
   3.830 +		struct proc *a_p;
   3.831 +	} */ *ap = v;
   3.832 +	struct vattr *vap = ap->a_vap;
   3.833 +
   3.834 +	vap->va_nlink = 1;
   3.835 +	vap->va_bytes = vap->va_size = 0;
   3.836 +
   3.837 +	return 0;
   3.838 +}
   3.839 +
   3.840 +int
   3.841 +kernfs_getattr(v)
   3.842 +	void *v;
   3.843 +{
   3.844 +	struct vop_getattr_args /* {
   3.845 +		struct vnode *a_vp;
   3.846 +		struct vattr *a_vap;
   3.847 +		struct ucred *a_cred;
   3.848 +		struct proc *a_p;
   3.849 +	} */ *ap = v;
   3.850 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   3.851 +	struct kernfs_subdir *ks;
   3.852 +	struct vattr *vap = ap->a_vap;
   3.853 +	int error = 0;
   3.854 +	char strbuf[KSTRING], *buf;
   3.855 +	size_t nread, total;
   3.856 +
   3.857 +	VATTR_NULL(vap);
   3.858 +	vap->va_type = ap->a_vp->v_type;
   3.859 +	vap->va_uid = 0;
   3.860 +	vap->va_gid = 0;
   3.861 +	vap->va_mode = kfs->kfs_mode;
   3.862 +	vap->va_fileid = kfs->kfs_fileno;
   3.863 +	vap->va_flags = 0;
   3.864 +	vap->va_size = 0;
   3.865 +	vap->va_blocksize = DEV_BSIZE;
   3.866 +	/*
   3.867 +	 * Make all times be current TOD, except for the "boottime" node.
   3.868 +	 * Avoid microtime(9), it's slow.
   3.869 +	 * We don't guard the read from time(9) with splclock(9) since we
   3.870 +	 * don't actually need to be THAT sure the access is atomic. 
   3.871 +	 */
   3.872 +	if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 && 
   3.873 +	    !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
   3.874 +		TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
   3.875 +	} else {
   3.876 +		TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
   3.877 +	}
   3.878 +	vap->va_atime = vap->va_mtime = vap->va_ctime;
   3.879 +	vap->va_gen = 0;
   3.880 +	vap->va_flags = 0;
   3.881 +	vap->va_rdev = 0;
   3.882 +	vap->va_bytes = 0;
   3.883 +
   3.884 +	switch (kfs->kfs_type) {
   3.885 +	case KFSkern:
   3.886 +		vap->va_nlink = nkern_dirs;
   3.887 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   3.888 +		break;
   3.889 +
   3.890 +	case KFSroot:
   3.891 +		vap->va_nlink = 1;
   3.892 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   3.893 +		break;
   3.894 +
   3.895 +	case KFSsubdir:
   3.896 +		ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
   3.897 +		vap->va_nlink = ks->ks_dirs;
   3.898 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   3.899 +		break;
   3.900 +
   3.901 +	case KFSnull:
   3.902 +	case KFStime:
   3.903 +	case KFSint:
   3.904 +	case KFSstring:
   3.905 +	case KFShostname:
   3.906 +	case KFSavenrun:
   3.907 +	case KFSdevice:
   3.908 +	case KFSmsgbuf:
   3.909 +#ifdef IPSEC
   3.910 +	case KFSipsecsa:
   3.911 +	case KFSipsecsp:
   3.912 +#endif
   3.913 +		vap->va_nlink = 1;
   3.914 +		total = 0;
   3.915 +		do {
   3.916 +			buf = strbuf;
   3.917 +			error = kernfs_xread(kfs, total, &buf,
   3.918 +			    sizeof(strbuf), &nread);
   3.919 +			total += nread;
   3.920 +		} while (error == 0 && nread != 0);
   3.921 +		vap->va_bytes = vap->va_size = total;
   3.922 +		break;
   3.923 +
   3.924 +#ifdef IPSEC
   3.925 +	case KFSipsecsadir:
   3.926 +	case KFSipsecspdir:
   3.927 +		vap->va_nlink = 2;
   3.928 +		vap->va_bytes = vap->va_size = DEV_BSIZE;
   3.929 +		break;
   3.930 +#endif
   3.931 +
   3.932 +	default:
   3.933 +		error = kernfs_try_fileop(kfs->kfs_type,
   3.934 +		    KERNFS_FILEOP_GETATTR, v, EINVAL);
   3.935 +		break;
   3.936 +	}
   3.937 +
   3.938 +	return (error);
   3.939 +}
   3.940 +
   3.941 +/*ARGSUSED*/
   3.942 +int
   3.943 +kernfs_setattr(v)
   3.944 +	void *v;
   3.945 +{
   3.946 +
   3.947 +	/*
   3.948 +	 * Silently ignore attribute changes.
   3.949 +	 * This allows for open with truncate to have no
   3.950 +	 * effect until some data is written.  I want to
   3.951 +	 * do it this way because all writes are atomic.
   3.952 +	 */
   3.953 +	return (0);
   3.954 +}
   3.955 +
   3.956 +static int
   3.957 +kernfs_default_xread(v)
   3.958 +	void *v;
   3.959 +{
   3.960 +	struct vop_read_args /* {
   3.961 +		struct vnode *a_vp;
   3.962 +		struct uio *a_uio;
   3.963 +		int  a_ioflag;
   3.964 +		struct ucred *a_cred;
   3.965 +	} */ *ap = v;
   3.966 +	struct uio *uio = ap->a_uio;
   3.967 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   3.968 +	char strbuf[KSTRING], *buf;
   3.969 +	off_t off;
   3.970 +	size_t len;
   3.971 +	int error;
   3.972 +
   3.973 +	if (ap->a_vp->v_type == VDIR)
   3.974 +		return (EOPNOTSUPP);
   3.975 +
   3.976 +	off = uio->uio_offset;
   3.977 +	buf = strbuf;
   3.978 +	if ((error = kernfs_xread(kfs, off, &buf, sizeof(strbuf), &len)) == 0)
   3.979 +		error = uiomove(buf, len, uio);
   3.980 +	return (error);
   3.981 +}
   3.982 +
   3.983 +int
   3.984 +kernfs_read(v)
   3.985 +	void *v;
   3.986 +{
   3.987 +	struct vop_read_args /* {
   3.988 +		struct vnode *a_vp;
   3.989 +		struct uio *a_uio;
   3.990 +		int  a_ioflag;
   3.991 +		struct ucred *a_cred;
   3.992 +	} */ *ap = v;
   3.993 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   3.994 +
   3.995 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v, 0);
   3.996 +}
   3.997 +
   3.998 +static int
   3.999 +kernfs_default_xwrite(v)
  3.1000 +	void *v;
  3.1001 +{
  3.1002 +	struct vop_write_args /* {
  3.1003 +		struct vnode *a_vp;
  3.1004 +		struct uio *a_uio;
  3.1005 +		int  a_ioflag;
  3.1006 +		struct ucred *a_cred;
  3.1007 +	} */ *ap = v;
  3.1008 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  3.1009 +	struct uio *uio = ap->a_uio;
  3.1010 +	int error, xlen;
  3.1011 +	char strbuf[KSTRING];
  3.1012 +
  3.1013 +	if (uio->uio_offset != 0)
  3.1014 +		return (EINVAL);
  3.1015 +
  3.1016 +	xlen = min(uio->uio_resid, KSTRING-1);
  3.1017 +	if ((error = uiomove(strbuf, xlen, uio)) != 0)
  3.1018 +		return (error);
  3.1019 +
  3.1020 +	if (uio->uio_resid != 0)
  3.1021 +		return (EIO);
  3.1022 +
  3.1023 +	strbuf[xlen] = '\0';
  3.1024 +	xlen = strlen(strbuf);
  3.1025 +	return (kernfs_xwrite(kfs, strbuf, xlen));
  3.1026 +}
  3.1027 +
  3.1028 +int
  3.1029 +kernfs_write(v)
  3.1030 +	void *v;
  3.1031 +{
  3.1032 +	struct vop_write_args /* {
  3.1033 +		struct vnode *a_vp;
  3.1034 +		struct uio *a_uio;
  3.1035 +		int  a_ioflag;
  3.1036 +		struct ucred *a_cred;
  3.1037 +	} */ *ap = v;
  3.1038 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  3.1039 +
  3.1040 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 0);
  3.1041 +}
  3.1042 +
  3.1043 +int
  3.1044 +kernfs_ioctl(v)
  3.1045 +	void *v;
  3.1046 +{
  3.1047 +	struct vop_ioctl_args /* {
  3.1048 +		const struct vnodeop_desc *a_desc;
  3.1049 +		struct vnode *a_vp;
  3.1050 +		u_long a_command;
  3.1051 +		void *a_data;
  3.1052 +		int a_fflag;
  3.1053 +		struct ucred *a_cred;
  3.1054 +		struct proc *a_p;
  3.1055 +	} */ *ap = v;
  3.1056 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  3.1057 +
  3.1058 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
  3.1059 +	    EPASSTHROUGH);
  3.1060 +}
  3.1061 +
  3.1062 +int
  3.1063 +kernfs_mmap(v)
  3.1064 +	void *v;
  3.1065 +{
  3.1066 +	struct vop_mmap_args /* {
  3.1067 +		const struct vnodeop_desc *a_desc;
  3.1068 +		struct vnode *a_vp;
  3.1069 +		int a_fflags;
  3.1070 +		struct ucred *a_cred;
  3.1071 +		struct proc *a_p;
  3.1072 +	} */ *ap = v;
  3.1073 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  3.1074 +
  3.1075 +	return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_MMAP, v, 0);
  3.1076 +}
  3.1077 +
  3.1078 +static int
  3.1079 +kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
  3.1080 +    u_int32_t value, struct vop_readdir_args *ap)
  3.1081 +{
  3.1082 +	struct kernfs_node *kfs;
  3.1083 +	struct vnode *vp;
  3.1084 +	int error;
  3.1085 +
  3.1086 +	if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
  3.1087 +	    value)) != 0)
  3.1088 +		return error;
  3.1089 +	if (kt->kt_tag == KFSdevice) {
  3.1090 +		struct vattr va;
  3.1091 +		if ((error = VOP_GETATTR(vp, &va, ap->a_cred,
  3.1092 +		    ap->a_uio->uio_segflg == UIO_USERSPACE ?
  3.1093 +		    ap->a_uio->uio_procp : &proc0)) != 0)
  3.1094 +			return (error);
  3.1095 +		d->d_fileno = va.va_fileid;
  3.1096 +	} else {
  3.1097 +		kfs = VTOKERN(vp);
  3.1098 +		d->d_fileno = kfs->kfs_fileno;
  3.1099 +	}
  3.1100 +	vput(vp);
  3.1101 +	return 0;
  3.1102 +}
  3.1103 +
  3.1104 +static int
  3.1105 +kernfs_setdirentfileno(struct dirent *d, off_t entry,
  3.1106 +    struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
  3.1107 +    const struct kern_target *kt, struct vop_readdir_args *ap)
  3.1108 +{
  3.1109 +	const struct kern_target *ikt;
  3.1110 +	int error;
  3.1111 +
  3.1112 +	switch (entry) {
  3.1113 +	case 0:
  3.1114 +		d->d_fileno = thisdir_kfs->kfs_fileno;
  3.1115 +		return 0;
  3.1116 +	case 1:
  3.1117 +		ikt = parent_kt;
  3.1118 +		break;
  3.1119 +	default:
  3.1120 +		ikt = kt;
  3.1121 +		break;
  3.1122 +	}
  3.1123 +	if (ikt != thisdir_kfs->kfs_kt) {
  3.1124 +		if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
  3.1125 +			return error;
  3.1126 +	} else
  3.1127 +		d->d_fileno = thisdir_kfs->kfs_fileno;
  3.1128 +	return 0;
  3.1129 +}
  3.1130 +
  3.1131 +int
  3.1132 +kernfs_readdir(v)
  3.1133 +	void *v;
  3.1134 +{
  3.1135 +	struct vop_readdir_args /* {
  3.1136 +		struct vnode *a_vp;
  3.1137 +		struct uio *a_uio;
  3.1138 +		struct ucred *a_cred;
  3.1139 +		int *a_eofflag;
  3.1140 +		off_t **a_cookies;
  3.1141 +		int a_*ncookies;
  3.1142 +	} */ *ap = v;
  3.1143 +	struct uio *uio = ap->a_uio;
  3.1144 +	struct dirent d;
  3.1145 +	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  3.1146 +	const struct kern_target *kt;
  3.1147 +	const struct dyn_kern_target *dkt = NULL;
  3.1148 +	const struct kernfs_subdir *ks;
  3.1149 +	off_t i, j;
  3.1150 +	int error;
  3.1151 +	off_t *cookies = NULL;
  3.1152 +	int ncookies = 0, n;
  3.1153 +#ifdef IPSEC
  3.1154 +	struct secasvar *sav, *sav2;
  3.1155 +	struct secpolicy *sp;
  3.1156 +#endif
  3.1157 +
  3.1158 +	if (uio->uio_resid < UIO_MX)
  3.1159 +		return (EINVAL);
  3.1160 +	if (uio->uio_offset < 0)
  3.1161 +		return (EINVAL);
  3.1162 +
  3.1163 +	error = 0;
  3.1164 +	i = uio->uio_offset;
  3.1165 +	memset(&d, 0, sizeof(d));
  3.1166 +	d.d_reclen = UIO_MX;
  3.1167 +	ncookies = uio->uio_resid / UIO_MX;
  3.1168 +
  3.1169 +	switch (kfs->kfs_type) {
  3.1170 +	case KFSkern:
  3.1171 +		if (i >= nkern_targets)
  3.1172 +			return (0);
  3.1173 +
  3.1174 +		if (ap->a_ncookies) {
  3.1175 +			ncookies = min(ncookies, (nkern_targets - i));
  3.1176 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  3.1177 +			    M_WAITOK);
  3.1178 +			*ap->a_cookies = cookies;
  3.1179 +		}
  3.1180 +
  3.1181 +		n = 0;
  3.1182 +		for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
  3.1183 +			if (i < static_nkern_targets)
  3.1184 +				kt = &kern_targets[i];
  3.1185 +			else {
  3.1186 +				if (dkt == NULL) {
  3.1187 +					dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
  3.1188 +					for (j = static_nkern_targets; j < i &&
  3.1189 +						     dkt != NULL; j++)
  3.1190 +						dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  3.1191 +					if (j != i)
  3.1192 +						break;
  3.1193 +				} else {
  3.1194 +					dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  3.1195 +					if (dkt == NULL)
  3.1196 +						break;
  3.1197 +				}
  3.1198 +				kt = &dkt->dkt_kt;
  3.1199 +			}
  3.1200 +			if (kt->kt_tag == KFSdevice) {
  3.1201 +				dev_t *dp = kt->kt_data;
  3.1202 +				struct vnode *fvp;
  3.1203 +
  3.1204 +				if (*dp == NODEV ||
  3.1205 +				    !vfinddev(*dp, kt->kt_vtype, &fvp))
  3.1206 +					continue;
  3.1207 +			}
  3.1208 +			d.d_namlen = kt->kt_namlen;
  3.1209 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  3.1210 +			    &kern_targets[0], kt, ap)) != 0)
  3.1211 +				break;
  3.1212 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  3.1213 +			d.d_type = kt->kt_type;
  3.1214 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  3.1215 +				break;
  3.1216 +			if (cookies)
  3.1217 +				*cookies++ = i + 1;
  3.1218 +			n++;
  3.1219 +		}
  3.1220 +		ncookies = n;
  3.1221 +		break;
  3.1222 +
  3.1223 +	case KFSroot:
  3.1224 +		if (i >= 2)
  3.1225 +			return 0;
  3.1226 +
  3.1227 +		if (ap->a_ncookies) {
  3.1228 +			ncookies = min(ncookies, (2 - i));
  3.1229 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  3.1230 +			    M_WAITOK);
  3.1231 +			*ap->a_cookies = cookies;
  3.1232 +		}
  3.1233 +
  3.1234 +		n = 0;
  3.1235 +		for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
  3.1236 +			kt = &kern_targets[i];
  3.1237 +			d.d_namlen = kt->kt_namlen;
  3.1238 +			d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
  3.1239 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  3.1240 +			d.d_type = kt->kt_type;
  3.1241 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  3.1242 +				break;
  3.1243 +			if (cookies)
  3.1244 +				*cookies++ = i + 1;
  3.1245 +			n++;
  3.1246 +		}
  3.1247 +		ncookies = n;
  3.1248 +		break;
  3.1249 +
  3.1250 +	case KFSsubdir:
  3.1251 +		ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
  3.1252 +		if (i >= ks->ks_nentries)
  3.1253 +			return (0);
  3.1254 +
  3.1255 +		if (ap->a_ncookies) {
  3.1256 +			ncookies = min(ncookies, (ks->ks_nentries - i));
  3.1257 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  3.1258 +			    M_WAITOK);
  3.1259 +			*ap->a_cookies = cookies;
  3.1260 +		}
  3.1261 +
  3.1262 +		dkt = SIMPLEQ_FIRST(&ks->ks_entries);
  3.1263 +		for (j = 0; j < i && dkt != NULL; j++)
  3.1264 +			dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  3.1265 +		n = 0;
  3.1266 +		for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
  3.1267 +			if (i < 2)
  3.1268 +				kt = &subdir_targets[i];
  3.1269 +			else {
  3.1270 +				/* check if ks_nentries lied to us */
  3.1271 +				if (dkt == NULL)
  3.1272 +					break;
  3.1273 +				kt = &dkt->dkt_kt;
  3.1274 +				dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
  3.1275 +			}
  3.1276 +			if (kt->kt_tag == KFSdevice) {
  3.1277 +				dev_t *dp = kt->kt_data;
  3.1278 +				struct vnode *fvp;
  3.1279 +
  3.1280 +				if (*dp == NODEV ||
  3.1281 +				    !vfinddev(*dp, kt->kt_vtype, &fvp))
  3.1282 +					continue;
  3.1283 +			}
  3.1284 +			d.d_namlen = kt->kt_namlen;
  3.1285 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  3.1286 +			    ks->ks_parent, kt, ap)) != 0)
  3.1287 +				break;
  3.1288 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  3.1289 +			d.d_type = kt->kt_type;
  3.1290 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  3.1291 +				break;
  3.1292 +			if (cookies)
  3.1293 +				*cookies++ = i + 1;
  3.1294 +			n++;
  3.1295 +		}
  3.1296 +		ncookies = n;
  3.1297 +		break;
  3.1298 +
  3.1299 +#ifdef IPSEC
  3.1300 +	case KFSipsecsadir:
  3.1301 +		/* count SA in the system */
  3.1302 +		n = 0;
  3.1303 +		TAILQ_FOREACH(sav, &satailq, tailq) {
  3.1304 +			for (sav2 = TAILQ_FIRST(&satailq);
  3.1305 +			    sav2 != sav;
  3.1306 +			    sav2 = TAILQ_NEXT(sav2, tailq)) {
  3.1307 +				if (sav->spi == sav2->spi) {
  3.1308 +					/* multiple SA with same SPI */
  3.1309 +					break;
  3.1310 +				}
  3.1311 +			}
  3.1312 +			if (sav == sav2 || sav->spi != sav2->spi)
  3.1313 +				n++;
  3.1314 +		}
  3.1315 +
  3.1316 +		if (i >= nipsecsa_targets + n)
  3.1317 +			return (0);
  3.1318 +
  3.1319 +		if (ap->a_ncookies) {
  3.1320 +			ncookies = min(ncookies, (n - i));
  3.1321 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  3.1322 +			    M_WAITOK);
  3.1323 +			*ap->a_cookies = cookies;
  3.1324 +		}
  3.1325 +
  3.1326 +		n = 0;
  3.1327 +		for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
  3.1328 +			kt = &ipsecsa_targets[i];
  3.1329 +			d.d_namlen = kt->kt_namlen;
  3.1330 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  3.1331 +			    &kern_targets[0], kt, ap)) != 0)
  3.1332 +				break;
  3.1333 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  3.1334 +			d.d_type = kt->kt_type;
  3.1335 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  3.1336 +				break;
  3.1337 +			if (cookies)
  3.1338 +				*cookies++ = i + 1;
  3.1339 +			n++;
  3.1340 +		}
  3.1341 +		if (error) {
  3.1342 +			ncookies = n;
  3.1343 +			break;
  3.1344 +		}
  3.1345 +
  3.1346 +		TAILQ_FOREACH(sav, &satailq, tailq) {
  3.1347 +			for (sav2 = TAILQ_FIRST(&satailq);
  3.1348 +			    sav2 != sav;
  3.1349 +			    sav2 = TAILQ_NEXT(sav2, tailq)) {
  3.1350 +				if (sav->spi == sav2->spi) {
  3.1351 +					/* multiple SA with same SPI */
  3.1352 +					break;
  3.1353 +				}
  3.1354 +			}
  3.1355 +			if (sav != sav2 && sav->spi == sav2->spi)
  3.1356 +				continue;
  3.1357 +			if (uio->uio_resid < UIO_MX)
  3.1358 +				break;
  3.1359 +			if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
  3.1360 +			    sav->spi, ap)) != 0)
  3.1361 +				break;
  3.1362 +			d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
  3.1363 +			    "%u", ntohl(sav->spi));
  3.1364 +			d.d_type = DT_REG;
  3.1365 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  3.1366 +				break;
  3.1367 +			if (cookies)
  3.1368 +				*cookies++ = i + 1;
  3.1369 +			n++;
  3.1370 +			i++;
  3.1371 +		}
  3.1372 +		ncookies = n;
  3.1373 +		break;
  3.1374 +
  3.1375 +	case KFSipsecspdir:
  3.1376 +		/* count SP in the system */
  3.1377 +		n = 0;
  3.1378 +		TAILQ_FOREACH(sp, &sptailq, tailq)
  3.1379 +			n++;
  3.1380 +
  3.1381 +		if (i >= nipsecsp_targets + n)
  3.1382 +			return (0);
  3.1383 +
  3.1384 +		if (ap->a_ncookies) {
  3.1385 +			ncookies = min(ncookies, (n - i));
  3.1386 +			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
  3.1387 +			    M_WAITOK);
  3.1388 +			*ap->a_cookies = cookies;
  3.1389 +		}
  3.1390 +
  3.1391 +		n = 0;
  3.1392 +		for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
  3.1393 +			kt = &ipsecsp_targets[i];
  3.1394 +			d.d_namlen = kt->kt_namlen;
  3.1395 +			if ((error = kernfs_setdirentfileno(&d, i, kfs,
  3.1396 +			    &kern_targets[0], kt, ap)) != 0)
  3.1397 +				break;
  3.1398 +			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
  3.1399 +			d.d_type = kt->kt_type;
  3.1400 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  3.1401 +				break;
  3.1402 +			if (cookies)
  3.1403 +				*cookies++ = i + 1;
  3.1404 +			n++;
  3.1405 +		}
  3.1406 +		if (error) {
  3.1407 +			ncookies = n;
  3.1408 +			break;
  3.1409 +		}
  3.1410 +
  3.1411 +		TAILQ_FOREACH(sp, &sptailq, tailq) {
  3.1412 +			if (uio->uio_resid < UIO_MX)
  3.1413 +				break;
  3.1414 +			if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
  3.1415 +			    sp->id, ap)) != 0)
  3.1416 +				break;
  3.1417 +			d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
  3.1418 +			    "%u", sp->id);
  3.1419 +			d.d_type = DT_REG;
  3.1420 +			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
  3.1421 +				break;
  3.1422 +			if (cookies)
  3.1423 +				*cookies++ = i + 1;
  3.1424 +			n++;
  3.1425 +			i++;
  3.1426 +		}
  3.1427 +		ncookies = n;
  3.1428 +		break;
  3.1429 +#endif
  3.1430 +
  3.1431 +	default:
  3.1432 +		error = ENOTDIR;
  3.1433 +		break;
  3.1434 +	}
  3.1435 +
  3.1436 +	if (ap->a_ncookies) {
  3.1437 +		if (error) {
  3.1438 +			if (cookies)
  3.1439 +				free(*ap->a_cookies, M_TEMP);
  3.1440 +			*ap->a_ncookies = 0;
  3.1441 +			*ap->a_cookies = NULL;
  3.1442 +		} else
  3.1443 +			*ap->a_ncookies = ncookies;
  3.1444 +	}
  3.1445 +
  3.1446 +	uio->uio_offset = i;
  3.1447 +	return (error);
  3.1448 +}
  3.1449 +
  3.1450 +int
  3.1451 +kernfs_inactive(v)
  3.1452 +	void *v;
  3.1453 +{
  3.1454 +	struct vop_inactive_args /* {
  3.1455 +		struct vnode *a_vp;
  3.1456 +		struct proc *a_p;
  3.1457 +	} */ *ap = v;
  3.1458 +	struct vnode *vp = ap->a_vp;
  3.1459 +	const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
  3.1460 +#ifdef IPSEC
  3.1461 +	struct mbuf *m;
  3.1462 +	struct secpolicy *sp;
  3.1463 +#endif
  3.1464 +
  3.1465 +	VOP_UNLOCK(vp, 0);
  3.1466 +	switch (kfs->kfs_type) {
  3.1467 +#ifdef IPSEC
  3.1468 +	case KFSipsecsa:
  3.1469 +		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
  3.1470 +		if (m)
  3.1471 +			m_freem(m);
  3.1472 +		else
  3.1473 +			vgone(vp);
  3.1474 +		break;
  3.1475 +	case KFSipsecsp:
  3.1476 +		sp = key_getspbyid(kfs->kfs_value);
  3.1477 +		if (sp)
  3.1478 +			key_freesp(sp);
  3.1479 +		else {
  3.1480 +			/* should never happen as we hold a refcnt */
  3.1481 +			vgone(vp);
  3.1482 +		}
  3.1483 +		break;
  3.1484 +#endif
  3.1485 +	default:
  3.1486 +		break;
  3.1487 +	}
  3.1488 +	return (0);
  3.1489 +}
  3.1490 +
  3.1491 +int
  3.1492 +kernfs_reclaim(v)
  3.1493 +	void *v;
  3.1494 +{
  3.1495 +	struct vop_reclaim_args /* {
  3.1496 +		struct vnode *a_vp;
  3.1497 +	} */ *ap = v;
  3.1498 +
  3.1499 +	return (kernfs_freevp(ap->a_vp));
  3.1500 +}
  3.1501 +
  3.1502 +/*
  3.1503 + * Return POSIX pathconf information applicable to special devices.
  3.1504 + */
  3.1505 +int
  3.1506 +kernfs_pathconf(v)
  3.1507 +	void *v;
  3.1508 +{
  3.1509 +	struct vop_pathconf_args /* {
  3.1510 +		struct vnode *a_vp;
  3.1511 +		int a_name;
  3.1512 +		register_t *a_retval;
  3.1513 +	} */ *ap = v;
  3.1514 +
  3.1515 +	switch (ap->a_name) {
  3.1516 +	case _PC_LINK_MAX:
  3.1517 +		*ap->a_retval = LINK_MAX;
  3.1518 +		return (0);
  3.1519 +	case _PC_MAX_CANON:
  3.1520 +		*ap->a_retval = MAX_CANON;
  3.1521 +		return (0);
  3.1522 +	case _PC_MAX_INPUT:
  3.1523 +		*ap->a_retval = MAX_INPUT;
  3.1524 +		return (0);
  3.1525 +	case _PC_PIPE_BUF:
  3.1526 +		*ap->a_retval = PIPE_BUF;
  3.1527 +		return (0);
  3.1528 +	case _PC_CHOWN_RESTRICTED:
  3.1529 +		*ap->a_retval = 1;
  3.1530 +		return (0);
  3.1531 +	case _PC_VDISABLE:
  3.1532 +		*ap->a_retval = _POSIX_VDISABLE;
  3.1533 +		return (0);
  3.1534 +	case _PC_SYNC_IO:
  3.1535 +		*ap->a_retval = 1;
  3.1536 +		return (0);
  3.1537 +	default:
  3.1538 +		return (EINVAL);
  3.1539 +	}
  3.1540 +	/* NOTREACHED */
  3.1541 +}
  3.1542 +
  3.1543 +/*
  3.1544 + * Print out the contents of a /dev/fd vnode.
  3.1545 + */
  3.1546 +/* ARGSUSED */
  3.1547 +int
  3.1548 +kernfs_print(v)
  3.1549 +	void *v;
  3.1550 +{
  3.1551 +
  3.1552 +	printf("tag VT_KERNFS, kernfs vnode\n");
  3.1553 +	return (0);
  3.1554 +}
  3.1555 +
  3.1556 +int
  3.1557 +kernfs_link(v) 
  3.1558 +	void *v;
  3.1559 +{
  3.1560 +	struct vop_link_args /* {
  3.1561 +		struct vnode *a_dvp;
  3.1562 +		struct vnode *a_vp;  
  3.1563 +		struct componentname *a_cnp;
  3.1564 +	} */ *ap = v;
  3.1565 + 
  3.1566 +	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  3.1567 +	vput(ap->a_dvp);
  3.1568 +	return (EROFS);
  3.1569 +}
  3.1570 +
  3.1571 +int
  3.1572 +kernfs_symlink(v)
  3.1573 +	void *v;
  3.1574 +{
  3.1575 +	struct vop_symlink_args /* {
  3.1576 +		struct vnode *a_dvp;
  3.1577 +		struct vnode **a_vpp;
  3.1578 +		struct componentname *a_cnp;
  3.1579 +		struct vattr *a_vap;
  3.1580 +		char *a_target;
  3.1581 +	} */ *ap = v;
  3.1582 +  
  3.1583 +	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  3.1584 +	vput(ap->a_dvp);
  3.1585 +	return (EROFS);
  3.1586 +}