1219089Spjd/* 2219089Spjd * CDDL HEADER START 3219089Spjd * 4219089Spjd * The contents of this file are subject to the terms of the 5219089Spjd * Common Development and Distribution License (the "License"). 6219089Spjd * You may not use this file except in compliance with the License. 7219089Spjd * 8219089Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9219089Spjd * or http://www.opensolaris.org/os/licensing. 10219089Spjd * See the License for the specific language governing permissions 11219089Spjd * and limitations under the License. 12219089Spjd * 13219089Spjd * When distributing Covered Code, include this CDDL HEADER in each 14219089Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15219089Spjd * If applicable, add the following below this CDDL HEADER, with the 16219089Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17219089Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18219089Spjd * 19219089Spjd * CDDL HEADER END 20219089Spjd */ 21219089Spjd/* 22219089Spjd * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23268855Sdelphij * Copyright (c) 2012, 2014 by Delphix. All rights reserved. 24219089Spjd */ 25219089Spjd 26219089Spjd#include <sys/zfs_context.h> 27219089Spjd 28219089Spjdlist_t zfs_dbgmsgs; 29219089Spjdint zfs_dbgmsg_size; 30219089Spjdkmutex_t zfs_dbgmsgs_lock; 31268079Sdelphijint zfs_dbgmsg_maxsize = 4<<20; /* 4MB */ 32219089Spjd 33219089Spjdvoid 34219089Spjdzfs_dbgmsg_init(void) 35219089Spjd{ 36219089Spjd list_create(&zfs_dbgmsgs, sizeof (zfs_dbgmsg_t), 37219089Spjd offsetof(zfs_dbgmsg_t, zdm_node)); 38219089Spjd mutex_init(&zfs_dbgmsgs_lock, NULL, MUTEX_DEFAULT, NULL); 39219089Spjd} 40219089Spjd 41219089Spjdvoid 42219089Spjdzfs_dbgmsg_fini(void) 43219089Spjd{ 44219089Spjd zfs_dbgmsg_t *zdm; 45219089Spjd 46219089Spjd while ((zdm = list_remove_head(&zfs_dbgmsgs)) != NULL) { 47219089Spjd int size = sizeof (zfs_dbgmsg_t) + strlen(zdm->zdm_msg); 48219089Spjd kmem_free(zdm, size); 49219089Spjd zfs_dbgmsg_size -= size; 50219089Spjd } 51219089Spjd mutex_destroy(&zfs_dbgmsgs_lock); 52240415Smm ASSERT0(zfs_dbgmsg_size); 53219089Spjd} 54219089Spjd 55219089Spjd/* 56219089Spjd * Print these messages by running: 57240415Smm * echo ::zfs_dbgmsg | mdb -k 58219089Spjd * 59219089Spjd * Monitor these messages by running: 60268855Sdelphij * dtrace -qn 'zfs-dbgmsg{printf("%s\n", stringof(arg0))}' 61268855Sdelphij * 62268855Sdelphij * When used with libzpool, monitor with: 63268855Sdelphij * dtrace -qn 'zfs$pid::zfs_dbgmsg:probe1{printf("%s\n", copyinstr(arg1))}' 64219089Spjd */ 65219089Spjdvoid 66219089Spjdzfs_dbgmsg(const char *fmt, ...) 67219089Spjd{ 68219089Spjd int size; 69219089Spjd va_list adx; 70219089Spjd zfs_dbgmsg_t *zdm; 71219089Spjd 72219089Spjd va_start(adx, fmt); 73219089Spjd size = vsnprintf(NULL, 0, fmt, adx); 74219089Spjd va_end(adx); 75219089Spjd 76219089Spjd /* 77219089Spjd * There is one byte of string in sizeof (zfs_dbgmsg_t), used 78219089Spjd * for the terminating null. 79219089Spjd */ 80219089Spjd zdm = kmem_alloc(sizeof (zfs_dbgmsg_t) + size, KM_SLEEP); 81219089Spjd zdm->zdm_timestamp = gethrestime_sec(); 82219089Spjd 83219089Spjd va_start(adx, fmt); 84219089Spjd (void) vsnprintf(zdm->zdm_msg, size + 1, fmt, adx); 85219089Spjd va_end(adx); 86219089Spjd 87219089Spjd DTRACE_PROBE1(zfs__dbgmsg, char *, zdm->zdm_msg); 88219089Spjd 89219089Spjd mutex_enter(&zfs_dbgmsgs_lock); 90219089Spjd list_insert_tail(&zfs_dbgmsgs, zdm); 91219089Spjd zfs_dbgmsg_size += sizeof (zfs_dbgmsg_t) + size; 92219089Spjd while (zfs_dbgmsg_size > zfs_dbgmsg_maxsize) { 93219089Spjd zdm = list_remove_head(&zfs_dbgmsgs); 94219089Spjd size = sizeof (zfs_dbgmsg_t) + strlen(zdm->zdm_msg); 95219089Spjd kmem_free(zdm, size); 96219089Spjd zfs_dbgmsg_size -= size; 97219089Spjd } 98219089Spjd mutex_exit(&zfs_dbgmsgs_lock); 99219089Spjd} 100254112Sdelphij 101254112Sdelphijvoid 102254112Sdelphijzfs_dbgmsg_print(const char *tag) 103254112Sdelphij{ 104254112Sdelphij zfs_dbgmsg_t *zdm; 105254112Sdelphij 106254112Sdelphij (void) printf("ZFS_DBGMSG(%s):\n", tag); 107254112Sdelphij mutex_enter(&zfs_dbgmsgs_lock); 108254112Sdelphij for (zdm = list_head(&zfs_dbgmsgs); zdm; 109254112Sdelphij zdm = list_next(&zfs_dbgmsgs, zdm)) 110254112Sdelphij (void) printf("%s\n", zdm->zdm_msg); 111254112Sdelphij mutex_exit(&zfs_dbgmsgs_lock); 112254112Sdelphij} 113