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/contrib/openzfs/module/os/freebsd/spl/spl_kstat.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 /*
    2  * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * Links to Illumos.org for more information on kstat function:
   27  * [1] https://illumos.org/man/1M/kstat
   28  * [2] https://illumos.org/man/9f/kstat_create
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/types.h>
   35 #include <sys/param.h>
   36 #include <sys/kernel.h>
   37 #include <sys/systm.h>
   38 #include <sys/malloc.h>
   39 #include <sys/sysctl.h>
   40 #include <sys/kstat.h>
   41 #include <sys/sbuf.h>
   42 #include <sys/zone.h>
   43 
   44 static MALLOC_DEFINE(M_KSTAT, "kstat_data", "Kernel statistics");
   45 
   46 SYSCTL_ROOT_NODE(OID_AUTO, kstat, CTLFLAG_RW, 0, "Kernel statistics");
   47 
   48 void
   49 __kstat_set_raw_ops(kstat_t *ksp,
   50     int (*headers)(char *buf, size_t size),
   51     int (*data)(char *buf, size_t size, void *data),
   52     void *(*addr)(kstat_t *ksp, loff_t index))
   53 {
   54         ksp->ks_raw_ops.headers = headers;
   55         ksp->ks_raw_ops.data    = data;
   56         ksp->ks_raw_ops.addr    = addr;
   57 }
   58 
   59 void
   60 __kstat_set_seq_raw_ops(kstat_t *ksp,
   61     int (*headers)(struct seq_file *f),
   62     int (*data)(char *buf, size_t size, void *data),
   63     void *(*addr)(kstat_t *ksp, loff_t index))
   64 {
   65         ksp->ks_raw_ops.seq_headers = headers;
   66         ksp->ks_raw_ops.data    = data;
   67         ksp->ks_raw_ops.addr    = addr;
   68 }
   69 
   70 static int
   71 kstat_default_update(kstat_t *ksp, int rw)
   72 {
   73         ASSERT3P(ksp, !=, NULL);
   74 
   75         if (rw == KSTAT_WRITE)
   76                 return (EACCES);
   77 
   78         return (0);
   79 }
   80 
   81 static int
   82 kstat_resize_raw(kstat_t *ksp)
   83 {
   84         if (ksp->ks_raw_bufsize == KSTAT_RAW_MAX)
   85                 return (ENOMEM);
   86 
   87         free(ksp->ks_raw_buf, M_TEMP);
   88         ksp->ks_raw_bufsize = MIN(ksp->ks_raw_bufsize * 2, KSTAT_RAW_MAX);
   89         ksp->ks_raw_buf = malloc(ksp->ks_raw_bufsize, M_TEMP, M_WAITOK);
   90 
   91         return (0);
   92 }
   93 
   94 static void *
   95 kstat_raw_default_addr(kstat_t *ksp, loff_t n)
   96 {
   97         if (n == 0)
   98                 return (ksp->ks_data);
   99         return (NULL);
  100 }
  101 
  102 static int
  103 kstat_sysctl(SYSCTL_HANDLER_ARGS)
  104 {
  105         kstat_t *ksp = arg1;
  106         kstat_named_t *ksent;
  107         uint64_t val;
  108 
  109         ksent = ksp->ks_data;
  110         /* Select the correct element */
  111         ksent += arg2;
  112         /* Update the aggsums before reading */
  113         (void) ksp->ks_update(ksp, KSTAT_READ);
  114         val = ksent->value.ui64;
  115 
  116         return (sysctl_handle_64(oidp, &val, 0, req));
  117 }
  118 
  119 static int
  120 kstat_sysctl_string(SYSCTL_HANDLER_ARGS)
  121 {
  122         kstat_t *ksp = arg1;
  123         kstat_named_t *ksent = ksp->ks_data;
  124         char *val;
  125         uint32_t len = 0;
  126 
  127         /* Select the correct element */
  128         ksent += arg2;
  129         /* Update the aggsums before reading */
  130         (void) ksp->ks_update(ksp, KSTAT_READ);
  131         val = KSTAT_NAMED_STR_PTR(ksent);
  132         len = KSTAT_NAMED_STR_BUFLEN(ksent);
  133         val[len-1] = '\0';
  134 
  135         return (sysctl_handle_string(oidp, val, len, req));
  136 }
  137 
  138 static int
  139 kstat_sysctl_dataset(SYSCTL_HANDLER_ARGS)
  140 {
  141         kstat_t *ksp = arg1;
  142         kstat_named_t *ksent;
  143         kstat_named_t *ksent_ds;
  144         uint64_t val;
  145         char *ds_name;
  146         uint32_t ds_len = 0;
  147 
  148         ksent_ds = ksent = ksp->ks_data;
  149         ds_name = KSTAT_NAMED_STR_PTR(ksent_ds);
  150         ds_len = KSTAT_NAMED_STR_BUFLEN(ksent_ds);
  151         ds_name[ds_len-1] = '\0';
  152 
  153         if (!zone_dataset_visible(ds_name, NULL)) {
  154                 return (EPERM);
  155         }
  156 
  157         /* Select the correct element */
  158         ksent += arg2;
  159         /* Update the aggsums before reading */
  160         (void) ksp->ks_update(ksp, KSTAT_READ);
  161         val = ksent->value.ui64;
  162 
  163         return (sysctl_handle_64(oidp, &val, 0, req));
  164 }
  165 
  166 static int
  167 kstat_sysctl_dataset_string(SYSCTL_HANDLER_ARGS)
  168 {
  169         kstat_t *ksp = arg1;
  170         kstat_named_t *ksent = ksp->ks_data;
  171         char *val;
  172         uint32_t len = 0;
  173 
  174         /* Select the correct element */
  175         ksent += arg2;
  176         val = KSTAT_NAMED_STR_PTR(ksent);
  177         len = KSTAT_NAMED_STR_BUFLEN(ksent);
  178         val[len-1] = '\0';
  179 
  180         if (!zone_dataset_visible(val, NULL)) {
  181                 return (EPERM);
  182         }
  183 
  184         return (sysctl_handle_string(oidp, val, len, req));
  185 }
  186 
  187 static int
  188 kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
  189 {
  190         struct sbuf *sb;
  191         kstat_t *ksp = arg1;
  192         kstat_io_t *kip = ksp->ks_data;
  193         int rc;
  194 
  195         sb = sbuf_new_auto();
  196         if (sb == NULL)
  197                 return (ENOMEM);
  198         /* Update the aggsums before reading */
  199         (void) ksp->ks_update(ksp, KSTAT_READ);
  200 
  201         /* though wlentime & friends are signed, they will never be negative */
  202         sbuf_printf(sb,
  203             "%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
  204             "%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
  205             kip->nread, kip->nwritten,
  206             kip->reads, kip->writes,
  207             kip->wtime, kip->wlentime, kip->wlastupdate,
  208             kip->rtime, kip->rlentime, kip->rlastupdate,
  209             kip->wcnt,  kip->rcnt);
  210         rc = sbuf_finish(sb);
  211         if (rc == 0)
  212                 rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
  213         sbuf_delete(sb);
  214         return (rc);
  215 }
  216 
  217 static int
  218 kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
  219 {
  220         struct sbuf *sb;
  221         void *data;
  222         kstat_t *ksp = arg1;
  223         void *(*addr_op)(kstat_t *ksp, loff_t index);
  224         int n, has_header, rc = 0;
  225 
  226         sb = sbuf_new_auto();
  227         if (sb == NULL)
  228                 return (ENOMEM);
  229 
  230         if (ksp->ks_raw_ops.addr)
  231                 addr_op = ksp->ks_raw_ops.addr;
  232         else
  233                 addr_op = kstat_raw_default_addr;
  234 
  235         mutex_enter(ksp->ks_lock);
  236 
  237         /* Update the aggsums before reading */
  238         (void) ksp->ks_update(ksp, KSTAT_READ);
  239 
  240         ksp->ks_raw_bufsize = PAGE_SIZE;
  241         ksp->ks_raw_buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
  242 
  243         n = 0;
  244         has_header = (ksp->ks_raw_ops.headers ||
  245             ksp->ks_raw_ops.seq_headers);
  246 
  247 restart_headers:
  248         if (ksp->ks_raw_ops.headers) {
  249                 rc = ksp->ks_raw_ops.headers(
  250                     ksp->ks_raw_buf, ksp->ks_raw_bufsize);
  251         } else if (ksp->ks_raw_ops.seq_headers) {
  252                 struct seq_file f;
  253 
  254                 f.sf_buf = ksp->ks_raw_buf;
  255                 f.sf_size = ksp->ks_raw_bufsize;
  256                 rc = ksp->ks_raw_ops.seq_headers(&f);
  257         }
  258         if (has_header) {
  259                 if (rc == ENOMEM && !kstat_resize_raw(ksp))
  260                         goto restart_headers;
  261                 if (rc == 0)
  262                         sbuf_printf(sb, "\n%s", ksp->ks_raw_buf);
  263         }
  264 
  265         while ((data = addr_op(ksp, n)) != NULL) {
  266 restart:
  267                 if (ksp->ks_raw_ops.data) {
  268                         rc = ksp->ks_raw_ops.data(ksp->ks_raw_buf,
  269                             ksp->ks_raw_bufsize, data);
  270                         if (rc == ENOMEM && !kstat_resize_raw(ksp))
  271                                 goto restart;
  272                         if (rc == 0)
  273                                 sbuf_printf(sb, "%s", ksp->ks_raw_buf);
  274 
  275                 } else {
  276                         ASSERT3U(ksp->ks_ndata, ==, 1);
  277                         sbuf_hexdump(sb, ksp->ks_data,
  278                             ksp->ks_data_size, NULL, 0);
  279                 }
  280                 n++;
  281         }
  282         free(ksp->ks_raw_buf, M_TEMP);
  283         mutex_exit(ksp->ks_lock);
  284         sbuf_trim(sb);
  285         rc = sbuf_finish(sb);
  286         if (rc == 0)
  287                 rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
  288         sbuf_delete(sb);
  289         return (rc);
  290 }
  291 
  292 kstat_t *
  293 __kstat_create(const char *module, int instance, const char *name,
  294     const char *class, uchar_t ks_type, uint_t ks_ndata, uchar_t flags)
  295 {
  296         char buf[KSTAT_STRLEN];
  297         struct sysctl_oid *root;
  298         kstat_t *ksp;
  299         char *pool;
  300 
  301         KASSERT(instance == 0, ("instance=%d", instance));
  302         if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
  303                 ASSERT3U(ks_ndata, ==, 1);
  304 
  305         if (class == NULL)
  306                 class = "misc";
  307 
  308         /*
  309          * Allocate the main structure. We don't need to keep a copy of
  310          * module in here, because it is only used for sysctl node creation
  311          * done in this function.
  312          */
  313         ksp = malloc(sizeof (*ksp), M_KSTAT, M_WAITOK|M_ZERO);
  314 
  315         ksp->ks_crtime = gethrtime();
  316         ksp->ks_snaptime = ksp->ks_crtime;
  317         ksp->ks_instance = instance;
  318         (void) strlcpy(ksp->ks_name, name, KSTAT_STRLEN);
  319         (void) strlcpy(ksp->ks_class, class, KSTAT_STRLEN);
  320         ksp->ks_type = ks_type;
  321         ksp->ks_flags = flags;
  322         ksp->ks_update = kstat_default_update;
  323 
  324         mutex_init(&ksp->ks_private_lock, NULL, MUTEX_DEFAULT, NULL);
  325         ksp->ks_lock = &ksp->ks_private_lock;
  326 
  327         switch (ksp->ks_type) {
  328         case KSTAT_TYPE_RAW:
  329                 ksp->ks_ndata = 1;
  330                 ksp->ks_data_size = ks_ndata;
  331                 break;
  332         case KSTAT_TYPE_NAMED:
  333                 ksp->ks_ndata = ks_ndata;
  334                 ksp->ks_data_size = ks_ndata * sizeof (kstat_named_t);
  335                 break;
  336         case KSTAT_TYPE_INTR:
  337                 ksp->ks_ndata = ks_ndata;
  338                 ksp->ks_data_size = ks_ndata * sizeof (kstat_intr_t);
  339                 break;
  340         case KSTAT_TYPE_IO:
  341                 ksp->ks_ndata = ks_ndata;
  342                 ksp->ks_data_size = ks_ndata * sizeof (kstat_io_t);
  343                 break;
  344         case KSTAT_TYPE_TIMER:
  345                 ksp->ks_ndata = ks_ndata;
  346                 ksp->ks_data_size = ks_ndata * sizeof (kstat_timer_t);
  347                 break;
  348         default:
  349                 panic("Undefined kstat type %d\n", ksp->ks_type);
  350         }
  351 
  352         if (ksp->ks_flags & KSTAT_FLAG_VIRTUAL)
  353                 ksp->ks_data = NULL;
  354         else
  355                 ksp->ks_data = kmem_zalloc(ksp->ks_data_size, KM_SLEEP);
  356 
  357         /*
  358          * Some kstats use a module name like "zfs/poolname" to distinguish a
  359          * set of kstats belonging to a specific pool.  Split on '/' to add an
  360          * extra node for the pool name if needed.
  361          */
  362         (void) strlcpy(buf, module, KSTAT_STRLEN);
  363         module = buf;
  364         pool = strchr(module, '/');
  365         if (pool != NULL)
  366                 *pool++ = '\0';
  367 
  368         /*
  369          * Create sysctl tree for those statistics:
  370          *
  371          *      kstat.<module>[.<pool>].<class>.<name>
  372          */
  373         sysctl_ctx_init(&ksp->ks_sysctl_ctx);
  374         root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
  375             SYSCTL_STATIC_CHILDREN(_kstat), OID_AUTO, module, CTLFLAG_RW, 0,
  376             "");
  377         if (root == NULL) {
  378                 printf("%s: Cannot create kstat.%s tree!\n", __func__, module);
  379                 sysctl_ctx_free(&ksp->ks_sysctl_ctx);
  380                 free(ksp, M_KSTAT);
  381                 return (NULL);
  382         }
  383         if (pool != NULL) {
  384                 root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
  385                     SYSCTL_CHILDREN(root), OID_AUTO, pool, CTLFLAG_RW, 0, "");
  386                 if (root == NULL) {
  387                         printf("%s: Cannot create kstat.%s.%s tree!\n",
  388                             __func__, module, pool);
  389                         sysctl_ctx_free(&ksp->ks_sysctl_ctx);
  390                         free(ksp, M_KSTAT);
  391                         return (NULL);
  392                 }
  393         }
  394         root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root),
  395             OID_AUTO, class, CTLFLAG_RW, 0, "");
  396         if (root == NULL) {
  397                 if (pool != NULL)
  398                         printf("%s: Cannot create kstat.%s.%s.%s tree!\n",
  399                             __func__, module, pool, class);
  400                 else
  401                         printf("%s: Cannot create kstat.%s.%s tree!\n",
  402                             __func__, module, class);
  403                 sysctl_ctx_free(&ksp->ks_sysctl_ctx);
  404                 free(ksp, M_KSTAT);
  405                 return (NULL);
  406         }
  407         if (ksp->ks_type == KSTAT_TYPE_NAMED) {
  408                 root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
  409                     SYSCTL_CHILDREN(root),
  410                     OID_AUTO, name, CTLFLAG_RW, 0, "");
  411                 if (root == NULL) {
  412                         if (pool != NULL)
  413                                 printf("%s: Cannot create kstat.%s.%s.%s.%s "
  414                                     "tree!\n", __func__, module, pool, class,
  415                                     name);
  416                         else
  417                                 printf("%s: Cannot create kstat.%s.%s.%s "
  418                                     "tree!\n", __func__, module, class, name);
  419                         sysctl_ctx_free(&ksp->ks_sysctl_ctx);
  420                         free(ksp, M_KSTAT);
  421                         return (NULL);
  422                 }
  423 
  424         }
  425         ksp->ks_sysctl_root = root;
  426 
  427         return (ksp);
  428 }
  429 
  430 static void
  431 kstat_install_named(kstat_t *ksp)
  432 {
  433         kstat_named_t *ksent;
  434         char *namelast;
  435         int typelast;
  436 
  437         ksent = ksp->ks_data;
  438 
  439         VERIFY((ksp->ks_flags & KSTAT_FLAG_VIRTUAL) || ksent != NULL);
  440 
  441         typelast = 0;
  442         namelast = NULL;
  443 
  444         for (int i = 0; i < ksp->ks_ndata; i++, ksent++) {
  445                 if (ksent->data_type != 0) {
  446                         typelast = ksent->data_type;
  447                         namelast = ksent->name;
  448                 }
  449                 switch (typelast) {
  450                 case KSTAT_DATA_CHAR:
  451                         /* Not Implemented */
  452                         break;
  453                 case KSTAT_DATA_INT32:
  454                         SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  455                             SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  456                             OID_AUTO, namelast,
  457                             CTLTYPE_S32 | CTLFLAG_RD | CTLFLAG_MPSAFE,
  458                             ksp, i, kstat_sysctl, "I", namelast);
  459                         break;
  460                 case KSTAT_DATA_UINT32:
  461                         SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  462                             SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  463                             OID_AUTO, namelast,
  464                             CTLTYPE_U32 | CTLFLAG_RD | CTLFLAG_MPSAFE,
  465                             ksp, i, kstat_sysctl, "IU", namelast);
  466                         break;
  467                 case KSTAT_DATA_INT64:
  468                         SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  469                             SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  470                             OID_AUTO, namelast,
  471                             CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
  472                             ksp, i, kstat_sysctl, "Q", namelast);
  473                         break;
  474                 case KSTAT_DATA_UINT64:
  475                         if (strcmp(ksp->ks_class, "dataset") == 0) {
  476                                 SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  477                                     SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  478                                     OID_AUTO, namelast,
  479                                     CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
  480                                     ksp, i, kstat_sysctl_dataset, "QU",
  481                                     namelast);
  482                         } else {
  483                                 SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  484                                     SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  485                                     OID_AUTO, namelast,
  486                                     CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
  487                                     ksp, i, kstat_sysctl, "QU", namelast);
  488                         }
  489                         break;
  490                 case KSTAT_DATA_LONG:
  491                         SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  492                             SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  493                             OID_AUTO, namelast,
  494                             CTLTYPE_LONG | CTLFLAG_RD | CTLFLAG_MPSAFE,
  495                             ksp, i, kstat_sysctl, "L", namelast);
  496                         break;
  497                 case KSTAT_DATA_ULONG:
  498                         SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  499                             SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  500                             OID_AUTO, namelast,
  501                             CTLTYPE_ULONG | CTLFLAG_RD | CTLFLAG_MPSAFE,
  502                             ksp, i, kstat_sysctl, "LU", namelast);
  503                         break;
  504                 case KSTAT_DATA_STRING:
  505                         if (strcmp(ksp->ks_class, "dataset") == 0) {
  506                                 SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  507                                     SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  508                                     OID_AUTO, namelast, CTLTYPE_STRING |
  509                                     CTLFLAG_RD | CTLFLAG_MPSAFE,
  510                                     ksp, i, kstat_sysctl_dataset_string, "A",
  511                                     namelast);
  512                         } else {
  513                                 SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  514                                     SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  515                                     OID_AUTO, namelast, CTLTYPE_STRING |
  516                                     CTLFLAG_RD | CTLFLAG_MPSAFE,
  517                                     ksp, i, kstat_sysctl_string, "A",
  518                                     namelast);
  519                         }
  520                         break;
  521                 default:
  522                         panic("unsupported type: %d", typelast);
  523                 }
  524         }
  525 }
  526 
  527 void
  528 kstat_install(kstat_t *ksp)
  529 {
  530         struct sysctl_oid *root;
  531 
  532         if (ksp->ks_ndata == UINT32_MAX)
  533                 VERIFY3U(ksp->ks_type, ==, KSTAT_TYPE_RAW);
  534 
  535         switch (ksp->ks_type) {
  536         case KSTAT_TYPE_NAMED:
  537                 return (kstat_install_named(ksp));
  538         case KSTAT_TYPE_RAW:
  539                 if (ksp->ks_raw_ops.data) {
  540                         root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  541                             SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  542                             OID_AUTO, ksp->ks_name, CTLTYPE_STRING | CTLFLAG_RD
  543                             | CTLFLAG_MPSAFE | CTLFLAG_SKIP,
  544                             ksp, 0, kstat_sysctl_raw, "A", ksp->ks_name);
  545                 } else {
  546                         root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  547                             SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  548                             OID_AUTO, ksp->ks_name, CTLTYPE_OPAQUE | CTLFLAG_RD
  549                             | CTLFLAG_MPSAFE | CTLFLAG_SKIP,
  550                             ksp, 0, kstat_sysctl_raw, "", ksp->ks_name);
  551                 }
  552                 break;
  553         case KSTAT_TYPE_IO:
  554                 root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
  555                     SYSCTL_CHILDREN(ksp->ks_sysctl_root),
  556                     OID_AUTO, ksp->ks_name,
  557                     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
  558                     ksp, 0, kstat_sysctl_io, "A", ksp->ks_name);
  559                 break;
  560         case KSTAT_TYPE_TIMER:
  561         case KSTAT_TYPE_INTR:
  562         default:
  563                 panic("unsupported kstat type %d\n", ksp->ks_type);
  564         }
  565         VERIFY3P(root, !=, NULL);
  566         ksp->ks_sysctl_root = root;
  567 }
  568 
  569 void
  570 kstat_delete(kstat_t *ksp)
  571 {
  572 
  573         sysctl_ctx_free(&ksp->ks_sysctl_ctx);
  574         ksp->ks_lock = NULL;
  575         mutex_destroy(&ksp->ks_private_lock);
  576         if (!(ksp->ks_flags & KSTAT_FLAG_VIRTUAL))
  577                 kmem_free(ksp->ks_data, ksp->ks_data_size);
  578         free(ksp, M_KSTAT);
  579 }

Cache object: 5694e872fd4ed4b76099a28838c8c0ee


[ 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.