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/zfs/zfs_debug.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  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 /*
   22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   23  * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
   24  */
   25 
   26 #include <sys/zfs_context.h>
   27 #include <sys/kstat.h>
   28 
   29 typedef struct zfs_dbgmsg {
   30         list_node_t zdm_node;
   31         time_t zdm_timestamp;
   32         uint_t zdm_size;
   33         char zdm_msg[];
   34 } zfs_dbgmsg_t;
   35 
   36 static list_t zfs_dbgmsgs;
   37 static uint_t zfs_dbgmsg_size = 0;
   38 static kmutex_t zfs_dbgmsgs_lock;
   39 uint_t zfs_dbgmsg_maxsize = 4<<20; /* 4MB */
   40 static kstat_t *zfs_dbgmsg_kstat;
   41 
   42 /*
   43  * Internal ZFS debug messages are enabled by default.
   44  *
   45  * # Print debug messages as they're logged
   46  * dtrace -n 'zfs-dbgmsg { print(stringof(arg0)); }'
   47  *
   48  * # Print all logged dbgmsg entries
   49  * sysctl kstat.zfs.misc.dbgmsg
   50  *
   51  * # Disable the kernel debug message log.
   52  * sysctl vfs.zfs.dbgmsg_enable=0
   53  */
   54 int zfs_dbgmsg_enable = B_TRUE;
   55 
   56 static int
   57 zfs_dbgmsg_headers(char *buf, size_t size)
   58 {
   59         (void) snprintf(buf, size, "%-12s %-8s\n", "timestamp", "message");
   60 
   61         return (0);
   62 }
   63 
   64 static int
   65 zfs_dbgmsg_data(char *buf, size_t size, void *data)
   66 {
   67         zfs_dbgmsg_t *zdm = (zfs_dbgmsg_t *)data;
   68 
   69         (void) snprintf(buf, size, "%-12llu %-s\n",
   70             (u_longlong_t)zdm->zdm_timestamp, zdm->zdm_msg);
   71 
   72         return (0);
   73 }
   74 
   75 static void *
   76 zfs_dbgmsg_addr(kstat_t *ksp, loff_t n)
   77 {
   78         zfs_dbgmsg_t *zdm = (zfs_dbgmsg_t *)ksp->ks_private;
   79 
   80         ASSERT(MUTEX_HELD(&zfs_dbgmsgs_lock));
   81 
   82         if (n == 0)
   83                 ksp->ks_private = list_head(&zfs_dbgmsgs);
   84         else if (zdm)
   85                 ksp->ks_private = list_next(&zfs_dbgmsgs, zdm);
   86 
   87         return (ksp->ks_private);
   88 }
   89 
   90 static void
   91 zfs_dbgmsg_purge(uint_t max_size)
   92 {
   93         zfs_dbgmsg_t *zdm;
   94         uint_t size;
   95 
   96         ASSERT(MUTEX_HELD(&zfs_dbgmsgs_lock));
   97 
   98         while (zfs_dbgmsg_size > max_size) {
   99                 zdm = list_remove_head(&zfs_dbgmsgs);
  100                 if (zdm == NULL)
  101                         return;
  102 
  103                 size = zdm->zdm_size;
  104                 kmem_free(zdm, size);
  105                 zfs_dbgmsg_size -= size;
  106         }
  107 }
  108 
  109 static int
  110 zfs_dbgmsg_update(kstat_t *ksp, int rw)
  111 {
  112         if (rw == KSTAT_WRITE)
  113                 zfs_dbgmsg_purge(0);
  114 
  115         return (0);
  116 }
  117 
  118 void
  119 zfs_dbgmsg_init(void)
  120 {
  121         list_create(&zfs_dbgmsgs, sizeof (zfs_dbgmsg_t),
  122             offsetof(zfs_dbgmsg_t, zdm_node));
  123         mutex_init(&zfs_dbgmsgs_lock, NULL, MUTEX_DEFAULT, NULL);
  124 
  125         zfs_dbgmsg_kstat = kstat_create("zfs", 0, "dbgmsg", "misc",
  126             KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
  127         if (zfs_dbgmsg_kstat) {
  128                 zfs_dbgmsg_kstat->ks_lock = &zfs_dbgmsgs_lock;
  129                 zfs_dbgmsg_kstat->ks_ndata = UINT32_MAX;
  130                 zfs_dbgmsg_kstat->ks_private = NULL;
  131                 zfs_dbgmsg_kstat->ks_update = zfs_dbgmsg_update;
  132                 kstat_set_raw_ops(zfs_dbgmsg_kstat, zfs_dbgmsg_headers,
  133                     zfs_dbgmsg_data, zfs_dbgmsg_addr);
  134                 kstat_install(zfs_dbgmsg_kstat);
  135         }
  136 }
  137 
  138 void
  139 zfs_dbgmsg_fini(void)
  140 {
  141         if (zfs_dbgmsg_kstat)
  142                 kstat_delete(zfs_dbgmsg_kstat);
  143         /*
  144          * TODO - decide how to make this permanent
  145          */
  146 #ifdef _KERNEL
  147         mutex_enter(&zfs_dbgmsgs_lock);
  148         zfs_dbgmsg_purge(0);
  149         mutex_exit(&zfs_dbgmsgs_lock);
  150         mutex_destroy(&zfs_dbgmsgs_lock);
  151 #endif
  152 }
  153 
  154 void
  155 __zfs_dbgmsg(char *buf)
  156 {
  157         zfs_dbgmsg_t *zdm;
  158         uint_t size;
  159 
  160         DTRACE_PROBE1(zfs__dbgmsg, char *, buf);
  161 
  162         size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1;
  163         zdm = kmem_zalloc(size, KM_SLEEP);
  164         zdm->zdm_size = size;
  165         zdm->zdm_timestamp = gethrestime_sec();
  166         strcpy(zdm->zdm_msg, buf);
  167 
  168         mutex_enter(&zfs_dbgmsgs_lock);
  169         list_insert_tail(&zfs_dbgmsgs, zdm);
  170         zfs_dbgmsg_size += size;
  171         zfs_dbgmsg_purge(zfs_dbgmsg_maxsize);
  172         mutex_exit(&zfs_dbgmsgs_lock);
  173 }
  174 
  175 void
  176 __set_error(const char *file, const char *func, int line, int err)
  177 {
  178         /*
  179          * To enable this:
  180          *
  181          * $ echo 512 >/sys/module/zfs/parameters/zfs_flags
  182          */
  183         if (zfs_flags & ZFS_DEBUG_SET_ERROR)
  184                 __dprintf(B_FALSE, file, func, line, "error %lu", (ulong_t)err);
  185 }
  186 
  187 #ifdef _KERNEL
  188 void
  189 __dprintf(boolean_t dprint, const char *file, const char *func,
  190     int line, const char *fmt, ...)
  191 {
  192         const char *newfile;
  193         va_list adx;
  194         size_t size;
  195         char *buf;
  196         char *nl;
  197         int i;
  198 
  199         size = 1024;
  200         buf = kmem_alloc(size, KM_SLEEP);
  201 
  202         /*
  203          * Get rid of annoying prefix to filename.
  204          */
  205         newfile = strrchr(file, '/');
  206         if (newfile != NULL) {
  207                 newfile = newfile + 1; /* Get rid of leading / */
  208         } else {
  209                 newfile = file;
  210         }
  211 
  212         i = snprintf(buf, size, "%s:%d:%s(): ", newfile, line, func);
  213 
  214         if (i < size) {
  215                 va_start(adx, fmt);
  216                 (void) vsnprintf(buf + i, size - i, fmt, adx);
  217                 va_end(adx);
  218         }
  219 
  220         /*
  221          * Get rid of trailing newline.
  222          */
  223         nl = strrchr(buf, '\n');
  224         if (nl != NULL)
  225                 *nl = '\0';
  226 
  227         __zfs_dbgmsg(buf);
  228 
  229         kmem_free(buf, size);
  230 }
  231 
  232 #else
  233 
  234 void
  235 zfs_dbgmsg_print(const char *tag)
  236 {
  237         zfs_dbgmsg_t *zdm;
  238 
  239         (void) printf("ZFS_DBGMSG(%s):\n", tag);
  240         mutex_enter(&zfs_dbgmsgs_lock);
  241         for (zdm = list_head(&zfs_dbgmsgs); zdm;
  242             zdm = list_next(&zfs_dbgmsgs, zdm))
  243                 (void) printf("%s\n", zdm->zdm_msg);
  244         mutex_exit(&zfs_dbgmsgs_lock);
  245 }
  246 #endif /* _KERNEL */
  247 
  248 ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_enable, INT, ZMOD_RW,
  249         "Enable ZFS debug message log");
  250 
  251 ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_maxsize, UINT, ZMOD_RW,
  252         "Maximum ZFS debug log size");

Cache object: 402ff7e3f8507a8273f8d5b42647a30f


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