1*7a7741afSMartin Matuska /* 2*7a7741afSMartin Matuska * CDDL HEADER START 3*7a7741afSMartin Matuska * 4*7a7741afSMartin Matuska * The contents of this file are subject to the terms of the 5*7a7741afSMartin Matuska * Common Development and Distribution License (the "License"). 6*7a7741afSMartin Matuska * You may not use this file except in compliance with the License. 7*7a7741afSMartin Matuska * 8*7a7741afSMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7a7741afSMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10*7a7741afSMartin Matuska * See the License for the specific language governing permissions 11*7a7741afSMartin Matuska * and limitations under the License. 12*7a7741afSMartin Matuska * 13*7a7741afSMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14*7a7741afSMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7a7741afSMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16*7a7741afSMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17*7a7741afSMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18*7a7741afSMartin Matuska * 19*7a7741afSMartin Matuska * CDDL HEADER END 20*7a7741afSMartin Matuska */ 21*7a7741afSMartin Matuska /* 22*7a7741afSMartin Matuska * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23*7a7741afSMartin Matuska * Copyright (c) 2012, 2014 by Delphix. All rights reserved. 24*7a7741afSMartin Matuska * Copyright (c) 2024, Rob Norris <robn@despairlabs.com> 25*7a7741afSMartin Matuska */ 26*7a7741afSMartin Matuska 27*7a7741afSMartin Matuska #include <sys/zfs_context.h> 28*7a7741afSMartin Matuska 29*7a7741afSMartin Matuska typedef struct zfs_dbgmsg { 30*7a7741afSMartin Matuska list_node_t zdm_node; 31*7a7741afSMartin Matuska uint64_t zdm_timestamp; 32*7a7741afSMartin Matuska uint_t zdm_size; 33*7a7741afSMartin Matuska char zdm_msg[]; /* variable length allocation */ 34*7a7741afSMartin Matuska } zfs_dbgmsg_t; 35*7a7741afSMartin Matuska 36*7a7741afSMartin Matuska static list_t zfs_dbgmsgs; 37*7a7741afSMartin Matuska static kmutex_t zfs_dbgmsgs_lock; 38*7a7741afSMartin Matuska 39*7a7741afSMartin Matuska int zfs_dbgmsg_enable = B_TRUE; 40*7a7741afSMartin Matuska 41*7a7741afSMartin Matuska void 42*7a7741afSMartin Matuska zfs_dbgmsg_init(void) 43*7a7741afSMartin Matuska { 44*7a7741afSMartin Matuska list_create(&zfs_dbgmsgs, sizeof (zfs_dbgmsg_t), 45*7a7741afSMartin Matuska offsetof(zfs_dbgmsg_t, zdm_node)); 46*7a7741afSMartin Matuska mutex_init(&zfs_dbgmsgs_lock, NULL, MUTEX_DEFAULT, NULL); 47*7a7741afSMartin Matuska } 48*7a7741afSMartin Matuska 49*7a7741afSMartin Matuska void 50*7a7741afSMartin Matuska zfs_dbgmsg_fini(void) 51*7a7741afSMartin Matuska { 52*7a7741afSMartin Matuska zfs_dbgmsg_t *zdm; 53*7a7741afSMartin Matuska while ((zdm = list_remove_head(&zfs_dbgmsgs))) 54*7a7741afSMartin Matuska umem_free(zdm, zdm->zdm_size); 55*7a7741afSMartin Matuska mutex_destroy(&zfs_dbgmsgs_lock); 56*7a7741afSMartin Matuska } 57*7a7741afSMartin Matuska 58*7a7741afSMartin Matuska void 59*7a7741afSMartin Matuska __set_error(const char *file, const char *func, int line, int err) 60*7a7741afSMartin Matuska { 61*7a7741afSMartin Matuska if (zfs_flags & ZFS_DEBUG_SET_ERROR) 62*7a7741afSMartin Matuska __dprintf(B_FALSE, file, func, line, "error %lu", 63*7a7741afSMartin Matuska (ulong_t)err); 64*7a7741afSMartin Matuska } 65*7a7741afSMartin Matuska 66*7a7741afSMartin Matuska void 67*7a7741afSMartin Matuska __zfs_dbgmsg(char *buf) 68*7a7741afSMartin Matuska { 69*7a7741afSMartin Matuska uint_t size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1; 70*7a7741afSMartin Matuska zfs_dbgmsg_t *zdm = umem_zalloc(size, KM_SLEEP); 71*7a7741afSMartin Matuska zdm->zdm_size = size; 72*7a7741afSMartin Matuska zdm->zdm_timestamp = gethrestime_sec(); 73*7a7741afSMartin Matuska strcpy(zdm->zdm_msg, buf); 74*7a7741afSMartin Matuska 75*7a7741afSMartin Matuska mutex_enter(&zfs_dbgmsgs_lock); 76*7a7741afSMartin Matuska list_insert_tail(&zfs_dbgmsgs, zdm); 77*7a7741afSMartin Matuska mutex_exit(&zfs_dbgmsgs_lock); 78*7a7741afSMartin Matuska } 79*7a7741afSMartin Matuska 80*7a7741afSMartin Matuska void 81*7a7741afSMartin Matuska zfs_dbgmsg_print(int fd, const char *tag) 82*7a7741afSMartin Matuska { 83*7a7741afSMartin Matuska ssize_t ret __attribute__((unused)); 84*7a7741afSMartin Matuska 85*7a7741afSMartin Matuska mutex_enter(&zfs_dbgmsgs_lock); 86*7a7741afSMartin Matuska 87*7a7741afSMartin Matuska /* 88*7a7741afSMartin Matuska * We use write() in this function instead of printf() 89*7a7741afSMartin Matuska * so it is safe to call from a signal handler. 90*7a7741afSMartin Matuska */ 91*7a7741afSMartin Matuska ret = write(fd, "ZFS_DBGMSG(", 11); 92*7a7741afSMartin Matuska ret = write(fd, tag, strlen(tag)); 93*7a7741afSMartin Matuska ret = write(fd, ") START:\n", 9); 94*7a7741afSMartin Matuska 95*7a7741afSMartin Matuska for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs); zdm != NULL; 96*7a7741afSMartin Matuska zdm = list_next(&zfs_dbgmsgs, zdm)) { 97*7a7741afSMartin Matuska ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg)); 98*7a7741afSMartin Matuska ret = write(fd, "\n", 1); 99*7a7741afSMartin Matuska } 100*7a7741afSMartin Matuska 101*7a7741afSMartin Matuska ret = write(fd, "ZFS_DBGMSG(", 11); 102*7a7741afSMartin Matuska ret = write(fd, tag, strlen(tag)); 103*7a7741afSMartin Matuska ret = write(fd, ") END\n", 6); 104*7a7741afSMartin Matuska 105*7a7741afSMartin Matuska mutex_exit(&zfs_dbgmsgs_lock); 106*7a7741afSMartin Matuska } 107