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-proc.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) Proc Implementation.
   24  */
   25 
   26 #include <sys/systeminfo.h>
   27 #include <sys/kstat.h>
   28 #include <sys/kmem.h>
   29 #include <sys/kmem_cache.h>
   30 #include <sys/vmem.h>
   31 #include <sys/taskq.h>
   32 #include <sys/proc.h>
   33 #include <linux/ctype.h>
   34 #include <linux/kmod.h>
   35 #include <linux/seq_file.h>
   36 #include <linux/uaccess.h>
   37 #include <linux/version.h>
   38 #include "zfs_gitrev.h"
   39 
   40 #if defined(CONSTIFY_PLUGIN) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
   41 typedef struct ctl_table __no_const spl_ctl_table;
   42 #else
   43 typedef struct ctl_table spl_ctl_table;
   44 #endif
   45 
   46 static unsigned long table_min = 0;
   47 static unsigned long table_max = ~0;
   48 
   49 static struct ctl_table_header *spl_header = NULL;
   50 static struct proc_dir_entry *proc_spl = NULL;
   51 static struct proc_dir_entry *proc_spl_kmem = NULL;
   52 static struct proc_dir_entry *proc_spl_kmem_slab = NULL;
   53 static struct proc_dir_entry *proc_spl_taskq_all = NULL;
   54 static struct proc_dir_entry *proc_spl_taskq = NULL;
   55 struct proc_dir_entry *proc_spl_kstat = NULL;
   56 
   57 #ifdef DEBUG_KMEM
   58 static int
   59 proc_domemused(struct ctl_table *table, int write,
   60     void __user *buffer, size_t *lenp, loff_t *ppos)
   61 {
   62         int rc = 0;
   63         unsigned long val;
   64         spl_ctl_table dummy = *table;
   65 
   66         dummy.data = &val;
   67         dummy.proc_handler = &proc_dointvec;
   68         dummy.extra1 = &table_min;
   69         dummy.extra2 = &table_max;
   70 
   71         if (write) {
   72                 *ppos += *lenp;
   73         } else {
   74 #ifdef HAVE_ATOMIC64_T
   75                 val = atomic64_read((atomic64_t *)table->data);
   76 #else
   77                 val = atomic_read((atomic_t *)table->data);
   78 #endif /* HAVE_ATOMIC64_T */
   79                 rc = proc_doulongvec_minmax(&dummy, write, buffer, lenp, ppos);
   80         }
   81 
   82         return (rc);
   83 }
   84 #endif /* DEBUG_KMEM */
   85 
   86 static int
   87 proc_doslab(struct ctl_table *table, int write,
   88     void __user *buffer, size_t *lenp, loff_t *ppos)
   89 {
   90         int rc = 0;
   91         unsigned long val = 0, mask;
   92         spl_ctl_table dummy = *table;
   93         spl_kmem_cache_t *skc = NULL;
   94 
   95         dummy.data = &val;
   96         dummy.proc_handler = &proc_dointvec;
   97         dummy.extra1 = &table_min;
   98         dummy.extra2 = &table_max;
   99 
  100         if (write) {
  101                 *ppos += *lenp;
  102         } else {
  103                 down_read(&spl_kmem_cache_sem);
  104                 mask = (unsigned long)table->data;
  105 
  106                 list_for_each_entry(skc, &spl_kmem_cache_list, skc_list) {
  107 
  108                         /* Only use slabs of the correct kmem/vmem type */
  109                         if (!(skc->skc_flags & mask))
  110                                 continue;
  111 
  112                         /* Sum the specified field for selected slabs */
  113                         switch (mask & (KMC_TOTAL | KMC_ALLOC | KMC_MAX)) {
  114                         case KMC_TOTAL:
  115                                 val += skc->skc_slab_size * skc->skc_slab_total;
  116                                 break;
  117                         case KMC_ALLOC:
  118                                 val += skc->skc_obj_size * skc->skc_obj_alloc;
  119                                 break;
  120                         case KMC_MAX:
  121                                 val += skc->skc_obj_size * skc->skc_obj_max;
  122                                 break;
  123                         }
  124                 }
  125 
  126                 up_read(&spl_kmem_cache_sem);
  127                 rc = proc_doulongvec_minmax(&dummy, write, buffer, lenp, ppos);
  128         }
  129 
  130         return (rc);
  131 }
  132 
  133 static int
  134 proc_dohostid(struct ctl_table *table, int write,
  135     void __user *buffer, size_t *lenp, loff_t *ppos)
  136 {
  137         char *end, str[32];
  138         unsigned long hid;
  139         spl_ctl_table dummy = *table;
  140 
  141         dummy.data = str;
  142         dummy.maxlen = sizeof (str) - 1;
  143 
  144         if (!write)
  145                 snprintf(str, sizeof (str), "%lx",
  146                     (unsigned long) zone_get_hostid(NULL));
  147 
  148         /* always returns 0 */
  149         proc_dostring(&dummy, write, buffer, lenp, ppos);
  150 
  151         if (write) {
  152                 /*
  153                  * We can't use proc_doulongvec_minmax() in the write
  154                  * case here because hostid, while a hex value, has no
  155                  * leading 0x, which confuses the helper function.
  156                  */
  157 
  158                 hid = simple_strtoul(str, &end, 16);
  159                 if (str == end)
  160                         return (-EINVAL);
  161                 spl_hostid = hid;
  162         }
  163 
  164         return (0);
  165 }
  166 
  167 static void
  168 taskq_seq_show_headers(struct seq_file *f)
  169 {
  170         seq_printf(f, "%-25s %5s %5s %5s %5s %5s %5s %12s %5s %10s\n",
  171             "taskq", "act", "nthr", "spwn", "maxt", "pri",
  172             "mina", "maxa", "cura", "flags");
  173 }
  174 
  175 /* indices into the lheads array below */
  176 #define LHEAD_PEND      0
  177 #define LHEAD_PRIO      1
  178 #define LHEAD_DELAY     2
  179 #define LHEAD_WAIT      3
  180 #define LHEAD_ACTIVE    4
  181 #define LHEAD_SIZE      5
  182 
  183 static unsigned int spl_max_show_tasks = 512;
  184 /* CSTYLED */
  185 module_param(spl_max_show_tasks, uint, 0644);
  186 MODULE_PARM_DESC(spl_max_show_tasks, "Max number of tasks shown in taskq proc");
  187 
  188 static int
  189 taskq_seq_show_impl(struct seq_file *f, void *p, boolean_t allflag)
  190 {
  191         taskq_t *tq = p;
  192         taskq_thread_t *tqt = NULL;
  193         spl_wait_queue_entry_t *wq;
  194         struct task_struct *tsk;
  195         taskq_ent_t *tqe;
  196         char name[100];
  197         struct list_head *lheads[LHEAD_SIZE], *lh;
  198         static char *list_names[LHEAD_SIZE] =
  199             {"pend", "prio", "delay", "wait", "active" };
  200         int i, j, have_lheads = 0;
  201         unsigned long wflags, flags;
  202 
  203         spin_lock_irqsave_nested(&tq->tq_lock, flags, tq->tq_lock_class);
  204         spin_lock_irqsave(&tq->tq_wait_waitq.lock, wflags);
  205 
  206         /* get the various lists and check whether they're empty */
  207         lheads[LHEAD_PEND] = &tq->tq_pend_list;
  208         lheads[LHEAD_PRIO] = &tq->tq_prio_list;
  209         lheads[LHEAD_DELAY] = &tq->tq_delay_list;
  210 #ifdef HAVE_WAIT_QUEUE_HEAD_ENTRY
  211         lheads[LHEAD_WAIT] = &tq->tq_wait_waitq.head;
  212 #else
  213         lheads[LHEAD_WAIT] = &tq->tq_wait_waitq.task_list;
  214 #endif
  215         lheads[LHEAD_ACTIVE] = &tq->tq_active_list;
  216 
  217         for (i = 0; i < LHEAD_SIZE; ++i) {
  218                 if (list_empty(lheads[i]))
  219                         lheads[i] = NULL;
  220                 else
  221                         ++have_lheads;
  222         }
  223 
  224         /* early return in non-"all" mode if lists are all empty */
  225         if (!allflag && !have_lheads) {
  226                 spin_unlock_irqrestore(&tq->tq_wait_waitq.lock, wflags);
  227                 spin_unlock_irqrestore(&tq->tq_lock, flags);
  228                 return (0);
  229         }
  230 
  231         /* unlock the waitq quickly */
  232         if (!lheads[LHEAD_WAIT])
  233                 spin_unlock_irqrestore(&tq->tq_wait_waitq.lock, wflags);
  234 
  235         /* show the base taskq contents */
  236         snprintf(name, sizeof (name), "%s/%d", tq->tq_name, tq->tq_instance);
  237         seq_printf(f, "%-25s ", name);
  238         seq_printf(f, "%5d %5d %5d %5d %5d %5d %12d %5d %10x\n",
  239             tq->tq_nactive, tq->tq_nthreads, tq->tq_nspawn,
  240             tq->tq_maxthreads, tq->tq_pri, tq->tq_minalloc, tq->tq_maxalloc,
  241             tq->tq_nalloc, tq->tq_flags);
  242 
  243         /* show the active list */
  244         if (lheads[LHEAD_ACTIVE]) {
  245                 j = 0;
  246                 list_for_each_entry(tqt, &tq->tq_active_list, tqt_active_list) {
  247                         if (j == 0)
  248                                 seq_printf(f, "\t%s:",
  249                                     list_names[LHEAD_ACTIVE]);
  250                         else if (j == 2) {
  251                                 seq_printf(f, "\n\t       ");
  252                                 j = 0;
  253                         }
  254                         seq_printf(f, " [%d]%pf(%ps)",
  255                             tqt->tqt_thread->pid,
  256                             tqt->tqt_task->tqent_func,
  257                             tqt->tqt_task->tqent_arg);
  258                         ++j;
  259                 }
  260                 seq_printf(f, "\n");
  261         }
  262 
  263         for (i = LHEAD_PEND; i <= LHEAD_WAIT; ++i)
  264                 if (lheads[i]) {
  265                         j = 0;
  266                         list_for_each(lh, lheads[i]) {
  267                                 if (spl_max_show_tasks != 0 &&
  268                                     j >= spl_max_show_tasks) {
  269                                         seq_printf(f, "\n\t(truncated)");
  270                                         break;
  271                                 }
  272                                 /* show the wait waitq list */
  273                                 if (i == LHEAD_WAIT) {
  274 #ifdef HAVE_WAIT_QUEUE_HEAD_ENTRY
  275                                         wq = list_entry(lh,
  276                                             spl_wait_queue_entry_t, entry);
  277 #else
  278                                         wq = list_entry(lh,
  279                                             spl_wait_queue_entry_t, task_list);
  280 #endif
  281                                         if (j == 0)
  282                                                 seq_printf(f, "\t%s:",
  283                                                     list_names[i]);
  284                                         else if (j % 8 == 0)
  285                                                 seq_printf(f, "\n\t     ");
  286 
  287                                         tsk = wq->private;
  288                                         seq_printf(f, " %d", tsk->pid);
  289                                 /* pend, prio and delay lists */
  290                                 } else {
  291                                         tqe = list_entry(lh, taskq_ent_t,
  292                                             tqent_list);
  293                                         if (j == 0)
  294                                                 seq_printf(f, "\t%s:",
  295                                                     list_names[i]);
  296                                         else if (j % 2 == 0)
  297                                                 seq_printf(f, "\n\t     ");
  298 
  299                                         seq_printf(f, " %pf(%ps)",
  300                                             tqe->tqent_func,
  301                                             tqe->tqent_arg);
  302                                 }
  303                                 ++j;
  304                         }
  305                         seq_printf(f, "\n");
  306                 }
  307         if (lheads[LHEAD_WAIT])
  308                 spin_unlock_irqrestore(&tq->tq_wait_waitq.lock, wflags);
  309         spin_unlock_irqrestore(&tq->tq_lock, flags);
  310 
  311         return (0);
  312 }
  313 
  314 static int
  315 taskq_all_seq_show(struct seq_file *f, void *p)
  316 {
  317         return (taskq_seq_show_impl(f, p, B_TRUE));
  318 }
  319 
  320 static int
  321 taskq_seq_show(struct seq_file *f, void *p)
  322 {
  323         return (taskq_seq_show_impl(f, p, B_FALSE));
  324 }
  325 
  326 static void *
  327 taskq_seq_start(struct seq_file *f, loff_t *pos)
  328 {
  329         struct list_head *p;
  330         loff_t n = *pos;
  331 
  332         down_read(&tq_list_sem);
  333         if (!n)
  334                 taskq_seq_show_headers(f);
  335 
  336         p = tq_list.next;
  337         while (n--) {
  338                 p = p->next;
  339                 if (p == &tq_list)
  340                 return (NULL);
  341         }
  342 
  343         return (list_entry(p, taskq_t, tq_taskqs));
  344 }
  345 
  346 static void *
  347 taskq_seq_next(struct seq_file *f, void *p, loff_t *pos)
  348 {
  349         taskq_t *tq = p;
  350 
  351         ++*pos;
  352         return ((tq->tq_taskqs.next == &tq_list) ?
  353             NULL : list_entry(tq->tq_taskqs.next, taskq_t, tq_taskqs));
  354 }
  355 
  356 static void
  357 slab_seq_show_headers(struct seq_file *f)
  358 {
  359         seq_printf(f,
  360             "--------------------- cache ----------"
  361             "---------------------------------------------  "
  362             "----- slab ------  "
  363             "---- object -----  "
  364             "--- emergency ---\n");
  365         seq_printf(f,
  366             "name                                  "
  367             "  flags      size     alloc slabsize  objsize  "
  368             "total alloc   max  "
  369             "total alloc   max  "
  370             "dlock alloc   max\n");
  371 }
  372 
  373 static int
  374 slab_seq_show(struct seq_file *f, void *p)
  375 {
  376         spl_kmem_cache_t *skc = p;
  377 
  378         ASSERT(skc->skc_magic == SKC_MAGIC);
  379 
  380         if (skc->skc_flags & KMC_SLAB) {
  381                 /*
  382                  * This cache is backed by a generic Linux kmem cache which
  383                  * has its own accounting. For these caches we only track
  384                  * the number of active allocated objects that exist within
  385                  * the underlying Linux slabs. For the overall statistics of
  386                  * the underlying Linux cache please refer to /proc/slabinfo.
  387                  */
  388                 spin_lock(&skc->skc_lock);
  389                 uint64_t objs_allocated =
  390                     percpu_counter_sum(&skc->skc_linux_alloc);
  391                 seq_printf(f, "%-36s  ", skc->skc_name);
  392                 seq_printf(f, "0x%05lx %9s %9lu %8s %8u  "
  393                     "%5s %5s %5s  %5s %5lu %5s  %5s %5s %5s\n",
  394                     (long unsigned)skc->skc_flags,
  395                     "-",
  396                     (long unsigned)(skc->skc_obj_size * objs_allocated),
  397                     "-",
  398                     (unsigned)skc->skc_obj_size,
  399                     "-", "-", "-", "-",
  400                     (long unsigned)objs_allocated,
  401                     "-", "-", "-", "-");
  402                 spin_unlock(&skc->skc_lock);
  403                 return (0);
  404         }
  405 
  406         spin_lock(&skc->skc_lock);
  407         seq_printf(f, "%-36s  ", skc->skc_name);
  408         seq_printf(f, "0x%05lx %9lu %9lu %8u %8u  "
  409             "%5lu %5lu %5lu  %5lu %5lu %5lu  %5lu %5lu %5lu\n",
  410             (long unsigned)skc->skc_flags,
  411             (long unsigned)(skc->skc_slab_size * skc->skc_slab_total),
  412             (long unsigned)(skc->skc_obj_size * skc->skc_obj_alloc),
  413             (unsigned)skc->skc_slab_size,
  414             (unsigned)skc->skc_obj_size,
  415             (long unsigned)skc->skc_slab_total,
  416             (long unsigned)skc->skc_slab_alloc,
  417             (long unsigned)skc->skc_slab_max,
  418             (long unsigned)skc->skc_obj_total,
  419             (long unsigned)skc->skc_obj_alloc,
  420             (long unsigned)skc->skc_obj_max,
  421             (long unsigned)skc->skc_obj_deadlock,
  422             (long unsigned)skc->skc_obj_emergency,
  423             (long unsigned)skc->skc_obj_emergency_max);
  424         spin_unlock(&skc->skc_lock);
  425         return (0);
  426 }
  427 
  428 static void *
  429 slab_seq_start(struct seq_file *f, loff_t *pos)
  430 {
  431         struct list_head *p;
  432         loff_t n = *pos;
  433 
  434         down_read(&spl_kmem_cache_sem);
  435         if (!n)
  436                 slab_seq_show_headers(f);
  437 
  438         p = spl_kmem_cache_list.next;
  439         while (n--) {
  440                 p = p->next;
  441                 if (p == &spl_kmem_cache_list)
  442                         return (NULL);
  443         }
  444 
  445         return (list_entry(p, spl_kmem_cache_t, skc_list));
  446 }
  447 
  448 static void *
  449 slab_seq_next(struct seq_file *f, void *p, loff_t *pos)
  450 {
  451         spl_kmem_cache_t *skc = p;
  452 
  453         ++*pos;
  454         return ((skc->skc_list.next == &spl_kmem_cache_list) ?
  455             NULL : list_entry(skc->skc_list.next, spl_kmem_cache_t, skc_list));
  456 }
  457 
  458 static void
  459 slab_seq_stop(struct seq_file *f, void *v)
  460 {
  461         up_read(&spl_kmem_cache_sem);
  462 }
  463 
  464 static const struct seq_operations slab_seq_ops = {
  465         .show  = slab_seq_show,
  466         .start = slab_seq_start,
  467         .next  = slab_seq_next,
  468         .stop  = slab_seq_stop,
  469 };
  470 
  471 static int
  472 proc_slab_open(struct inode *inode, struct file *filp)
  473 {
  474         return (seq_open(filp, &slab_seq_ops));
  475 }
  476 
  477 static const kstat_proc_op_t proc_slab_operations = {
  478 #ifdef HAVE_PROC_OPS_STRUCT
  479         .proc_open      = proc_slab_open,
  480         .proc_read      = seq_read,
  481         .proc_lseek     = seq_lseek,
  482         .proc_release   = seq_release,
  483 #else
  484         .open           = proc_slab_open,
  485         .read           = seq_read,
  486         .llseek         = seq_lseek,
  487         .release        = seq_release,
  488 #endif
  489 };
  490 
  491 static void
  492 taskq_seq_stop(struct seq_file *f, void *v)
  493 {
  494         up_read(&tq_list_sem);
  495 }
  496 
  497 static const struct seq_operations taskq_all_seq_ops = {
  498         .show   = taskq_all_seq_show,
  499         .start  = taskq_seq_start,
  500         .next   = taskq_seq_next,
  501         .stop   = taskq_seq_stop,
  502 };
  503 
  504 static const struct seq_operations taskq_seq_ops = {
  505         .show   = taskq_seq_show,
  506         .start  = taskq_seq_start,
  507         .next   = taskq_seq_next,
  508         .stop   = taskq_seq_stop,
  509 };
  510 
  511 static int
  512 proc_taskq_all_open(struct inode *inode, struct file *filp)
  513 {
  514         return (seq_open(filp, &taskq_all_seq_ops));
  515 }
  516 
  517 static int
  518 proc_taskq_open(struct inode *inode, struct file *filp)
  519 {
  520         return (seq_open(filp, &taskq_seq_ops));
  521 }
  522 
  523 static const kstat_proc_op_t proc_taskq_all_operations = {
  524 #ifdef HAVE_PROC_OPS_STRUCT
  525         .proc_open      = proc_taskq_all_open,
  526         .proc_read      = seq_read,
  527         .proc_lseek     = seq_lseek,
  528         .proc_release   = seq_release,
  529 #else
  530         .open           = proc_taskq_all_open,
  531         .read           = seq_read,
  532         .llseek         = seq_lseek,
  533         .release        = seq_release,
  534 #endif
  535 };
  536 
  537 static const kstat_proc_op_t proc_taskq_operations = {
  538 #ifdef HAVE_PROC_OPS_STRUCT
  539         .proc_open      = proc_taskq_open,
  540         .proc_read      = seq_read,
  541         .proc_lseek     = seq_lseek,
  542         .proc_release   = seq_release,
  543 #else
  544         .open           = proc_taskq_open,
  545         .read           = seq_read,
  546         .llseek         = seq_lseek,
  547         .release        = seq_release,
  548 #endif
  549 };
  550 
  551 static struct ctl_table spl_kmem_table[] = {
  552 #ifdef DEBUG_KMEM
  553         {
  554                 .procname       = "kmem_used",
  555                 .data           = &kmem_alloc_used,
  556 #ifdef HAVE_ATOMIC64_T
  557                 .maxlen         = sizeof (atomic64_t),
  558 #else
  559                 .maxlen         = sizeof (atomic_t),
  560 #endif /* HAVE_ATOMIC64_T */
  561                 .mode           = 0444,
  562                 .proc_handler   = &proc_domemused,
  563         },
  564         {
  565                 .procname       = "kmem_max",
  566                 .data           = &kmem_alloc_max,
  567                 .maxlen         = sizeof (unsigned long),
  568                 .extra1         = &table_min,
  569                 .extra2         = &table_max,
  570                 .mode           = 0444,
  571                 .proc_handler   = &proc_doulongvec_minmax,
  572         },
  573 #endif /* DEBUG_KMEM */
  574         {
  575                 .procname       = "slab_kvmem_total",
  576                 .data           = (void *)(KMC_KVMEM | KMC_TOTAL),
  577                 .maxlen         = sizeof (unsigned long),
  578                 .extra1         = &table_min,
  579                 .extra2         = &table_max,
  580                 .mode           = 0444,
  581                 .proc_handler   = &proc_doslab,
  582         },
  583         {
  584                 .procname       = "slab_kvmem_alloc",
  585                 .data           = (void *)(KMC_KVMEM | KMC_ALLOC),
  586                 .maxlen         = sizeof (unsigned long),
  587                 .extra1         = &table_min,
  588                 .extra2         = &table_max,
  589                 .mode           = 0444,
  590                 .proc_handler   = &proc_doslab,
  591         },
  592         {
  593                 .procname       = "slab_kvmem_max",
  594                 .data           = (void *)(KMC_KVMEM | KMC_MAX),
  595                 .maxlen         = sizeof (unsigned long),
  596                 .extra1         = &table_min,
  597                 .extra2         = &table_max,
  598                 .mode           = 0444,
  599                 .proc_handler   = &proc_doslab,
  600         },
  601         {},
  602 };
  603 
  604 static struct ctl_table spl_kstat_table[] = {
  605         {},
  606 };
  607 
  608 static struct ctl_table spl_table[] = {
  609         /*
  610          * NB No .strategy entries have been provided since
  611          * sysctl(8) prefers to go via /proc for portability.
  612          */
  613         {
  614                 .procname       = "gitrev",
  615                 .data           = (char *)ZFS_META_GITREV,
  616                 .maxlen         = sizeof (ZFS_META_GITREV),
  617                 .mode           = 0444,
  618                 .proc_handler   = &proc_dostring,
  619         },
  620         {
  621                 .procname       = "hostid",
  622                 .data           = &spl_hostid,
  623                 .maxlen         = sizeof (unsigned long),
  624                 .mode           = 0644,
  625                 .proc_handler   = &proc_dohostid,
  626         },
  627         {
  628                 .procname       = "kmem",
  629                 .mode           = 0555,
  630                 .child          = spl_kmem_table,
  631         },
  632         {
  633                 .procname       = "kstat",
  634                 .mode           = 0555,
  635                 .child          = spl_kstat_table,
  636         },
  637         {},
  638 };
  639 
  640 static struct ctl_table spl_dir[] = {
  641         {
  642                 .procname       = "spl",
  643                 .mode           = 0555,
  644                 .child          = spl_table,
  645         },
  646         {}
  647 };
  648 
  649 static struct ctl_table spl_root[] = {
  650         {
  651         .procname = "kernel",
  652         .mode = 0555,
  653         .child = spl_dir,
  654         },
  655         {}
  656 };
  657 
  658 int
  659 spl_proc_init(void)
  660 {
  661         int rc = 0;
  662 
  663         spl_header = register_sysctl_table(spl_root);
  664         if (spl_header == NULL)
  665                 return (-EUNATCH);
  666 
  667         proc_spl = proc_mkdir("spl", NULL);
  668         if (proc_spl == NULL) {
  669                 rc = -EUNATCH;
  670                 goto out;
  671         }
  672 
  673         proc_spl_taskq_all = proc_create_data("taskq-all", 0444, proc_spl,
  674             &proc_taskq_all_operations, NULL);
  675         if (proc_spl_taskq_all == NULL) {
  676                 rc = -EUNATCH;
  677                 goto out;
  678         }
  679 
  680         proc_spl_taskq = proc_create_data("taskq", 0444, proc_spl,
  681             &proc_taskq_operations, NULL);
  682         if (proc_spl_taskq == NULL) {
  683                 rc = -EUNATCH;
  684                 goto out;
  685         }
  686 
  687         proc_spl_kmem = proc_mkdir("kmem", proc_spl);
  688         if (proc_spl_kmem == NULL) {
  689                 rc = -EUNATCH;
  690                 goto out;
  691         }
  692 
  693         proc_spl_kmem_slab = proc_create_data("slab", 0444, proc_spl_kmem,
  694             &proc_slab_operations, NULL);
  695         if (proc_spl_kmem_slab == NULL) {
  696                 rc = -EUNATCH;
  697                 goto out;
  698         }
  699 
  700         proc_spl_kstat = proc_mkdir("kstat", proc_spl);
  701         if (proc_spl_kstat == NULL) {
  702                 rc = -EUNATCH;
  703                 goto out;
  704         }
  705 out:
  706         if (rc) {
  707                 remove_proc_entry("kstat", proc_spl);
  708                 remove_proc_entry("slab", proc_spl_kmem);
  709                 remove_proc_entry("kmem", proc_spl);
  710                 remove_proc_entry("taskq-all", proc_spl);
  711                 remove_proc_entry("taskq", proc_spl);
  712                 remove_proc_entry("spl", NULL);
  713                 unregister_sysctl_table(spl_header);
  714         }
  715 
  716         return (rc);
  717 }
  718 
  719 void
  720 spl_proc_fini(void)
  721 {
  722         remove_proc_entry("kstat", proc_spl);
  723         remove_proc_entry("slab", proc_spl_kmem);
  724         remove_proc_entry("kmem", proc_spl);
  725         remove_proc_entry("taskq-all", proc_spl);
  726         remove_proc_entry("taskq", proc_spl);
  727         remove_proc_entry("spl", NULL);
  728 
  729         ASSERT(spl_header != NULL);
  730         unregister_sysctl_table(spl_header);
  731 }

Cache object: 4b46c1d408080d780c127c52ef03787d


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