The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/miscfs/kernfs/kernfs_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 9597d636c205feb69958e4e61c305ff4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.