13f9d6ad7SLin Ling /* 23f9d6ad7SLin Ling * CDDL HEADER START 33f9d6ad7SLin Ling * 43f9d6ad7SLin Ling * The contents of this file are subject to the terms of the 53f9d6ad7SLin Ling * Common Development and Distribution License (the "License"). 63f9d6ad7SLin Ling * You may not use this file except in compliance with the License. 73f9d6ad7SLin Ling * 83f9d6ad7SLin Ling * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93f9d6ad7SLin Ling * or http://www.opensolaris.org/os/licensing. 103f9d6ad7SLin Ling * See the License for the specific language governing permissions 113f9d6ad7SLin Ling * and limitations under the License. 123f9d6ad7SLin Ling * 133f9d6ad7SLin Ling * When distributing Covered Code, include this CDDL HEADER in each 143f9d6ad7SLin Ling * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153f9d6ad7SLin Ling * If applicable, add the following below this CDDL HEADER, with the 163f9d6ad7SLin Ling * fields enclosed by brackets "[]" replaced with your own identifying 173f9d6ad7SLin Ling * information: Portions Copyright [yyyy] [name of copyright owner] 183f9d6ad7SLin Ling * 193f9d6ad7SLin Ling * CDDL HEADER END 203f9d6ad7SLin Ling */ 213f9d6ad7SLin Ling /* 223f9d6ad7SLin Ling * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23*2a104a52SAlex Reece * Copyright (c) 2012, 2014 by Delphix. All rights reserved. 243f9d6ad7SLin Ling */ 253f9d6ad7SLin Ling 263f9d6ad7SLin Ling #include <sys/zfs_context.h> 273f9d6ad7SLin Ling 283f9d6ad7SLin Ling list_t zfs_dbgmsgs; 293f9d6ad7SLin Ling int zfs_dbgmsg_size; 303f9d6ad7SLin Ling kmutex_t zfs_dbgmsgs_lock; 317fd05ac4SMatthew Ahrens int zfs_dbgmsg_maxsize = 4<<20; /* 4MB */ 323f9d6ad7SLin Ling 333f9d6ad7SLin Ling void 343f9d6ad7SLin Ling zfs_dbgmsg_init(void) 353f9d6ad7SLin Ling { 363f9d6ad7SLin Ling list_create(&zfs_dbgmsgs, sizeof (zfs_dbgmsg_t), 373f9d6ad7SLin Ling offsetof(zfs_dbgmsg_t, zdm_node)); 383f9d6ad7SLin Ling mutex_init(&zfs_dbgmsgs_lock, NULL, MUTEX_DEFAULT, NULL); 393f9d6ad7SLin Ling } 403f9d6ad7SLin Ling 413f9d6ad7SLin Ling void 423f9d6ad7SLin Ling zfs_dbgmsg_fini(void) 433f9d6ad7SLin Ling { 443f9d6ad7SLin Ling zfs_dbgmsg_t *zdm; 453f9d6ad7SLin Ling 463f9d6ad7SLin Ling while ((zdm = list_remove_head(&zfs_dbgmsgs)) != NULL) { 473f9d6ad7SLin Ling int size = sizeof (zfs_dbgmsg_t) + strlen(zdm->zdm_msg); 483f9d6ad7SLin Ling kmem_free(zdm, size); 493f9d6ad7SLin Ling zfs_dbgmsg_size -= size; 503f9d6ad7SLin Ling } 513f9d6ad7SLin Ling mutex_destroy(&zfs_dbgmsgs_lock); 52fb09f5aaSMadhav Suresh ASSERT0(zfs_dbgmsg_size); 533f9d6ad7SLin Ling } 543f9d6ad7SLin Ling 553f9d6ad7SLin Ling /* 563f9d6ad7SLin Ling * Print these messages by running: 573f9d6ad7SLin Ling * echo ::zfs_dbgmsg | mdb -k 583f9d6ad7SLin Ling * 593f9d6ad7SLin Ling * Monitor these messages by running: 60*2a104a52SAlex Reece * dtrace -qn 'zfs-dbgmsg{printf("%s\n", stringof(arg0))}' 61*2a104a52SAlex Reece * 62*2a104a52SAlex Reece * When used with libzpool, monitor with: 63*2a104a52SAlex Reece * dtrace -qn 'zfs$pid::zfs_dbgmsg:probe1{printf("%s\n", copyinstr(arg1))}' 643f9d6ad7SLin Ling */ 653f9d6ad7SLin Ling void 663f9d6ad7SLin Ling zfs_dbgmsg(const char *fmt, ...) 673f9d6ad7SLin Ling { 683f9d6ad7SLin Ling int size; 693f9d6ad7SLin Ling va_list adx; 703f9d6ad7SLin Ling zfs_dbgmsg_t *zdm; 713f9d6ad7SLin Ling 723f9d6ad7SLin Ling va_start(adx, fmt); 733f9d6ad7SLin Ling size = vsnprintf(NULL, 0, fmt, adx); 743f9d6ad7SLin Ling va_end(adx); 753f9d6ad7SLin Ling 763f9d6ad7SLin Ling /* 773f9d6ad7SLin Ling * There is one byte of string in sizeof (zfs_dbgmsg_t), used 783f9d6ad7SLin Ling * for the terminating null. 793f9d6ad7SLin Ling */ 803f9d6ad7SLin Ling zdm = kmem_alloc(sizeof (zfs_dbgmsg_t) + size, KM_SLEEP); 813f9d6ad7SLin Ling zdm->zdm_timestamp = gethrestime_sec(); 823f9d6ad7SLin Ling 833f9d6ad7SLin Ling va_start(adx, fmt); 843f9d6ad7SLin Ling (void) vsnprintf(zdm->zdm_msg, size + 1, fmt, adx); 853f9d6ad7SLin Ling va_end(adx); 863f9d6ad7SLin Ling 873f9d6ad7SLin Ling DTRACE_PROBE1(zfs__dbgmsg, char *, zdm->zdm_msg); 883f9d6ad7SLin Ling 893f9d6ad7SLin Ling mutex_enter(&zfs_dbgmsgs_lock); 903f9d6ad7SLin Ling list_insert_tail(&zfs_dbgmsgs, zdm); 913f9d6ad7SLin Ling zfs_dbgmsg_size += sizeof (zfs_dbgmsg_t) + size; 923f9d6ad7SLin Ling while (zfs_dbgmsg_size > zfs_dbgmsg_maxsize) { 933f9d6ad7SLin Ling zdm = list_remove_head(&zfs_dbgmsgs); 943f9d6ad7SLin Ling size = sizeof (zfs_dbgmsg_t) + strlen(zdm->zdm_msg); 953f9d6ad7SLin Ling kmem_free(zdm, size); 963f9d6ad7SLin Ling zfs_dbgmsg_size -= size; 973f9d6ad7SLin Ling } 983f9d6ad7SLin Ling mutex_exit(&zfs_dbgmsgs_lock); 993f9d6ad7SLin Ling } 100b4952e17SGeorge Wilson 101b4952e17SGeorge Wilson void 102b4952e17SGeorge Wilson zfs_dbgmsg_print(const char *tag) 103b4952e17SGeorge Wilson { 104b4952e17SGeorge Wilson zfs_dbgmsg_t *zdm; 105b4952e17SGeorge Wilson 106b4952e17SGeorge Wilson (void) printf("ZFS_DBGMSG(%s):\n", tag); 107b4952e17SGeorge Wilson mutex_enter(&zfs_dbgmsgs_lock); 108b4952e17SGeorge Wilson for (zdm = list_head(&zfs_dbgmsgs); zdm; 109b4952e17SGeorge Wilson zdm = list_next(&zfs_dbgmsgs, zdm)) 110b4952e17SGeorge Wilson (void) printf("%s\n", zdm->zdm_msg); 111b4952e17SGeorge Wilson mutex_exit(&zfs_dbgmsgs_lock); 112b4952e17SGeorge Wilson } 113