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/linux/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-2010 Lawrence Livermore National Security, LLC.
    3  *  Copyright (C) 2007 The Regents of the University of California.
    4  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
    5  *  Written by Brian Behlendorf <behlendorf1@llnl.gov>.
    6  *  UCRL-CODE-235197
    7  *
    8  *  This file is part of the SPL, Solaris Porting Layer.
    9  *
   10  *  The SPL is free software; you can redistribute it and/or modify it
   11  *  under the terms of the GNU General Public License as published by the
   12  *  Free Software Foundation; either version 2 of the License, or (at your
   13  *  option) any later version.
   14  *
   15  *  The SPL is distributed in the hope that it will be useful, but WITHOUT
   16  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   18  *  for more details.
   19  *
   20  *  You should have received a copy of the GNU General Public License along
   21  *  with the SPL.  If not, see <http://www.gnu.org/licenses/>.
   22  *
   23  *  Solaris Porting Layer (SPL) Kstat Implementation.
   24  *
   25  *  Links to Illumos.org for more information on kstat function:
   26  *  [1] https://illumos.org/man/1M/kstat
   27  *  [2] https://illumos.org/man/9f/kstat_create
   28  */
   29 
   30 #include <linux/seq_file.h>
   31 #include <sys/kstat.h>
   32 #include <sys/vmem.h>
   33 #include <sys/cmn_err.h>
   34 #include <sys/sysmacros.h>
   35 
   36 static kmutex_t kstat_module_lock;
   37 static struct list_head kstat_module_list;
   38 static kid_t kstat_id;
   39 
   40 static int
   41 kstat_resize_raw(kstat_t *ksp)
   42 {
   43         if (ksp->ks_raw_bufsize == KSTAT_RAW_MAX)
   44                 return (ENOMEM);
   45 
   46         vmem_free(ksp->ks_raw_buf, ksp->ks_raw_bufsize);
   47         ksp->ks_raw_bufsize = MIN(ksp->ks_raw_bufsize * 2, KSTAT_RAW_MAX);
   48         ksp->ks_raw_buf = vmem_alloc(ksp->ks_raw_bufsize, KM_SLEEP);
   49 
   50         return (0);
   51 }
   52 
   53 static int
   54 kstat_seq_show_headers(struct seq_file *f)
   55 {
   56         kstat_t *ksp = (kstat_t *)f->private;
   57         int rc = 0;
   58 
   59         ASSERT(ksp->ks_magic == KS_MAGIC);
   60 
   61         seq_printf(f, "%d %d 0x%02x %d %d %lld %lld\n",
   62             ksp->ks_kid, ksp->ks_type, ksp->ks_flags,
   63             ksp->ks_ndata, (int)ksp->ks_data_size,
   64             ksp->ks_crtime, ksp->ks_snaptime);
   65 
   66         switch (ksp->ks_type) {
   67                 case KSTAT_TYPE_RAW:
   68 restart:
   69                         if (ksp->ks_raw_ops.headers) {
   70                                 rc = ksp->ks_raw_ops.headers(
   71                                     ksp->ks_raw_buf, ksp->ks_raw_bufsize);
   72                                 if (rc == ENOMEM && !kstat_resize_raw(ksp))
   73                                         goto restart;
   74                                 if (!rc)
   75                                         seq_puts(f, ksp->ks_raw_buf);
   76                         } else {
   77                                 seq_printf(f, "raw data\n");
   78                         }
   79                         break;
   80                 case KSTAT_TYPE_NAMED:
   81                         seq_printf(f, "%-31s %-4s %s\n",
   82                             "name", "type", "data");
   83                         break;
   84                 case KSTAT_TYPE_INTR:
   85                         seq_printf(f, "%-8s %-8s %-8s %-8s %-8s\n",
   86                             "hard", "soft", "watchdog",
   87                             "spurious", "multsvc");
   88                         break;
   89                 case KSTAT_TYPE_IO:
   90                         seq_printf(f,
   91                             "%-8s %-8s %-8s %-8s %-8s %-8s "
   92                             "%-8s %-8s %-8s %-8s %-8s %-8s\n",
   93                             "nread", "nwritten", "reads", "writes",
   94                             "wtime", "wlentime", "wupdate",
   95                             "rtime", "rlentime", "rupdate",
   96                             "wcnt", "rcnt");
   97                         break;
   98                 case KSTAT_TYPE_TIMER:
   99                         seq_printf(f,
  100                             "%-31s %-8s "
  101                             "%-8s %-8s %-8s %-8s %-8s\n",
  102                             "name", "events", "elapsed",
  103                             "min", "max", "start", "stop");
  104                         break;
  105                 default:
  106                         PANIC("Undefined kstat type %d\n", ksp->ks_type);
  107         }
  108 
  109         return (-rc);
  110 }
  111 
  112 static int
  113 kstat_seq_show_raw(struct seq_file *f, unsigned char *p, int l)
  114 {
  115         int i, j;
  116 
  117         for (i = 0; ; i++) {
  118                 seq_printf(f, "%03x:", i);
  119 
  120                 for (j = 0; j < 16; j++) {
  121                         if (i * 16 + j >= l) {
  122                                 seq_printf(f, "\n");
  123                                 goto out;
  124                         }
  125 
  126                         seq_printf(f, " %02x", (unsigned char)p[i * 16 + j]);
  127                 }
  128                 seq_printf(f, "\n");
  129         }
  130 out:
  131         return (0);
  132 }
  133 
  134 static int
  135 kstat_seq_show_named(struct seq_file *f, kstat_named_t *knp)
  136 {
  137         seq_printf(f, "%-31s %-4d ", knp->name, knp->data_type);
  138 
  139         switch (knp->data_type) {
  140                 case KSTAT_DATA_CHAR:
  141                         knp->value.c[15] = '\0'; /* NULL terminate */
  142                         seq_printf(f, "%-16s", knp->value.c);
  143                         break;
  144                 /*
  145                  * NOTE - We need to be more careful able what tokens are
  146                  * used for each arch, for now this is correct for x86_64.
  147                  */
  148                 case KSTAT_DATA_INT32:
  149                         seq_printf(f, "%d", knp->value.i32);
  150                         break;
  151                 case KSTAT_DATA_UINT32:
  152                         seq_printf(f, "%u", knp->value.ui32);
  153                         break;
  154                 case KSTAT_DATA_INT64:
  155                         seq_printf(f, "%lld", (signed long long)knp->value.i64);
  156                         break;
  157                 case KSTAT_DATA_UINT64:
  158                         seq_printf(f, "%llu",
  159                             (unsigned long long)knp->value.ui64);
  160                         break;
  161                 case KSTAT_DATA_LONG:
  162                         seq_printf(f, "%ld", knp->value.l);
  163                         break;
  164                 case KSTAT_DATA_ULONG:
  165                         seq_printf(f, "%lu", knp->value.ul);
  166                         break;
  167                 case KSTAT_DATA_STRING:
  168                         KSTAT_NAMED_STR_PTR(knp)
  169                                 [KSTAT_NAMED_STR_BUFLEN(knp)-1] = '\0';
  170                         seq_printf(f, "%s", KSTAT_NAMED_STR_PTR(knp));
  171                         break;
  172                 default:
  173                         PANIC("Undefined kstat data type %d\n", knp->data_type);
  174         }
  175 
  176         seq_printf(f, "\n");
  177 
  178         return (0);
  179 }
  180 
  181 static int
  182 kstat_seq_show_intr(struct seq_file *f, kstat_intr_t *kip)
  183 {
  184         seq_printf(f, "%-8u %-8u %-8u %-8u %-8u\n",
  185             kip->intrs[KSTAT_INTR_HARD],
  186             kip->intrs[KSTAT_INTR_SOFT],
  187             kip->intrs[KSTAT_INTR_WATCHDOG],
  188             kip->intrs[KSTAT_INTR_SPURIOUS],
  189             kip->intrs[KSTAT_INTR_MULTSVC]);
  190 
  191         return (0);
  192 }
  193 
  194 static int
  195 kstat_seq_show_io(struct seq_file *f, kstat_io_t *kip)
  196 {
  197         /* though wlentime & friends are signed, they will never be negative */
  198         seq_printf(f,
  199             "%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
  200             "%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
  201             kip->nread, kip->nwritten,
  202             kip->reads, kip->writes,
  203             kip->wtime, kip->wlentime, kip->wlastupdate,
  204             kip->rtime, kip->rlentime, kip->rlastupdate,
  205             kip->wcnt,  kip->rcnt);
  206 
  207         return (0);
  208 }
  209 
  210 static int
  211 kstat_seq_show_timer(struct seq_file *f, kstat_timer_t *ktp)
  212 {
  213         seq_printf(f,
  214             "%-31s %-8llu %-8llu %-8llu %-8llu %-8llu %-8llu\n",
  215             ktp->name, ktp->num_events, ktp->elapsed_time,
  216             ktp->min_time, ktp->max_time,
  217             ktp->start_time, ktp->stop_time);
  218 
  219         return (0);
  220 }
  221 
  222 static int
  223 kstat_seq_show(struct seq_file *f, void *p)
  224 {
  225         kstat_t *ksp = (kstat_t *)f->private;
  226         int rc = 0;
  227 
  228         ASSERT(ksp->ks_magic == KS_MAGIC);
  229 
  230         switch (ksp->ks_type) {
  231                 case KSTAT_TYPE_RAW:
  232 restart:
  233                         if (ksp->ks_raw_ops.data) {
  234                                 rc = ksp->ks_raw_ops.data(
  235                                     ksp->ks_raw_buf, ksp->ks_raw_bufsize, p);
  236                                 if (rc == ENOMEM && !kstat_resize_raw(ksp))
  237                                         goto restart;
  238                                 if (!rc)
  239                                         seq_puts(f, ksp->ks_raw_buf);
  240                         } else {
  241                                 ASSERT(ksp->ks_ndata == 1);
  242                                 rc = kstat_seq_show_raw(f, ksp->ks_data,
  243                                     ksp->ks_data_size);
  244                         }
  245                         break;
  246                 case KSTAT_TYPE_NAMED:
  247                         rc = kstat_seq_show_named(f, (kstat_named_t *)p);
  248                         break;
  249                 case KSTAT_TYPE_INTR:
  250                         rc = kstat_seq_show_intr(f, (kstat_intr_t *)p);
  251                         break;
  252                 case KSTAT_TYPE_IO:
  253                         rc = kstat_seq_show_io(f, (kstat_io_t *)p);
  254                         break;
  255                 case KSTAT_TYPE_TIMER:
  256                         rc = kstat_seq_show_timer(f, (kstat_timer_t *)p);
  257                         break;
  258                 default:
  259                         PANIC("Undefined kstat type %d\n", ksp->ks_type);
  260         }
  261 
  262         return (-rc);
  263 }
  264 
  265 static int
  266 kstat_default_update(kstat_t *ksp, int rw)
  267 {
  268         ASSERT(ksp != NULL);
  269 
  270         if (rw == KSTAT_WRITE)
  271                 return (EACCES);
  272 
  273         return (0);
  274 }
  275 
  276 static void *
  277 kstat_seq_data_addr(kstat_t *ksp, loff_t n)
  278 {
  279         void *rc = NULL;
  280 
  281         switch (ksp->ks_type) {
  282                 case KSTAT_TYPE_RAW:
  283                         if (ksp->ks_raw_ops.addr)
  284                                 rc = ksp->ks_raw_ops.addr(ksp, n);
  285                         else
  286                                 rc = ksp->ks_data;
  287                         break;
  288                 case KSTAT_TYPE_NAMED:
  289                         rc = ksp->ks_data + n * sizeof (kstat_named_t);
  290                         break;
  291                 case KSTAT_TYPE_INTR:
  292                         rc = ksp->ks_data + n * sizeof (kstat_intr_t);
  293                         break;
  294                 case KSTAT_TYPE_IO:
  295                         rc = ksp->ks_data + n * sizeof (kstat_io_t);
  296                         break;
  297                 case KSTAT_TYPE_TIMER:
  298                         rc = ksp->ks_data + n * sizeof (kstat_timer_t);
  299                         break;
  300                 default:
  301                         PANIC("Undefined kstat type %d\n", ksp->ks_type);
  302         }
  303 
  304         return (rc);
  305 }
  306 
  307 static void *
  308 kstat_seq_start(struct seq_file *f, loff_t *pos)
  309 {
  310         loff_t n = *pos;
  311         kstat_t *ksp = (kstat_t *)f->private;
  312         ASSERT(ksp->ks_magic == KS_MAGIC);
  313 
  314         mutex_enter(ksp->ks_lock);
  315 
  316         if (ksp->ks_type == KSTAT_TYPE_RAW) {
  317                 ksp->ks_raw_bufsize = PAGE_SIZE;
  318                 ksp->ks_raw_buf = vmem_alloc(ksp->ks_raw_bufsize, KM_SLEEP);
  319         }
  320 
  321         /* Dynamically update kstat, on error existing kstats are used */
  322         (void) ksp->ks_update(ksp, KSTAT_READ);
  323 
  324         ksp->ks_snaptime = gethrtime();
  325 
  326         if (!(ksp->ks_flags & KSTAT_FLAG_NO_HEADERS) && !n &&
  327             kstat_seq_show_headers(f))
  328                 return (NULL);
  329 
  330         if (n >= ksp->ks_ndata)
  331                 return (NULL);
  332 
  333         return (kstat_seq_data_addr(ksp, n));
  334 }
  335 
  336 static void *
  337 kstat_seq_next(struct seq_file *f, void *p, loff_t *pos)
  338 {
  339         kstat_t *ksp = (kstat_t *)f->private;
  340         ASSERT(ksp->ks_magic == KS_MAGIC);
  341 
  342         ++*pos;
  343         if (*pos >= ksp->ks_ndata)
  344                 return (NULL);
  345 
  346         return (kstat_seq_data_addr(ksp, *pos));
  347 }
  348 
  349 static void
  350 kstat_seq_stop(struct seq_file *f, void *v)
  351 {
  352         kstat_t *ksp = (kstat_t *)f->private;
  353         ASSERT(ksp->ks_magic == KS_MAGIC);
  354 
  355         if (ksp->ks_type == KSTAT_TYPE_RAW)
  356                 vmem_free(ksp->ks_raw_buf, ksp->ks_raw_bufsize);
  357 
  358         mutex_exit(ksp->ks_lock);
  359 }
  360 
  361 static const struct seq_operations kstat_seq_ops = {
  362         .show  = kstat_seq_show,
  363         .start = kstat_seq_start,
  364         .next  = kstat_seq_next,
  365         .stop  = kstat_seq_stop,
  366 };
  367 
  368 static kstat_module_t *
  369 kstat_find_module(char *name)
  370 {
  371         kstat_module_t *module = NULL;
  372 
  373         list_for_each_entry(module, &kstat_module_list, ksm_module_list) {
  374                 if (strncmp(name, module->ksm_name, KSTAT_STRLEN) == 0)
  375                         return (module);
  376         }
  377 
  378         return (NULL);
  379 }
  380 
  381 static kstat_module_t *
  382 kstat_create_module(char *name)
  383 {
  384         kstat_module_t *module;
  385         struct proc_dir_entry *pde;
  386 
  387         pde = proc_mkdir(name, proc_spl_kstat);
  388         if (pde == NULL)
  389                 return (NULL);
  390 
  391         module = kmem_alloc(sizeof (kstat_module_t), KM_SLEEP);
  392         module->ksm_proc = pde;
  393         strlcpy(module->ksm_name, name, KSTAT_STRLEN);
  394         INIT_LIST_HEAD(&module->ksm_kstat_list);
  395         list_add_tail(&module->ksm_module_list, &kstat_module_list);
  396 
  397         return (module);
  398 
  399 }
  400 
  401 static void
  402 kstat_delete_module(kstat_module_t *module)
  403 {
  404         ASSERT(list_empty(&module->ksm_kstat_list));
  405         remove_proc_entry(module->ksm_name, proc_spl_kstat);
  406         list_del(&module->ksm_module_list);
  407         kmem_free(module, sizeof (kstat_module_t));
  408 }
  409 
  410 static int
  411 proc_kstat_open(struct inode *inode, struct file *filp)
  412 {
  413         struct seq_file *f;
  414         int rc;
  415 
  416         rc = seq_open(filp, &kstat_seq_ops);
  417         if (rc)
  418                 return (rc);
  419 
  420         f = filp->private_data;
  421         f->private = SPL_PDE_DATA(inode);
  422 
  423         return (0);
  424 }
  425 
  426 static ssize_t
  427 proc_kstat_write(struct file *filp, const char __user *buf, size_t len,
  428     loff_t *ppos)
  429 {
  430         struct seq_file *f = filp->private_data;
  431         kstat_t *ksp = f->private;
  432         int rc;
  433 
  434         ASSERT(ksp->ks_magic == KS_MAGIC);
  435 
  436         mutex_enter(ksp->ks_lock);
  437         rc = ksp->ks_update(ksp, KSTAT_WRITE);
  438         mutex_exit(ksp->ks_lock);
  439 
  440         if (rc)
  441                 return (-rc);
  442 
  443         *ppos += len;
  444         return (len);
  445 }
  446 
  447 static const kstat_proc_op_t proc_kstat_operations = {
  448 #ifdef HAVE_PROC_OPS_STRUCT
  449         .proc_open      = proc_kstat_open,
  450         .proc_write     = proc_kstat_write,
  451         .proc_read      = seq_read,
  452         .proc_lseek     = seq_lseek,
  453         .proc_release   = seq_release,
  454 #else
  455         .open           = proc_kstat_open,
  456         .write          = proc_kstat_write,
  457         .read           = seq_read,
  458         .llseek         = seq_lseek,
  459         .release        = seq_release,
  460 #endif
  461 };
  462 
  463 void
  464 __kstat_set_raw_ops(kstat_t *ksp,
  465     int (*headers)(char *buf, size_t size),
  466     int (*data)(char *buf, size_t size, void *data),
  467     void *(*addr)(kstat_t *ksp, loff_t index))
  468 {
  469         ksp->ks_raw_ops.headers = headers;
  470         ksp->ks_raw_ops.data    = data;
  471         ksp->ks_raw_ops.addr    = addr;
  472 }
  473 EXPORT_SYMBOL(__kstat_set_raw_ops);
  474 
  475 void
  476 kstat_proc_entry_init(kstat_proc_entry_t *kpep, const char *module,
  477     const char *name)
  478 {
  479         kpep->kpe_owner = NULL;
  480         kpep->kpe_proc = NULL;
  481         INIT_LIST_HEAD(&kpep->kpe_list);
  482         strlcpy(kpep->kpe_module, module, sizeof (kpep->kpe_module));
  483         strlcpy(kpep->kpe_name, name, sizeof (kpep->kpe_name));
  484 }
  485 EXPORT_SYMBOL(kstat_proc_entry_init);
  486 
  487 kstat_t *
  488 __kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
  489     const char *ks_class, uchar_t ks_type, uint_t ks_ndata,
  490     uchar_t ks_flags)
  491 {
  492         kstat_t *ksp;
  493 
  494         ASSERT(ks_module);
  495         ASSERT(ks_instance == 0);
  496         ASSERT(ks_name);
  497 
  498         if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
  499                 ASSERT(ks_ndata == 1);
  500 
  501         ksp = kmem_zalloc(sizeof (*ksp), KM_SLEEP);
  502         if (ksp == NULL)
  503                 return (ksp);
  504 
  505         mutex_enter(&kstat_module_lock);
  506         ksp->ks_kid = kstat_id;
  507         kstat_id++;
  508         mutex_exit(&kstat_module_lock);
  509 
  510         ksp->ks_magic = KS_MAGIC;
  511         mutex_init(&ksp->ks_private_lock, NULL, MUTEX_DEFAULT, NULL);
  512         ksp->ks_lock = &ksp->ks_private_lock;
  513 
  514         ksp->ks_crtime = gethrtime();
  515         ksp->ks_snaptime = ksp->ks_crtime;
  516         ksp->ks_instance = ks_instance;
  517         strlcpy(ksp->ks_class, ks_class, sizeof (ksp->ks_class));
  518         ksp->ks_type = ks_type;
  519         ksp->ks_flags = ks_flags;
  520         ksp->ks_update = kstat_default_update;
  521         ksp->ks_private = NULL;
  522         ksp->ks_raw_ops.headers = NULL;
  523         ksp->ks_raw_ops.data = NULL;
  524         ksp->ks_raw_ops.addr = NULL;
  525         ksp->ks_raw_buf = NULL;
  526         ksp->ks_raw_bufsize = 0;
  527         kstat_proc_entry_init(&ksp->ks_proc, ks_module, ks_name);
  528 
  529         switch (ksp->ks_type) {
  530                 case KSTAT_TYPE_RAW:
  531                         ksp->ks_ndata = 1;
  532                         ksp->ks_data_size = ks_ndata;
  533                         break;
  534                 case KSTAT_TYPE_NAMED:
  535                         ksp->ks_ndata = ks_ndata;
  536                         ksp->ks_data_size = ks_ndata * sizeof (kstat_named_t);
  537                         break;
  538                 case KSTAT_TYPE_INTR:
  539                         ksp->ks_ndata = ks_ndata;
  540                         ksp->ks_data_size = ks_ndata * sizeof (kstat_intr_t);
  541                         break;
  542                 case KSTAT_TYPE_IO:
  543                         ksp->ks_ndata = ks_ndata;
  544                         ksp->ks_data_size = ks_ndata * sizeof (kstat_io_t);
  545                         break;
  546                 case KSTAT_TYPE_TIMER:
  547                         ksp->ks_ndata = ks_ndata;
  548                         ksp->ks_data_size = ks_ndata * sizeof (kstat_timer_t);
  549                         break;
  550                 default:
  551                         PANIC("Undefined kstat type %d\n", ksp->ks_type);
  552         }
  553 
  554         if (ksp->ks_flags & KSTAT_FLAG_VIRTUAL) {
  555                 ksp->ks_data = NULL;
  556         } else {
  557                 ksp->ks_data = kmem_zalloc(ksp->ks_data_size, KM_SLEEP);
  558                 if (ksp->ks_data == NULL) {
  559                         kmem_free(ksp, sizeof (*ksp));
  560                         ksp = NULL;
  561                 }
  562         }
  563 
  564         return (ksp);
  565 }
  566 EXPORT_SYMBOL(__kstat_create);
  567 
  568 static int
  569 kstat_detect_collision(kstat_proc_entry_t *kpep)
  570 {
  571         kstat_module_t *module;
  572         kstat_proc_entry_t *tmp = NULL;
  573         char *parent;
  574         char *cp;
  575 
  576         parent = kmem_asprintf("%s", kpep->kpe_module);
  577 
  578         if ((cp = strrchr(parent, '/')) == NULL) {
  579                 kmem_strfree(parent);
  580                 return (0);
  581         }
  582 
  583         cp[0] = '\0';
  584         if ((module = kstat_find_module(parent)) != NULL) {
  585                 list_for_each_entry(tmp, &module->ksm_kstat_list, kpe_list) {
  586                         if (strncmp(tmp->kpe_name, cp+1, KSTAT_STRLEN) == 0) {
  587                                 kmem_strfree(parent);
  588                                 return (EEXIST);
  589                         }
  590                 }
  591         }
  592 
  593         kmem_strfree(parent);
  594         return (0);
  595 }
  596 
  597 /*
  598  * Add a file to the proc filesystem under the kstat namespace (i.e.
  599  * /proc/spl/kstat/). The file need not necessarily be implemented as a
  600  * kstat.
  601  */
  602 void
  603 kstat_proc_entry_install(kstat_proc_entry_t *kpep, mode_t mode,
  604     const kstat_proc_op_t *proc_ops, void *data)
  605 {
  606         kstat_module_t *module;
  607         kstat_proc_entry_t *tmp = NULL;
  608 
  609         ASSERT(kpep);
  610 
  611         mutex_enter(&kstat_module_lock);
  612 
  613         module = kstat_find_module(kpep->kpe_module);
  614         if (module == NULL) {
  615                 if (kstat_detect_collision(kpep) != 0) {
  616                         cmn_err(CE_WARN, "kstat_create('%s', '%s'): namespace" \
  617                             " collision", kpep->kpe_module, kpep->kpe_name);
  618                         goto out;
  619                 }
  620                 module = kstat_create_module(kpep->kpe_module);
  621                 if (module == NULL)
  622                         goto out;
  623         }
  624 
  625         /*
  626          * Only one entry by this name per-module, on failure the module
  627          * shouldn't be deleted because we know it has at least one entry.
  628          */
  629         list_for_each_entry(tmp, &module->ksm_kstat_list, kpe_list) {
  630                 if (strncmp(tmp->kpe_name, kpep->kpe_name, KSTAT_STRLEN) == 0)
  631                         goto out;
  632         }
  633 
  634         list_add_tail(&kpep->kpe_list, &module->ksm_kstat_list);
  635 
  636         kpep->kpe_owner = module;
  637         kpep->kpe_proc = proc_create_data(kpep->kpe_name, mode,
  638             module->ksm_proc, proc_ops, data);
  639         if (kpep->kpe_proc == NULL) {
  640                 list_del_init(&kpep->kpe_list);
  641                 if (list_empty(&module->ksm_kstat_list))
  642                         kstat_delete_module(module);
  643         }
  644 out:
  645         mutex_exit(&kstat_module_lock);
  646 
  647 }
  648 EXPORT_SYMBOL(kstat_proc_entry_install);
  649 
  650 void
  651 __kstat_install(kstat_t *ksp)
  652 {
  653         ASSERT(ksp);
  654         mode_t mode;
  655         /* Specify permission modes for different kstats */
  656         if (strncmp(ksp->ks_proc.kpe_name, "dbufs", KSTAT_STRLEN) == 0) {
  657                 mode = 0600;
  658         } else {
  659                 mode = 0644;
  660         }
  661         kstat_proc_entry_install(
  662             &ksp->ks_proc, mode, &proc_kstat_operations, ksp);
  663 }
  664 EXPORT_SYMBOL(__kstat_install);
  665 
  666 void
  667 kstat_proc_entry_delete(kstat_proc_entry_t *kpep)
  668 {
  669         kstat_module_t *module = kpep->kpe_owner;
  670         if (kpep->kpe_proc)
  671                 remove_proc_entry(kpep->kpe_name, module->ksm_proc);
  672 
  673         mutex_enter(&kstat_module_lock);
  674         list_del_init(&kpep->kpe_list);
  675 
  676         /*
  677          * Remove top level module directory if it wasn't empty before, but now
  678          * is.
  679          */
  680         if (kpep->kpe_proc && list_empty(&module->ksm_kstat_list))
  681                 kstat_delete_module(module);
  682         mutex_exit(&kstat_module_lock);
  683 
  684 }
  685 EXPORT_SYMBOL(kstat_proc_entry_delete);
  686 
  687 void
  688 __kstat_delete(kstat_t *ksp)
  689 {
  690         kstat_proc_entry_delete(&ksp->ks_proc);
  691 
  692         if (!(ksp->ks_flags & KSTAT_FLAG_VIRTUAL))
  693                 kmem_free(ksp->ks_data, ksp->ks_data_size);
  694 
  695         ksp->ks_lock = NULL;
  696         mutex_destroy(&ksp->ks_private_lock);
  697         kmem_free(ksp, sizeof (*ksp));
  698 }
  699 EXPORT_SYMBOL(__kstat_delete);
  700 
  701 int
  702 spl_kstat_init(void)
  703 {
  704         mutex_init(&kstat_module_lock, NULL, MUTEX_DEFAULT, NULL);
  705         INIT_LIST_HEAD(&kstat_module_list);
  706         kstat_id = 0;
  707         return (0);
  708 }
  709 
  710 void
  711 spl_kstat_fini(void)
  712 {
  713         ASSERT(list_empty(&kstat_module_list));
  714         mutex_destroy(&kstat_module_lock);
  715 }

Cache object: 3fca0615d8c24f441e184181d8ebf21c


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