Home | History | Annotate | Line # | Download | only in kernfs
kernfs_vnops.c revision 1.98.2.1
      1  1.98.2.1       jdc /*	$NetBSD: kernfs_vnops.c,v 1.98.2.1 2004/05/14 06:31:44 jdc Exp $	*/
      2      1.27       cgd 
      3       1.1       cgd /*
      4      1.23   mycroft  * Copyright (c) 1992, 1993
      5      1.23   mycroft  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7      1.17       cgd  * This code is derived from software donated to Berkeley by
      8       1.1       cgd  * Jan-Simon Pendry.
      9       1.1       cgd  *
     10       1.2       cgd  * Redistribution and use in source and binary forms, with or without
     11       1.2       cgd  * modification, are permitted provided that the following conditions
     12       1.2       cgd  * are met:
     13       1.2       cgd  * 1. Redistributions of source code must retain the above copyright
     14       1.2       cgd  *    notice, this list of conditions and the following disclaimer.
     15       1.2       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.2       cgd  *    notice, this list of conditions and the following disclaimer in the
     17       1.2       cgd  *    documentation and/or other materials provided with the distribution.
     18      1.89       agc  * 3. Neither the name of the University nor the names of its contributors
     19       1.2       cgd  *    may be used to endorse or promote products derived from this software
     20       1.2       cgd  *    without specific prior written permission.
     21       1.1       cgd  *
     22       1.2       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23       1.2       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24       1.2       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25       1.2       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26       1.2       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27       1.2       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28       1.2       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29       1.2       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30       1.2       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31       1.2       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32       1.2       cgd  * SUCH DAMAGE.
     33       1.1       cgd  *
     34      1.57      fvdl  *	@(#)kernfs_vnops.c	8.15 (Berkeley) 5/21/95
     35       1.1       cgd  */
     36       1.1       cgd 
     37       1.1       cgd /*
     38      1.23   mycroft  * Kernel parameter filesystem (/kern)
     39       1.1       cgd  */
     40      1.77     lukem 
     41      1.77     lukem #include <sys/cdefs.h>
     42  1.98.2.1       jdc __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.98.2.1 2004/05/14 06:31:44 jdc Exp $");
     43      1.90    itojun 
     44      1.90    itojun #ifdef _KERNEL_OPT
     45      1.90    itojun #include "opt_ipsec.h"
     46      1.90    itojun #endif
     47      1.55       mrg 
     48      1.14   mycroft #include <sys/param.h>
     49      1.14   mycroft #include <sys/systm.h>
     50      1.14   mycroft #include <sys/kernel.h>
     51      1.23   mycroft #include <sys/vmmeter.h>
     52      1.14   mycroft #include <sys/time.h>
     53      1.14   mycroft #include <sys/proc.h>
     54      1.23   mycroft #include <sys/vnode.h>
     55      1.23   mycroft #include <sys/malloc.h>
     56      1.14   mycroft #include <sys/file.h>
     57      1.14   mycroft #include <sys/stat.h>
     58      1.14   mycroft #include <sys/mount.h>
     59      1.14   mycroft #include <sys/namei.h>
     60      1.14   mycroft #include <sys/buf.h>
     61      1.23   mycroft #include <sys/dirent.h>
     62      1.28   mycroft #include <sys/msgbuf.h>
     63      1.44   mycroft 
     64      1.44   mycroft #include <miscfs/genfs/genfs.h>
     65      1.17       cgd #include <miscfs/kernfs/kernfs.h>
     66      1.63       mrg 
     67      1.90    itojun #ifdef IPSEC
     68      1.90    itojun #include <sys/mbuf.h>
     69      1.90    itojun #include <net/route.h>
     70      1.90    itojun #include <netinet/in.h>
     71      1.90    itojun #include <netinet6/ipsec.h>
     72      1.90    itojun #include <netkey/key.h>
     73      1.90    itojun #endif
     74      1.90    itojun 
     75      1.54       mrg #include <uvm/uvm_extern.h>
     76      1.54       mrg 
     77      1.17       cgd #define KSTRING	256		/* Largest I/O available via this filesystem */
     78      1.17       cgd #define	UIO_MX 32
     79       1.1       cgd 
     80      1.23   mycroft #define	READ_MODE	(S_IRUSR|S_IRGRP|S_IROTH)
     81      1.23   mycroft #define	WRITE_MODE	(S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
     82  1.98.2.1       jdc #define	UREAD_MODE	(S_IRUSR)
     83      1.23   mycroft #define DIR_MODE	(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
     84      1.90    itojun #define UDIR_MODE	(S_IRUSR|S_IXUSR)
     85      1.23   mycroft 
     86      1.90    itojun #define N(s) sizeof(s)-1, s
     87      1.75  jdolecek const struct kern_target kern_targets[] = {
     88       1.1       cgd /* NOTE: The name must be less than UIO_MX-16 chars in length */
     89      1.23   mycroft      /*        name            data          tag           type  ro/rw */
     90      1.98     darcy      { DT_DIR, N("."),         0,            KFSkern,        VDIR, DIR_MODE   },
     91      1.98     darcy      { DT_DIR, N(".."),        0,            KFSroot,        VDIR, DIR_MODE   },
     92      1.98     darcy      { DT_REG, N("boottime"),  &boottime.tv_sec, KFSint,     VREG, READ_MODE  },
     93      1.69   thorpej 			/* XXX cast away const */
     94      1.69   thorpej      { DT_REG, N("copyright"), (void *)copyright,
     95      1.98     darcy      					     KFSstring,      VREG, READ_MODE  },
     96      1.98     darcy      { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },
     97      1.98     darcy      { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },
     98      1.90    itojun #ifdef IPSEC
     99      1.98     darcy      { DT_DIR, N("ipsecsa"),   0,	     KFSipsecsadir,  VDIR, UDIR_MODE  },
    100      1.98     darcy      { DT_DIR, N("ipsecsp"),   0,	     KFSipsecspdir,  VDIR, UDIR_MODE  },
    101      1.90    itojun #endif
    102      1.98     darcy      { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },
    103      1.98     darcy      { DT_REG, N("msgbuf"),    0,	     KFSmsgbuf,      VREG, READ_MODE  },
    104      1.98     darcy      { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },
    105      1.98     darcy      { DT_REG, N("physmem"),   &physmem,     KFSint,         VREG, READ_MODE  },
    106      1.17       cgd #if 0
    107      1.98     darcy      { DT_DIR, N("root"),      0,            KFSnull,        VDIR, DIR_MODE   },
    108      1.17       cgd #endif
    109      1.98     darcy      { DT_BLK, N("rootdev"),   &rootdev,     KFSdevice,      VBLK, READ_MODE  },
    110      1.98     darcy      { DT_CHR, N("rrootdev"),  &rrootdev,    KFSdevice,      VCHR, READ_MODE  },
    111      1.98     darcy      { DT_REG, N("time"),      0,            KFStime,        VREG, READ_MODE  },
    112      1.69   thorpej 			/* XXX cast away const */
    113      1.69   thorpej      { DT_REG, N("version"),   (void *)version,
    114      1.98     darcy      					     KFSstring,      VREG, READ_MODE  },
    115      1.90    itojun };
    116      1.90    itojun #ifdef IPSEC
    117      1.90    itojun const struct kern_target ipsecsa_targets[] = {
    118      1.90    itojun /* NOTE: The name must be less than UIO_MX-16 chars in length */
    119      1.90    itojun      /*        name            data          tag           type  ro/rw */
    120      1.98     darcy      { DT_DIR, N("."),         0,            KFSipsecsadir,  VDIR, DIR_MODE   },
    121      1.98     darcy      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
    122      1.90    itojun };
    123      1.90    itojun const struct kern_target ipsecsp_targets[] = {
    124      1.90    itojun /* NOTE: The name must be less than UIO_MX-16 chars in length */
    125      1.90    itojun      /*        name            data          tag           type  ro/rw */
    126      1.98     darcy      { DT_DIR, N("."),         0,            KFSipsecspdir,  VDIR, DIR_MODE   },
    127      1.98     darcy      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
    128      1.90    itojun };
    129  1.98.2.1       jdc const struct kern_target ipsecsa_kt =
    130  1.98.2.1       jdc      { DT_DIR, N(""),          0,            KFSipsecsa,     VREG, UREAD_MODE };
    131  1.98.2.1       jdc const struct kern_target ipsecsp_kt =
    132  1.98.2.1       jdc      { DT_DIR, N(""),          0,            KFSipsecsp,     VREG, UREAD_MODE };
    133      1.90    itojun #endif
    134      1.23   mycroft #undef N
    135      1.90    itojun int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
    136      1.90    itojun #ifdef IPSEC
    137      1.90    itojun int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
    138      1.90    itojun int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
    139      1.90    itojun #endif
    140      1.90    itojun 
    141       1.1       cgd 
    142      1.41  christos int	kernfs_lookup	__P((void *));
    143      1.85  jdolecek #define	kernfs_create	genfs_eopnotsupp
    144      1.85  jdolecek #define	kernfs_mknod	genfs_eopnotsupp
    145      1.90    itojun int	kernfs_open	__P((void *));
    146      1.90    itojun int	kernfs_close	__P((void *));
    147      1.41  christos int	kernfs_access	__P((void *));
    148      1.41  christos int	kernfs_getattr	__P((void *));
    149      1.41  christos int	kernfs_setattr	__P((void *));
    150      1.41  christos int	kernfs_read	__P((void *));
    151      1.41  christos int	kernfs_write	__P((void *));
    152      1.65  wrstuden #define	kernfs_fcntl	genfs_fcntl
    153      1.61  matthias #define	kernfs_ioctl	genfs_enoioctl
    154      1.45   mycroft #define	kernfs_poll	genfs_poll
    155      1.57      fvdl #define kernfs_revoke	genfs_revoke
    156      1.44   mycroft #define	kernfs_fsync	genfs_nullop
    157      1.44   mycroft #define	kernfs_seek	genfs_nullop
    158      1.85  jdolecek #define	kernfs_remove	genfs_eopnotsupp
    159      1.41  christos int	kernfs_link	__P((void *));
    160      1.85  jdolecek #define	kernfs_rename	genfs_eopnotsupp
    161      1.85  jdolecek #define	kernfs_mkdir	genfs_eopnotsupp
    162      1.85  jdolecek #define	kernfs_rmdir	genfs_eopnotsupp
    163      1.41  christos int	kernfs_symlink	__P((void *));
    164      1.41  christos int	kernfs_readdir	__P((void *));
    165      1.44   mycroft #define	kernfs_readlink	genfs_eopnotsupp
    166      1.44   mycroft #define	kernfs_abortop	genfs_abortop
    167      1.41  christos int	kernfs_inactive	__P((void *));
    168      1.41  christos int	kernfs_reclaim	__P((void *));
    169      1.64  wrstuden #define	kernfs_lock	genfs_lock
    170      1.64  wrstuden #define	kernfs_unlock	genfs_unlock
    171      1.44   mycroft #define	kernfs_bmap	genfs_badop
    172      1.44   mycroft #define	kernfs_strategy	genfs_badop
    173      1.41  christos int	kernfs_print	__P((void *));
    174      1.64  wrstuden #define	kernfs_islocked	genfs_islocked
    175      1.41  christos int	kernfs_pathconf	__P((void *));
    176      1.62    kleink #define	kernfs_advlock	genfs_einval
    177      1.44   mycroft #define	kernfs_blkatoff	genfs_eopnotsupp
    178      1.44   mycroft #define	kernfs_valloc	genfs_eopnotsupp
    179      1.44   mycroft #define	kernfs_vfree	genfs_nullop
    180      1.44   mycroft #define	kernfs_truncate	genfs_eopnotsupp
    181      1.44   mycroft #define	kernfs_update	genfs_nullop
    182      1.44   mycroft #define	kernfs_bwrite	genfs_eopnotsupp
    183      1.79       chs #define	kernfs_putpages	genfs_putpages
    184      1.41  christos 
    185      1.90    itojun static int	kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *));
    186      1.90    itojun static int	kernfs_xwrite __P((const struct kernfs_node *, char *, size_t));
    187      1.41  christos 
    188      1.41  christos int (**kernfs_vnodeop_p) __P((void *));
    189      1.71  jdolecek const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
    190      1.41  christos 	{ &vop_default_desc, vn_default_error },
    191      1.44   mycroft 	{ &vop_lookup_desc, kernfs_lookup },		/* lookup */
    192      1.44   mycroft 	{ &vop_create_desc, kernfs_create },		/* create */
    193      1.44   mycroft 	{ &vop_mknod_desc, kernfs_mknod },		/* mknod */
    194      1.44   mycroft 	{ &vop_open_desc, kernfs_open },		/* open */
    195      1.44   mycroft 	{ &vop_close_desc, kernfs_close },		/* close */
    196      1.44   mycroft 	{ &vop_access_desc, kernfs_access },		/* access */
    197      1.44   mycroft 	{ &vop_getattr_desc, kernfs_getattr },		/* getattr */
    198      1.44   mycroft 	{ &vop_setattr_desc, kernfs_setattr },		/* setattr */
    199      1.44   mycroft 	{ &vop_read_desc, kernfs_read },		/* read */
    200      1.44   mycroft 	{ &vop_write_desc, kernfs_write },		/* write */
    201      1.65  wrstuden 	{ &vop_fcntl_desc, kernfs_fcntl },		/* fcntl */
    202      1.44   mycroft 	{ &vop_ioctl_desc, kernfs_ioctl },		/* ioctl */
    203      1.45   mycroft 	{ &vop_poll_desc, kernfs_poll },		/* poll */
    204      1.57      fvdl 	{ &vop_revoke_desc, kernfs_revoke },		/* revoke */
    205      1.44   mycroft 	{ &vop_fsync_desc, kernfs_fsync },		/* fsync */
    206      1.44   mycroft 	{ &vop_seek_desc, kernfs_seek },		/* seek */
    207      1.44   mycroft 	{ &vop_remove_desc, kernfs_remove },		/* remove */
    208      1.44   mycroft 	{ &vop_link_desc, kernfs_link },		/* link */
    209      1.44   mycroft 	{ &vop_rename_desc, kernfs_rename },		/* rename */
    210      1.44   mycroft 	{ &vop_mkdir_desc, kernfs_mkdir },		/* mkdir */
    211      1.44   mycroft 	{ &vop_rmdir_desc, kernfs_rmdir },		/* rmdir */
    212      1.44   mycroft 	{ &vop_symlink_desc, kernfs_symlink },		/* symlink */
    213      1.44   mycroft 	{ &vop_readdir_desc, kernfs_readdir },		/* readdir */
    214      1.44   mycroft 	{ &vop_readlink_desc, kernfs_readlink },	/* readlink */
    215      1.44   mycroft 	{ &vop_abortop_desc, kernfs_abortop },		/* abortop */
    216      1.44   mycroft 	{ &vop_inactive_desc, kernfs_inactive },	/* inactive */
    217      1.44   mycroft 	{ &vop_reclaim_desc, kernfs_reclaim },		/* reclaim */
    218      1.44   mycroft 	{ &vop_lock_desc, kernfs_lock },		/* lock */
    219      1.44   mycroft 	{ &vop_unlock_desc, kernfs_unlock },		/* unlock */
    220      1.44   mycroft 	{ &vop_bmap_desc, kernfs_bmap },		/* bmap */
    221      1.44   mycroft 	{ &vop_strategy_desc, kernfs_strategy },	/* strategy */
    222      1.44   mycroft 	{ &vop_print_desc, kernfs_print },		/* print */
    223      1.44   mycroft 	{ &vop_islocked_desc, kernfs_islocked },	/* islocked */
    224      1.44   mycroft 	{ &vop_pathconf_desc, kernfs_pathconf },	/* pathconf */
    225      1.44   mycroft 	{ &vop_advlock_desc, kernfs_advlock },		/* advlock */
    226      1.44   mycroft 	{ &vop_blkatoff_desc, kernfs_blkatoff },	/* blkatoff */
    227      1.44   mycroft 	{ &vop_valloc_desc, kernfs_valloc },		/* valloc */
    228      1.44   mycroft 	{ &vop_vfree_desc, kernfs_vfree },		/* vfree */
    229      1.44   mycroft 	{ &vop_truncate_desc, kernfs_truncate },	/* truncate */
    230      1.44   mycroft 	{ &vop_update_desc, kernfs_update },		/* update */
    231      1.44   mycroft 	{ &vop_bwrite_desc, kernfs_bwrite },		/* bwrite */
    232      1.79       chs 	{ &vop_putpages_desc, kernfs_putpages },	/* putpages */
    233      1.76       chs 	{ NULL, NULL }
    234      1.41  christos };
    235      1.71  jdolecek const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
    236      1.41  christos 	{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
    237      1.41  christos 
    238      1.82  jdolecek static int
    239      1.90    itojun kernfs_xread(kfs, off, bufp, len, wrlen)
    240      1.90    itojun 	struct kernfs_node *kfs;
    241      1.28   mycroft 	int off;
    242      1.28   mycroft 	char **bufp;
    243      1.82  jdolecek 	size_t len;
    244      1.82  jdolecek 	size_t *wrlen;
    245       1.1       cgd {
    246      1.90    itojun 	const struct kern_target *kt;
    247      1.90    itojun #ifdef IPSEC
    248      1.90    itojun 	struct mbuf *m;
    249      1.90    itojun #endif
    250      1.90    itojun 
    251      1.90    itojun 	kt = kfs->kfs_kt;
    252       1.1       cgd 
    253      1.90    itojun 	switch (kfs->kfs_type) {
    254      1.98     darcy 	case KFStime: {
    255       1.1       cgd 		struct timeval tv;
    256      1.28   mycroft 
    257       1.1       cgd 		microtime(&tv);
    258      1.90    itojun 		snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
    259       1.1       cgd 		break;
    260       1.1       cgd 	}
    261       1.1       cgd 
    262      1.98     darcy 	case KFSint: {
    263       1.1       cgd 		int *ip = kt->kt_data;
    264      1.28   mycroft 
    265      1.90    itojun 		snprintf(*bufp, len, "%d\n", *ip);
    266       1.1       cgd 		break;
    267       1.1       cgd 	}
    268       1.1       cgd 
    269      1.98     darcy 	case KFSstring: {
    270       1.1       cgd 		char *cp = kt->kt_data;
    271       1.1       cgd 
    272      1.28   mycroft 		*bufp = cp;
    273      1.28   mycroft 		break;
    274      1.28   mycroft 	}
    275       1.1       cgd 
    276      1.98     darcy 	case KFSmsgbuf: {
    277      1.28   mycroft 		long n;
    278      1.28   mycroft 
    279      1.52       leo 		/*
    280      1.52       leo 		 * deal with cases where the message buffer has
    281      1.52       leo 		 * become corrupted.
    282      1.52       leo 		 */
    283      1.52       leo 		if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
    284      1.52       leo 			msgbufenabled = 0;
    285      1.52       leo 			return (ENXIO);
    286      1.52       leo 		}
    287      1.52       leo 
    288      1.52       leo 		/*
    289      1.52       leo 		 * Note that reads of /kern/msgbuf won't necessarily yield
    290      1.52       leo 		 * consistent results, if the message buffer is modified
    291      1.52       leo 		 * while the read is in progress.  The worst that can happen
    292      1.52       leo 		 * is that incorrect data will be read.  There's no way
    293      1.52       leo 		 * that this can crash the system unless the values in the
    294      1.52       leo 		 * message buffer header are corrupted, but that'll cause
    295      1.52       leo 		 * the system to die anyway.
    296      1.52       leo 		 */
    297      1.82  jdolecek 		if (off >= msgbufp->msg_bufs) {
    298      1.82  jdolecek 			*wrlen = 0;
    299      1.28   mycroft 			return (0);
    300      1.82  jdolecek 		}
    301      1.28   mycroft 		n = msgbufp->msg_bufx + off;
    302      1.52       leo 		if (n >= msgbufp->msg_bufs)
    303      1.52       leo 			n -= msgbufp->msg_bufs;
    304      1.52       leo 		len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
    305      1.28   mycroft 		*bufp = msgbufp->msg_bufc + n;
    306      1.82  jdolecek 		*wrlen = len;
    307      1.82  jdolecek 		return (0);
    308       1.1       cgd 	}
    309       1.1       cgd 
    310      1.98     darcy 	case KFShostname: {
    311       1.1       cgd 		char *cp = hostname;
    312       1.1       cgd 		int xlen = hostnamelen;
    313       1.1       cgd 
    314      1.90    itojun 		if (xlen >= (len - 2))
    315       1.1       cgd 			return (EINVAL);
    316       1.1       cgd 
    317      1.60     perry 		memcpy(*bufp, cp, xlen);
    318      1.28   mycroft 		(*bufp)[xlen] = '\n';
    319      1.28   mycroft 		(*bufp)[xlen+1] = '\0';
    320      1.90    itojun 		len = strlen(*bufp);
    321       1.1       cgd 		break;
    322       1.1       cgd 	}
    323       1.1       cgd 
    324      1.98     darcy 	case KFSavenrun:
    325      1.31   mycroft 		averunnable.fscale = FSCALE;
    326      1.90    itojun 		snprintf(*bufp, len, "%d %d %d %ld\n",
    327      1.23   mycroft 		    averunnable.ldavg[0], averunnable.ldavg[1],
    328      1.23   mycroft 		    averunnable.ldavg[2], averunnable.fscale);
    329       1.1       cgd 		break;
    330       1.1       cgd 
    331      1.90    itojun #ifdef IPSEC
    332      1.98     darcy 	case KFSipsecsa:
    333      1.90    itojun 		/*
    334      1.90    itojun 		 * Note that SA configuration could be changed during the
    335      1.90    itojun 		 * read operation, resulting in garbled output.
    336      1.90    itojun 		 */
    337      1.90    itojun 		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
    338      1.90    itojun 		if (!m)
    339      1.90    itojun 			return (ENOBUFS);
    340      1.90    itojun 		if (off >= m->m_pkthdr.len) {
    341      1.90    itojun 			*wrlen = 0;
    342      1.90    itojun 			m_freem(m);
    343      1.90    itojun 			return (0);
    344      1.90    itojun 		}
    345      1.90    itojun 		if (len > m->m_pkthdr.len - off)
    346      1.90    itojun 			len = m->m_pkthdr.len - off;
    347      1.90    itojun 		m_copydata(m, off, len, *bufp);
    348      1.90    itojun 		*wrlen = len;
    349      1.90    itojun 		m_freem(m);
    350      1.90    itojun 		return (0);
    351      1.90    itojun 
    352      1.98     darcy 	case KFSipsecsp:
    353      1.90    itojun 		/*
    354      1.90    itojun 		 * Note that SP configuration could be changed during the
    355      1.90    itojun 		 * read operation, resulting in garbled output.
    356      1.90    itojun 		 */
    357      1.90    itojun 		if (!kfs->kfs_v) {
    358      1.90    itojun 			struct secpolicy *sp;
    359      1.90    itojun 
    360      1.90    itojun 			sp = key_getspbyid(kfs->kfs_value);
    361      1.90    itojun 			if (sp)
    362      1.90    itojun 				kfs->kfs_v = sp;
    363      1.90    itojun 			else
    364      1.90    itojun 				return (ENOENT);
    365      1.90    itojun 		}
    366      1.90    itojun 		m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
    367      1.90    itojun 		    SADB_X_SPDGET, 0, 0);
    368      1.90    itojun 		if (!m)
    369      1.90    itojun 			return (ENOBUFS);
    370      1.90    itojun 		if (off >= m->m_pkthdr.len) {
    371      1.90    itojun 			*wrlen = 0;
    372      1.90    itojun 			m_freem(m);
    373      1.90    itojun 			return (0);
    374      1.90    itojun 		}
    375      1.90    itojun 		if (len > m->m_pkthdr.len - off)
    376      1.90    itojun 			len = m->m_pkthdr.len - off;
    377      1.90    itojun 		m_copydata(m, off, len, *bufp);
    378      1.90    itojun 		*wrlen = len;
    379      1.90    itojun 		m_freem(m);
    380      1.90    itojun 		return (0);
    381      1.90    itojun #endif
    382      1.90    itojun 
    383       1.1       cgd 	default:
    384      1.82  jdolecek 		*wrlen = 0;
    385      1.28   mycroft 		return (0);
    386       1.1       cgd 	}
    387       1.1       cgd 
    388      1.28   mycroft 	len = strlen(*bufp);
    389      1.28   mycroft 	if (len <= off)
    390      1.82  jdolecek 		*wrlen = 0;
    391      1.82  jdolecek 	else {
    392      1.82  jdolecek 		*bufp += off;
    393      1.82  jdolecek 		*wrlen = len - off;
    394      1.82  jdolecek 	}
    395      1.82  jdolecek 	return (0);
    396       1.1       cgd }
    397       1.1       cgd 
    398      1.82  jdolecek static int
    399      1.90    itojun kernfs_xwrite(kfs, buf, len)
    400      1.90    itojun 	const struct kernfs_node *kfs;
    401       1.1       cgd 	char *buf;
    402      1.82  jdolecek 	size_t len;
    403       1.1       cgd {
    404      1.23   mycroft 
    405      1.90    itojun 	switch (kfs->kfs_type) {
    406      1.98     darcy 	case KFShostname:
    407       1.1       cgd 		if (buf[len-1] == '\n')
    408       1.1       cgd 			--len;
    409      1.60     perry 		memcpy(hostname, buf, len);
    410      1.17       cgd 		hostname[len] = '\0';
    411      1.82  jdolecek 		hostnamelen = (size_t) len;
    412       1.1       cgd 		return (0);
    413       1.1       cgd 
    414       1.1       cgd 	default:
    415       1.1       cgd 		return (EIO);
    416       1.1       cgd 	}
    417       1.1       cgd }
    418       1.1       cgd 
    419      1.17       cgd 
    420      1.17       cgd /*
    421       1.1       cgd  * vp is the current namei directory
    422       1.1       cgd  * ndp is the name to locate in that directory...
    423       1.1       cgd  */
    424      1.41  christos int
    425      1.41  christos kernfs_lookup(v)
    426      1.41  christos 	void *v;
    427      1.41  christos {
    428      1.23   mycroft 	struct vop_lookup_args /* {
    429      1.23   mycroft 		struct vnode * a_dvp;
    430      1.23   mycroft 		struct vnode ** a_vpp;
    431      1.23   mycroft 		struct componentname * a_cnp;
    432      1.41  christos 	} */ *ap = v;
    433      1.23   mycroft 	struct componentname *cnp = ap->a_cnp;
    434      1.23   mycroft 	struct vnode **vpp = ap->a_vpp;
    435      1.23   mycroft 	struct vnode *dvp = ap->a_dvp;
    436      1.48       cgd 	const char *pname = cnp->cn_nameptr;
    437      1.90    itojun 	const struct kernfs_node *kfs;
    438      1.75  jdolecek 	const struct kern_target *kt;
    439      1.64  wrstuden 	int error, i, wantpunlock;
    440      1.90    itojun #ifdef IPSEC
    441      1.90    itojun 	char *ep;
    442      1.90    itojun 	u_int32_t id;
    443       1.1       cgd #endif
    444      1.23   mycroft 
    445      1.35   mycroft 	*vpp = NULLVP;
    446      1.64  wrstuden 	cnp->cn_flags &= ~PDIRUNLOCK;
    447      1.35   mycroft 
    448      1.35   mycroft 	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
    449      1.35   mycroft 		return (EROFS);
    450      1.35   mycroft 
    451      1.23   mycroft 	if (cnp->cn_namelen == 1 && *pname == '.') {
    452      1.23   mycroft 		*vpp = dvp;
    453       1.1       cgd 		VREF(dvp);
    454       1.1       cgd 		return (0);
    455       1.1       cgd 	}
    456      1.13       cgd 
    457      1.90    itojun 	wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
    458      1.90    itojun 	kfs = VTOKERN(dvp);
    459      1.90    itojun 	switch (kfs->kfs_type) {
    460      1.98     darcy 	case KFSkern:
    461      1.90    itojun 		/*
    462      1.90    itojun 		 * Shouldn't get here with .. in the root node.
    463      1.90    itojun 		 */
    464      1.90    itojun 		if (cnp->cn_flags & ISDOTDOT)
    465      1.90    itojun 			return (EIO);
    466      1.64  wrstuden 
    467      1.90    itojun 		for (i = 0; i < nkern_targets; i++) {
    468      1.90    itojun 			kt = &kern_targets[i];
    469      1.90    itojun 			if (cnp->cn_namelen == kt->kt_namlen &&
    470      1.90    itojun 			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
    471      1.90    itojun 				goto found;
    472      1.90    itojun 		}
    473      1.90    itojun 		break;
    474      1.25   mycroft 
    475      1.90    itojun 	found:
    476      1.90    itojun 		error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
    477      1.90    itojun 		if ((error == 0) && wantpunlock) {
    478      1.90    itojun 			VOP_UNLOCK(dvp, 0);
    479      1.90    itojun 			cnp->cn_flags |= PDIRUNLOCK;
    480      1.90    itojun 		}
    481      1.90    itojun 		return (error);
    482      1.64  wrstuden 
    483      1.90    itojun #ifdef IPSEC
    484      1.98     darcy 	case KFSipsecsadir:
    485  1.98.2.1       jdc 		if (cnp->cn_flags & ISDOTDOT) {
    486  1.98.2.1       jdc 			kt = &kern_targets[0];
    487  1.98.2.1       jdc 			goto found;
    488  1.98.2.1       jdc 		}
    489  1.98.2.1       jdc 
    490  1.98.2.1       jdc 		for (i = 2; i < nipsecsa_targets; i++) {
    491      1.90    itojun 			kt = &ipsecsa_targets[i];
    492      1.90    itojun 			if (cnp->cn_namelen == kt->kt_namlen &&
    493  1.98.2.1       jdc 			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
    494  1.98.2.1       jdc 				goto found;
    495      1.90    itojun 		}
    496       1.1       cgd 
    497      1.90    itojun 		ep = NULL;
    498      1.90    itojun 		id = strtoul(pname, &ep, 10);
    499      1.90    itojun 		if (!ep || *ep || ep == pname)
    500      1.90    itojun 			break;
    501       1.1       cgd 
    502  1.98.2.1       jdc 		error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
    503      1.90    itojun 		if ((error == 0) && wantpunlock) {
    504      1.90    itojun 			VOP_UNLOCK(dvp, 0);
    505      1.90    itojun 			cnp->cn_flags |= PDIRUNLOCK;
    506      1.90    itojun 		}
    507      1.90    itojun 		return (error);
    508      1.23   mycroft 
    509      1.98     darcy 	case KFSipsecspdir:
    510  1.98.2.1       jdc 		if (cnp->cn_flags & ISDOTDOT) {
    511  1.98.2.1       jdc 			kt = &kern_targets[0];
    512  1.98.2.1       jdc 			goto found;
    513  1.98.2.1       jdc 		}
    514  1.98.2.1       jdc 
    515  1.98.2.1       jdc 		for (i = 2; i < nipsecsp_targets; i++) {
    516      1.90    itojun 			kt = &ipsecsp_targets[i];
    517      1.90    itojun 			if (cnp->cn_namelen == kt->kt_namlen &&
    518  1.98.2.1       jdc 			    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
    519  1.98.2.1       jdc 				goto found;
    520      1.57      fvdl 		}
    521      1.90    itojun 
    522      1.90    itojun 		ep = NULL;
    523      1.90    itojun 		id = strtoul(pname, &ep, 10);
    524      1.90    itojun 		if (!ep || *ep || ep == pname)
    525      1.90    itojun 			break;
    526      1.90    itojun 
    527  1.98.2.1       jdc 		error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
    528      1.90    itojun 		if ((error == 0) && wantpunlock) {
    529      1.64  wrstuden 			VOP_UNLOCK(dvp, 0);
    530      1.64  wrstuden 			cnp->cn_flags |= PDIRUNLOCK;
    531      1.64  wrstuden 		}
    532      1.90    itojun 		return (error);
    533      1.90    itojun #endif
    534      1.90    itojun 
    535      1.90    itojun 	default:
    536      1.90    itojun 		return (ENOTDIR);
    537      1.90    itojun 	}
    538      1.90    itojun 
    539      1.90    itojun 	return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
    540      1.90    itojun }
    541      1.90    itojun 
    542      1.90    itojun int
    543      1.90    itojun kernfs_open(v)
    544      1.90    itojun 	void *v;
    545      1.90    itojun {
    546      1.90    itojun 	struct vop_open_args /* {
    547      1.90    itojun 		struct vnode *a_vp;
    548      1.90    itojun 		int a_mode;
    549      1.90    itojun 		struct ucred *a_cred;
    550      1.90    itojun 		struct proc *a_p;
    551      1.90    itojun 	} */ *ap = v;
    552      1.90    itojun 	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
    553      1.90    itojun #ifdef IPSEC
    554      1.90    itojun 	struct mbuf *m;
    555      1.90    itojun 	struct secpolicy *sp;
    556      1.90    itojun #endif
    557      1.90    itojun 
    558      1.90    itojun 	switch (kfs->kfs_type) {
    559      1.90    itojun #ifdef IPSEC
    560      1.98     darcy 	case KFSipsecsa:
    561      1.90    itojun 		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
    562      1.90    itojun 		if (m) {
    563      1.90    itojun 			m_freem(m);
    564      1.90    itojun 			return (0);
    565      1.90    itojun 		} else
    566      1.90    itojun 			return (ENOENT);
    567      1.90    itojun 
    568      1.98     darcy 	case KFSipsecsp:
    569      1.90    itojun 		sp = key_getspbyid(kfs->kfs_value);
    570      1.90    itojun 		if (sp) {
    571      1.90    itojun 			kfs->kfs_v = sp;
    572      1.90    itojun 			return (0);
    573      1.90    itojun 		} else
    574      1.90    itojun 			return (ENOENT);
    575      1.90    itojun #endif
    576      1.90    itojun 
    577      1.90    itojun 	default:
    578      1.23   mycroft 		return (0);
    579      1.23   mycroft 	}
    580      1.90    itojun }
    581       1.1       cgd 
    582      1.90    itojun int
    583      1.90    itojun kernfs_close(v)
    584      1.90    itojun 	void *v;
    585      1.90    itojun {
    586      1.90    itojun 	struct vop_close_args /* {
    587      1.90    itojun 		struct vnode *a_vp;
    588      1.90    itojun 		int a_fflag;
    589      1.90    itojun 		struct ucred *a_cred;
    590      1.90    itojun 		struct proc *a_p;
    591      1.90    itojun 	} */ *ap = v;
    592      1.90    itojun 	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
    593      1.90    itojun 
    594      1.90    itojun 	switch (kfs->kfs_type) {
    595      1.90    itojun #ifdef IPSEC
    596      1.98     darcy 	case KFSipsecsp:
    597      1.90    itojun 		key_freesp((struct secpolicy *)kfs->kfs_v);
    598      1.90    itojun 		break;
    599       1.1       cgd #endif
    600      1.90    itojun 
    601      1.90    itojun 	default:
    602      1.90    itojun 		break;
    603      1.57      fvdl 	}
    604      1.23   mycroft 
    605       1.1       cgd 	return (0);
    606       1.1       cgd }
    607       1.1       cgd 
    608      1.28   mycroft int
    609      1.41  christos kernfs_access(v)
    610      1.41  christos 	void *v;
    611      1.41  christos {
    612      1.23   mycroft 	struct vop_access_args /* {
    613      1.23   mycroft 		struct vnode *a_vp;
    614      1.34   mycroft 		int a_mode;
    615      1.23   mycroft 		struct ucred *a_cred;
    616      1.23   mycroft 		struct proc *a_p;
    617      1.41  christos 	} */ *ap = v;
    618      1.90    itojun 	struct vattr va;
    619      1.90    itojun 	int error;
    620      1.17       cgd 
    621      1.90    itojun 	if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
    622      1.90    itojun 		return (error);
    623      1.49   mycroft 
    624      1.90    itojun 	return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
    625      1.90    itojun 	    ap->a_mode, ap->a_cred));
    626      1.23   mycroft }
    627      1.23   mycroft 
    628      1.41  christos int
    629      1.41  christos kernfs_getattr(v)
    630      1.41  christos 	void *v;
    631      1.41  christos {
    632      1.23   mycroft 	struct vop_getattr_args /* {
    633      1.23   mycroft 		struct vnode *a_vp;
    634      1.23   mycroft 		struct vattr *a_vap;
    635      1.23   mycroft 		struct ucred *a_cred;
    636      1.23   mycroft 		struct proc *a_p;
    637      1.41  christos 	} */ *ap = v;
    638      1.90    itojun 	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
    639      1.23   mycroft 	struct vattr *vap = ap->a_vap;
    640       1.1       cgd 	int error = 0;
    641      1.28   mycroft 	char strbuf[KSTRING], *buf;
    642      1.90    itojun 	size_t nread, total;
    643       1.1       cgd 
    644      1.90    itojun 	VATTR_NULL(vap);
    645      1.90    itojun 	vap->va_type = ap->a_vp->v_type;
    646      1.17       cgd 	vap->va_uid = 0;
    647      1.17       cgd 	vap->va_gid = 0;
    648      1.90    itojun 	vap->va_mode = kfs->kfs_mode;
    649      1.90    itojun 	vap->va_fileid = kfs->kfs_fileno;
    650      1.90    itojun 	vap->va_flags = 0;
    651      1.23   mycroft 	vap->va_size = 0;
    652       1.1       cgd 	vap->va_blocksize = DEV_BSIZE;
    653      1.81     lukem 	/*
    654      1.92       dan 	 * Make all times be current TOD, except for the "boottime" node.
    655      1.93    simonb 	 * Avoid microtime(9), it's slow.
    656      1.83    simonb 	 * We don't guard the read from time(9) with splclock(9) since we
    657      1.83    simonb 	 * don't actually need to be THAT sure the access is atomic.
    658      1.81     lukem 	 */
    659      1.96    itojun 	if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&
    660      1.92       dan 	    !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
    661      1.92       dan 		TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
    662      1.92       dan 	} else {
    663      1.92       dan 		TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
    664      1.92       dan 	}
    665      1.81     lukem 	vap->va_atime = vap->va_mtime = vap->va_ctime;
    666       1.1       cgd 	vap->va_gen = 0;
    667       1.1       cgd 	vap->va_flags = 0;
    668       1.1       cgd 	vap->va_rdev = 0;
    669       1.1       cgd 	vap->va_bytes = 0;
    670       1.1       cgd 
    671      1.90    itojun 	switch (kfs->kfs_type) {
    672      1.98     darcy 	case KFSkern:
    673      1.95       dan #ifdef IPSEC
    674      1.95       dan 		vap->va_nlink = 4; /* 2 extra subdirs */
    675      1.95       dan #else
    676      1.95       dan 		vap->va_nlink = 2;
    677      1.95       dan #endif
    678      1.90    itojun 		vap->va_bytes = vap->va_size = DEV_BSIZE;
    679      1.90    itojun 		break;
    680      1.90    itojun 
    681      1.98     darcy 	case KFSroot:
    682      1.90    itojun 		vap->va_nlink = 1;
    683      1.90    itojun 		vap->va_bytes = vap->va_size = DEV_BSIZE;
    684      1.90    itojun 		break;
    685      1.90    itojun 
    686      1.98     darcy 	case KFSnull:
    687      1.98     darcy 	case KFStime:
    688      1.98     darcy 	case KFSint:
    689      1.98     darcy 	case KFSstring:
    690      1.98     darcy 	case KFShostname:
    691      1.98     darcy 	case KFSavenrun:
    692      1.98     darcy 	case KFSdevice:
    693      1.98     darcy 	case KFSmsgbuf:
    694      1.90    itojun #ifdef IPSEC
    695      1.98     darcy 	case KFSipsecsa:
    696      1.98     darcy 	case KFSipsecsp:
    697       1.1       cgd #endif
    698       1.1       cgd 		vap->va_nlink = 1;
    699      1.84  jdolecek 		total = 0;
    700      1.84  jdolecek 		do {
    701      1.84  jdolecek 			buf = strbuf;
    702      1.90    itojun 			error = kernfs_xread(kfs, total, &buf,
    703      1.90    itojun 			    sizeof(strbuf), &nread);
    704      1.84  jdolecek 			total += nread;
    705      1.84  jdolecek 		} while (error == 0 && nread != 0);
    706      1.90    itojun 		vap->va_bytes = vap->va_size = total;
    707      1.90    itojun 		break;
    708      1.90    itojun 
    709      1.90    itojun #ifdef IPSEC
    710      1.98     darcy 	case KFSipsecsadir:
    711      1.98     darcy 	case KFSipsecspdir:
    712      1.90    itojun 		vap->va_nlink = 2;
    713      1.90    itojun 		vap->va_bytes = vap->va_size = DEV_BSIZE;
    714      1.90    itojun 		break;
    715      1.90    itojun #endif
    716      1.90    itojun 
    717      1.90    itojun 	default:
    718      1.90    itojun 		error = EINVAL;
    719      1.90    itojun 		break;
    720       1.1       cgd 	}
    721       1.1       cgd 
    722       1.1       cgd 	return (error);
    723       1.1       cgd }
    724       1.1       cgd 
    725      1.41  christos /*ARGSUSED*/
    726      1.41  christos int
    727      1.41  christos kernfs_setattr(v)
    728      1.41  christos 	void *v;
    729       1.1       cgd {
    730      1.90    itojun 
    731       1.1       cgd 	/*
    732      1.17       cgd 	 * Silently ignore attribute changes.
    733      1.17       cgd 	 * This allows for open with truncate to have no
    734      1.17       cgd 	 * effect until some data is written.  I want to
    735      1.17       cgd 	 * do it this way because all writes are atomic.
    736       1.1       cgd 	 */
    737      1.17       cgd 	return (0);
    738       1.1       cgd }
    739       1.1       cgd 
    740      1.28   mycroft int
    741      1.41  christos kernfs_read(v)
    742      1.41  christos 	void *v;
    743      1.41  christos {
    744      1.23   mycroft 	struct vop_read_args /* {
    745      1.23   mycroft 		struct vnode *a_vp;
    746      1.23   mycroft 		struct uio *a_uio;
    747      1.23   mycroft 		int  a_ioflag;
    748      1.23   mycroft 		struct ucred *a_cred;
    749      1.41  christos 	} */ *ap = v;
    750      1.23   mycroft 	struct uio *uio = ap->a_uio;
    751      1.90    itojun 	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
    752      1.28   mycroft 	char strbuf[KSTRING], *buf;
    753      1.82  jdolecek 	off_t off;
    754      1.82  jdolecek 	size_t len;
    755      1.28   mycroft 	int error;
    756      1.23   mycroft 
    757      1.90    itojun 	if (ap->a_vp->v_type == VDIR)
    758      1.23   mycroft 		return (EOPNOTSUPP);
    759      1.23   mycroft 
    760      1.28   mycroft 	off = uio->uio_offset;
    761      1.82  jdolecek 	buf = strbuf;
    762      1.90    itojun 	if ((error = kernfs_xread(kfs, off, &buf, sizeof(strbuf), &len)) == 0)
    763      1.82  jdolecek 		error = uiomove(buf, len, uio);
    764      1.82  jdolecek 	return (error);
    765       1.1       cgd }
    766       1.1       cgd 
    767      1.28   mycroft int
    768      1.41  christos kernfs_write(v)
    769      1.41  christos 	void *v;
    770      1.41  christos {
    771      1.23   mycroft 	struct vop_write_args /* {
    772      1.23   mycroft 		struct vnode *a_vp;
    773      1.23   mycroft 		struct uio *a_uio;
    774      1.23   mycroft 		int  a_ioflag;
    775      1.23   mycroft 		struct ucred *a_cred;
    776      1.41  christos 	} */ *ap = v;
    777      1.90    itojun 	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
    778      1.23   mycroft 	struct uio *uio = ap->a_uio;
    779      1.23   mycroft 	int error, xlen;
    780       1.1       cgd 	char strbuf[KSTRING];
    781      1.23   mycroft 
    782       1.1       cgd 	if (uio->uio_offset != 0)
    783       1.1       cgd 		return (EINVAL);
    784       1.1       cgd 
    785       1.1       cgd 	xlen = min(uio->uio_resid, KSTRING-1);
    786      1.41  christos 	if ((error = uiomove(strbuf, xlen, uio)) != 0)
    787       1.1       cgd 		return (error);
    788       1.1       cgd 
    789       1.1       cgd 	if (uio->uio_resid != 0)
    790       1.1       cgd 		return (EIO);
    791       1.1       cgd 
    792       1.1       cgd 	strbuf[xlen] = '\0';
    793      1.17       cgd 	xlen = strlen(strbuf);
    794      1.90    itojun 	return (kernfs_xwrite(kfs, strbuf, xlen));
    795       1.1       cgd }
    796       1.1       cgd 
    797  1.98.2.1       jdc static int
    798  1.98.2.1       jdc kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
    799  1.98.2.1       jdc     u_int32_t value, struct vop_readdir_args *ap)
    800  1.98.2.1       jdc {
    801  1.98.2.1       jdc 	struct kernfs_node *kfs;
    802  1.98.2.1       jdc 	struct vnode *vp;
    803  1.98.2.1       jdc 	int error;
    804  1.98.2.1       jdc 
    805  1.98.2.1       jdc 	if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
    806  1.98.2.1       jdc 	    value)) != 0)
    807  1.98.2.1       jdc 		return error;
    808  1.98.2.1       jdc 	if (kt->kt_tag == KFSdevice) {
    809  1.98.2.1       jdc 		struct vattr va;
    810  1.98.2.1       jdc 		if ((error = VOP_GETATTR(vp, &va, ap->a_cred,
    811  1.98.2.1       jdc 		    ap->a_uio->uio_segflg == UIO_USERSPACE ?
    812  1.98.2.1       jdc 		    ap->a_uio->uio_procp : &proc0)) != 0)
    813  1.98.2.1       jdc 			return (error);
    814  1.98.2.1       jdc 		d->d_fileno = va.va_fileid;
    815  1.98.2.1       jdc 	} else {
    816  1.98.2.1       jdc 		kfs = VTOKERN(vp);
    817  1.98.2.1       jdc 		d->d_fileno = kfs->kfs_fileno;
    818  1.98.2.1       jdc 	}
    819  1.98.2.1       jdc 	vput(vp);
    820  1.98.2.1       jdc 	return 0;
    821  1.98.2.1       jdc }
    822  1.98.2.1       jdc 
    823  1.98.2.1       jdc static int
    824  1.98.2.1       jdc kernfs_setdirentfileno(struct dirent *d, off_t entry,
    825  1.98.2.1       jdc     struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
    826  1.98.2.1       jdc     const struct kern_target *kt, struct vop_readdir_args *ap)
    827  1.98.2.1       jdc {
    828  1.98.2.1       jdc 	const struct kern_target *ikt;
    829  1.98.2.1       jdc 	int error;
    830  1.98.2.1       jdc 
    831  1.98.2.1       jdc 	switch (entry) {
    832  1.98.2.1       jdc 	case 0:
    833  1.98.2.1       jdc 		d->d_fileno = thisdir_kfs->kfs_fileno;
    834  1.98.2.1       jdc 		return 0;
    835  1.98.2.1       jdc 	case 1:
    836  1.98.2.1       jdc 		ikt = parent_kt;
    837  1.98.2.1       jdc 		break;
    838  1.98.2.1       jdc 	default:
    839  1.98.2.1       jdc 		ikt = kt;
    840  1.98.2.1       jdc 		break;
    841  1.98.2.1       jdc 	}
    842  1.98.2.1       jdc 	if (ikt != thisdir_kfs->kfs_kt) {
    843  1.98.2.1       jdc 		if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
    844  1.98.2.1       jdc 			return error;
    845  1.98.2.1       jdc 	} else
    846  1.98.2.1       jdc 		d->d_fileno = thisdir_kfs->kfs_fileno;
    847  1.98.2.1       jdc 	return 0;
    848  1.98.2.1       jdc }
    849  1.98.2.1       jdc 
    850      1.41  christos int
    851      1.41  christos kernfs_readdir(v)
    852      1.41  christos 	void *v;
    853      1.41  christos {
    854      1.23   mycroft 	struct vop_readdir_args /* {
    855      1.23   mycroft 		struct vnode *a_vp;
    856      1.23   mycroft 		struct uio *a_uio;
    857      1.23   mycroft 		struct ucred *a_cred;
    858      1.26   mycroft 		int *a_eofflag;
    859      1.57      fvdl 		off_t **a_cookies;
    860      1.57      fvdl 		int a_*ncookies;
    861      1.41  christos 	} */ *ap = v;
    862      1.23   mycroft 	struct uio *uio = ap->a_uio;
    863      1.37   mycroft 	struct dirent d;
    864      1.90    itojun 	struct kernfs_node *kfs = VTOKERN(ap->a_vp);
    865      1.75  jdolecek 	const struct kern_target *kt;
    866      1.67  sommerfe 	off_t i;
    867       1.1       cgd 	int error;
    868      1.57      fvdl 	off_t *cookies = NULL;
    869      1.90    itojun 	int ncookies = 0, n;
    870      1.90    itojun #ifdef IPSEC
    871      1.90    itojun 	struct secasvar *sav, *sav2;
    872      1.90    itojun 	struct secpolicy *sp;
    873      1.90    itojun #endif
    874      1.23   mycroft 
    875      1.37   mycroft 	if (uio->uio_resid < UIO_MX)
    876      1.37   mycroft 		return (EINVAL);
    877      1.38   mycroft 	if (uio->uio_offset < 0)
    878      1.37   mycroft 		return (EINVAL);
    879      1.26   mycroft 
    880       1.1       cgd 	error = 0;
    881      1.38   mycroft 	i = uio->uio_offset;
    882      1.90    itojun 	memset(&d, 0, sizeof(d));
    883      1.90    itojun 	d.d_reclen = UIO_MX;
    884      1.90    itojun 	ncookies = uio->uio_resid / UIO_MX;
    885      1.90    itojun 
    886      1.90    itojun 	switch (kfs->kfs_type) {
    887      1.98     darcy 	case KFSkern:
    888      1.90    itojun 		if (i >= nkern_targets)
    889      1.90    itojun 			return (0);
    890      1.66  sommerfe 
    891      1.90    itojun 		if (ap->a_ncookies) {
    892      1.90    itojun 			ncookies = min(ncookies, (nkern_targets - i));
    893      1.90    itojun 			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
    894      1.90    itojun 			    M_WAITOK);
    895      1.90    itojun 			*ap->a_cookies = cookies;
    896      1.90    itojun 		}
    897      1.90    itojun 
    898      1.90    itojun 		n = 0;
    899      1.90    itojun 		for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
    900      1.90    itojun 			kt = &kern_targets[i];
    901      1.98     darcy 			if (kt->kt_tag == KFSdevice) {
    902      1.94    itojun 				dev_t *dp = kt->kt_data;
    903      1.94    itojun 				struct vnode *fvp;
    904      1.94    itojun 
    905      1.94    itojun 				if (*dp == NODEV ||
    906      1.94    itojun 				    !vfinddev(*dp, kt->kt_vtype, &fvp))
    907      1.94    itojun 					continue;
    908      1.94    itojun 			}
    909      1.90    itojun 			d.d_namlen = kt->kt_namlen;
    910  1.98.2.1       jdc 			if ((error = kernfs_setdirentfileno(&d, i, kfs,
    911  1.98.2.1       jdc 			    &kern_targets[0], kt, ap)) != 0)
    912  1.98.2.1       jdc 				break;
    913      1.90    itojun 			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
    914      1.90    itojun 			d.d_type = kt->kt_type;
    915      1.90    itojun 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
    916      1.90    itojun 				break;
    917      1.90    itojun 			if (cookies)
    918      1.90    itojun 				*cookies++ = i + 1;
    919      1.90    itojun 			n++;
    920      1.90    itojun 		}
    921      1.90    itojun 		ncookies = n;
    922      1.90    itojun 		break;
    923      1.90    itojun 
    924      1.98     darcy 	case KFSroot:
    925      1.90    itojun 		if (i >= 2)
    926      1.90    itojun 			return 0;
    927      1.90    itojun 
    928      1.90    itojun 		if (ap->a_ncookies) {
    929      1.90    itojun 			ncookies = min(ncookies, (2 - i));
    930      1.90    itojun 			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
    931      1.90    itojun 			    M_WAITOK);
    932      1.90    itojun 			*ap->a_cookies = cookies;
    933      1.90    itojun 		}
    934      1.90    itojun 
    935      1.90    itojun 		n = 0;
    936      1.90    itojun 		for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
    937      1.90    itojun 			kt = &kern_targets[i];
    938      1.90    itojun 			d.d_namlen = kt->kt_namlen;
    939      1.90    itojun 			d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
    940      1.90    itojun 			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
    941      1.90    itojun 			d.d_type = kt->kt_type;
    942      1.90    itojun 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
    943      1.90    itojun 				break;
    944      1.90    itojun 			if (cookies)
    945      1.90    itojun 				*cookies++ = i + 1;
    946      1.90    itojun 			n++;
    947      1.90    itojun 		}
    948      1.90    itojun 		ncookies = n;
    949      1.90    itojun 		break;
    950      1.90    itojun 
    951      1.90    itojun #ifdef IPSEC
    952      1.98     darcy 	case KFSipsecsadir:
    953      1.90    itojun 		/* count SA in the system */
    954      1.90    itojun 		n = 0;
    955      1.90    itojun 		TAILQ_FOREACH(sav, &satailq, tailq) {
    956      1.90    itojun 			for (sav2 = TAILQ_FIRST(&satailq);
    957      1.90    itojun 			    sav2 != sav;
    958      1.90    itojun 			    sav2 = TAILQ_NEXT(sav2, tailq)) {
    959      1.90    itojun 				if (sav->spi == sav2->spi) {
    960      1.90    itojun 					/* multiple SA with same SPI */
    961      1.90    itojun 					break;
    962      1.90    itojun 				}
    963      1.90    itojun 			}
    964      1.90    itojun 			if (sav == sav2 || sav->spi != sav2->spi)
    965      1.90    itojun 				n++;
    966      1.90    itojun 		}
    967      1.37   mycroft 
    968      1.90    itojun 		if (i >= nipsecsa_targets + n)
    969      1.90    itojun 			return (0);
    970      1.57      fvdl 
    971      1.90    itojun 		if (ap->a_ncookies) {
    972      1.90    itojun 			ncookies = min(ncookies, (n - i));
    973      1.90    itojun 			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
    974      1.90    itojun 			    M_WAITOK);
    975      1.90    itojun 			*ap->a_cookies = cookies;
    976      1.90    itojun 		}
    977      1.26   mycroft 
    978      1.90    itojun 		n = 0;
    979      1.90    itojun 		for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
    980      1.90    itojun 			kt = &ipsecsa_targets[i];
    981      1.90    itojun 			d.d_namlen = kt->kt_namlen;
    982  1.98.2.1       jdc 			if ((error = kernfs_setdirentfileno(&d, i, kfs,
    983  1.98.2.1       jdc 			    &kern_targets[0], kt, ap)) != 0)
    984  1.98.2.1       jdc 				break;
    985      1.90    itojun 			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
    986      1.90    itojun 			d.d_type = kt->kt_type;
    987      1.90    itojun 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
    988      1.90    itojun 				break;
    989      1.90    itojun 			if (cookies)
    990      1.90    itojun 				*cookies++ = i + 1;
    991      1.90    itojun 			n++;
    992      1.90    itojun 		}
    993      1.90    itojun 		if (error) {
    994      1.90    itojun 			ncookies = n;
    995      1.90    itojun 			break;
    996      1.90    itojun 		}
    997      1.26   mycroft 
    998      1.90    itojun 		TAILQ_FOREACH(sav, &satailq, tailq) {
    999      1.90    itojun 			for (sav2 = TAILQ_FIRST(&satailq);
   1000      1.90    itojun 			    sav2 != sav;
   1001      1.90    itojun 			    sav2 = TAILQ_NEXT(sav2, tailq)) {
   1002      1.90    itojun 				if (sav->spi == sav2->spi) {
   1003      1.90    itojun 					/* multiple SA with same SPI */
   1004      1.90    itojun 					break;
   1005      1.90    itojun 				}
   1006      1.90    itojun 			}
   1007      1.90    itojun 			if (sav != sav2 && sav->spi == sav2->spi)
   1008      1.23   mycroft 				continue;
   1009      1.90    itojun 			if (uio->uio_resid < UIO_MX)
   1010      1.90    itojun 				break;
   1011  1.98.2.1       jdc 			if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
   1012  1.98.2.1       jdc 			    sav->spi, ap)) != 0)
   1013  1.98.2.1       jdc 				break;
   1014      1.90    itojun 			d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
   1015      1.90    itojun 			    "%u", ntohl(sav->spi));
   1016      1.90    itojun 			d.d_type = DT_REG;
   1017      1.90    itojun 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
   1018      1.90    itojun 				break;
   1019      1.90    itojun 			if (cookies)
   1020      1.90    itojun 				*cookies++ = i + 1;
   1021      1.90    itojun 			n++;
   1022      1.90    itojun 			i++;
   1023      1.23   mycroft 		}
   1024      1.90    itojun 		ncookies = n;
   1025      1.90    itojun 		break;
   1026      1.90    itojun 
   1027      1.98     darcy 	case KFSipsecspdir:
   1028      1.90    itojun 		/* count SP in the system */
   1029      1.90    itojun 		n = 0;
   1030      1.90    itojun 		TAILQ_FOREACH(sp, &sptailq, tailq)
   1031      1.90    itojun 			n++;
   1032      1.26   mycroft 
   1033      1.90    itojun 		if (i >= 2 + n)
   1034      1.90    itojun 			return (0);
   1035      1.90    itojun 
   1036      1.90    itojun 		if (ap->a_ncookies) {
   1037      1.90    itojun 			ncookies = min(ncookies, (n - i));
   1038      1.90    itojun 			cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
   1039      1.90    itojun 			    M_WAITOK);
   1040      1.90    itojun 			*ap->a_cookies = cookies;
   1041      1.90    itojun 		}
   1042      1.26   mycroft 
   1043      1.90    itojun 		n = 0;
   1044      1.90    itojun 		for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
   1045      1.90    itojun 			kt = &ipsecsp_targets[i];
   1046      1.90    itojun 			d.d_namlen = kt->kt_namlen;
   1047  1.98.2.1       jdc 			if ((error = kernfs_setdirentfileno(&d, i, kfs,
   1048  1.98.2.1       jdc 			    &kern_targets[0], kt, ap)) != 0)
   1049  1.98.2.1       jdc 				break;
   1050      1.90    itojun 			memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
   1051      1.90    itojun 			d.d_type = kt->kt_type;
   1052      1.90    itojun 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
   1053      1.90    itojun 				break;
   1054      1.90    itojun 			if (cookies)
   1055      1.90    itojun 				*cookies++ = i + 1;
   1056      1.90    itojun 			n++;
   1057      1.90    itojun 		}
   1058      1.90    itojun 		if (error) {
   1059      1.90    itojun 			ncookies = n;
   1060       1.1       cgd 			break;
   1061      1.57      fvdl 		}
   1062      1.90    itojun 
   1063      1.90    itojun 		TAILQ_FOREACH(sp, &sptailq, tailq) {
   1064      1.90    itojun 			if (uio->uio_resid < UIO_MX)
   1065      1.90    itojun 				break;
   1066  1.98.2.1       jdc 			if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
   1067  1.98.2.1       jdc 			    sp->id, ap)) != 0)
   1068  1.98.2.1       jdc 				break;
   1069      1.90    itojun 			d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
   1070      1.90    itojun 			    "%u", sp->id);
   1071      1.90    itojun 			d.d_type = DT_REG;
   1072      1.90    itojun 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
   1073      1.90    itojun 				break;
   1074      1.90    itojun 			if (cookies)
   1075      1.90    itojun 				*cookies++ = i + 1;
   1076      1.90    itojun 			n++;
   1077      1.90    itojun 			i++;
   1078      1.90    itojun 		}
   1079      1.90    itojun 		ncookies = n;
   1080      1.90    itojun 		break;
   1081      1.90    itojun #endif
   1082      1.90    itojun 
   1083      1.90    itojun 	default:
   1084      1.90    itojun 		error = ENOTDIR;
   1085      1.90    itojun 		break;
   1086      1.57      fvdl 	}
   1087      1.57      fvdl 
   1088      1.57      fvdl 	if (ap->a_ncookies) {
   1089      1.57      fvdl 		if (error) {
   1090      1.90    itojun 			if (cookies)
   1091      1.90    itojun 				free(*ap->a_cookies, M_TEMP);
   1092      1.57      fvdl 			*ap->a_ncookies = 0;
   1093      1.57      fvdl 			*ap->a_cookies = NULL;
   1094      1.57      fvdl 		} else
   1095      1.57      fvdl 			*ap->a_ncookies = ncookies;
   1096       1.1       cgd 	}
   1097       1.1       cgd 
   1098      1.38   mycroft 	uio->uio_offset = i;
   1099       1.1       cgd 	return (error);
   1100       1.1       cgd }
   1101       1.1       cgd 
   1102      1.41  christos int
   1103      1.41  christos kernfs_inactive(v)
   1104      1.41  christos 	void *v;
   1105      1.41  christos {
   1106      1.23   mycroft 	struct vop_inactive_args /* {
   1107      1.23   mycroft 		struct vnode *a_vp;
   1108      1.57      fvdl 		struct proc *a_p;
   1109      1.41  christos 	} */ *ap = v;
   1110      1.23   mycroft 	struct vnode *vp = ap->a_vp;
   1111      1.90    itojun 	const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
   1112      1.90    itojun #ifdef IPSEC
   1113      1.90    itojun 	struct mbuf *m;
   1114      1.90    itojun 	struct secpolicy *sp;
   1115      1.90    itojun #endif
   1116      1.23   mycroft 
   1117      1.90    itojun 	VOP_UNLOCK(vp, 0);
   1118      1.90    itojun 	switch (kfs->kfs_type) {
   1119      1.90    itojun #ifdef IPSEC
   1120      1.98     darcy 	case KFSipsecsa:
   1121      1.90    itojun 		m = key_setdumpsa_spi(htonl(kfs->kfs_value));
   1122      1.90    itojun 		if (m)
   1123      1.90    itojun 			m_freem(m);
   1124      1.91    itojun 		else
   1125      1.90    itojun 			vgone(vp);
   1126      1.90    itojun 		break;
   1127      1.98     darcy 	case KFSipsecsp:
   1128      1.90    itojun 		sp = key_getspbyid(kfs->kfs_value);
   1129      1.90    itojun 		if (sp)
   1130      1.90    itojun 			key_freesp(sp);
   1131      1.90    itojun 		else {
   1132      1.90    itojun 			/* should never happen as we hold a refcnt */
   1133      1.90    itojun 			vgone(vp);
   1134      1.90    itojun 		}
   1135      1.90    itojun 		break;
   1136      1.23   mycroft #endif
   1137      1.90    itojun 	default:
   1138      1.90    itojun 		break;
   1139      1.90    itojun 	}
   1140      1.23   mycroft 	return (0);
   1141      1.23   mycroft }
   1142      1.23   mycroft 
   1143      1.41  christos int
   1144      1.41  christos kernfs_reclaim(v)
   1145      1.41  christos 	void *v;
   1146      1.41  christos {
   1147      1.23   mycroft 	struct vop_reclaim_args /* {
   1148      1.23   mycroft 		struct vnode *a_vp;
   1149      1.41  christos 	} */ *ap = v;
   1150      1.23   mycroft 
   1151      1.90    itojun 	return (kernfs_freevp(ap->a_vp));
   1152       1.1       cgd }
   1153       1.1       cgd 
   1154       1.1       cgd /*
   1155      1.23   mycroft  * Return POSIX pathconf information applicable to special devices.
   1156      1.23   mycroft  */
   1157      1.41  christos int
   1158      1.41  christos kernfs_pathconf(v)
   1159      1.41  christos 	void *v;
   1160      1.41  christos {
   1161      1.23   mycroft 	struct vop_pathconf_args /* {
   1162      1.23   mycroft 		struct vnode *a_vp;
   1163      1.23   mycroft 		int a_name;
   1164      1.29       cgd 		register_t *a_retval;
   1165      1.41  christos 	} */ *ap = v;
   1166      1.23   mycroft 
   1167      1.23   mycroft 	switch (ap->a_name) {
   1168      1.23   mycroft 	case _PC_LINK_MAX:
   1169      1.23   mycroft 		*ap->a_retval = LINK_MAX;
   1170      1.23   mycroft 		return (0);
   1171      1.23   mycroft 	case _PC_MAX_CANON:
   1172      1.23   mycroft 		*ap->a_retval = MAX_CANON;
   1173      1.23   mycroft 		return (0);
   1174      1.23   mycroft 	case _PC_MAX_INPUT:
   1175      1.23   mycroft 		*ap->a_retval = MAX_INPUT;
   1176      1.23   mycroft 		return (0);
   1177      1.23   mycroft 	case _PC_PIPE_BUF:
   1178      1.23   mycroft 		*ap->a_retval = PIPE_BUF;
   1179      1.23   mycroft 		return (0);
   1180      1.23   mycroft 	case _PC_CHOWN_RESTRICTED:
   1181      1.23   mycroft 		*ap->a_retval = 1;
   1182      1.23   mycroft 		return (0);
   1183      1.23   mycroft 	case _PC_VDISABLE:
   1184      1.23   mycroft 		*ap->a_retval = _POSIX_VDISABLE;
   1185      1.59    kleink 		return (0);
   1186      1.59    kleink 	case _PC_SYNC_IO:
   1187      1.59    kleink 		*ap->a_retval = 1;
   1188      1.23   mycroft 		return (0);
   1189      1.23   mycroft 	default:
   1190      1.23   mycroft 		return (EINVAL);
   1191      1.23   mycroft 	}
   1192      1.23   mycroft 	/* NOTREACHED */
   1193      1.23   mycroft }
   1194      1.23   mycroft 
   1195      1.23   mycroft /*
   1196      1.23   mycroft  * Print out the contents of a /dev/fd vnode.
   1197       1.1       cgd  */
   1198       1.1       cgd /* ARGSUSED */
   1199      1.41  christos int
   1200      1.41  christos kernfs_print(v)
   1201      1.41  christos 	void *v;
   1202      1.23   mycroft {
   1203      1.23   mycroft 
   1204      1.47  christos 	printf("tag VT_KERNFS, kernfs vnode\n");
   1205      1.23   mycroft 	return (0);
   1206      1.23   mycroft }
   1207      1.23   mycroft 
   1208      1.40   mycroft int
   1209      1.41  christos kernfs_link(v)
   1210      1.41  christos 	void *v;
   1211      1.41  christos {
   1212      1.40   mycroft 	struct vop_link_args /* {
   1213      1.40   mycroft 		struct vnode *a_dvp;
   1214      1.40   mycroft 		struct vnode *a_vp;
   1215      1.40   mycroft 		struct componentname *a_cnp;
   1216      1.41  christos 	} */ *ap = v;
   1217      1.40   mycroft 
   1218      1.40   mycroft 	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
   1219      1.40   mycroft 	vput(ap->a_dvp);
   1220      1.40   mycroft 	return (EROFS);
   1221      1.40   mycroft }
   1222      1.40   mycroft 
   1223      1.40   mycroft int
   1224      1.41  christos kernfs_symlink(v)
   1225      1.41  christos 	void *v;
   1226      1.41  christos {
   1227      1.40   mycroft 	struct vop_symlink_args /* {
   1228      1.40   mycroft 		struct vnode *a_dvp;
   1229      1.40   mycroft 		struct vnode **a_vpp;
   1230      1.40   mycroft 		struct componentname *a_cnp;
   1231      1.40   mycroft 		struct vattr *a_vap;
   1232      1.40   mycroft 		char *a_target;
   1233      1.41  christos 	} */ *ap = v;
   1234      1.40   mycroft 
   1235      1.40   mycroft 	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
   1236      1.40   mycroft 	vput(ap->a_dvp);
   1237      1.40   mycroft 	return (EROFS);
   1238       1.1       cgd }
   1239