xref: /freebsd-src/sys/contrib/openzfs/module/os/linux/zfs/zfs_debug.c (revision 17aab35a77a1b1bf02fc85bb8ffadccb0ca5006d)
1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * CDDL HEADER START
3eda14cbcSMatt Macy  *
4eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11eda14cbcSMatt Macy  * and limitations under the License.
12eda14cbcSMatt Macy  *
13eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18eda14cbcSMatt Macy  *
19eda14cbcSMatt Macy  * CDDL HEADER END
20eda14cbcSMatt Macy  */
21eda14cbcSMatt Macy /*
22eda14cbcSMatt Macy  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23eda14cbcSMatt Macy  * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
24eda14cbcSMatt Macy  */
25eda14cbcSMatt Macy 
26eda14cbcSMatt Macy #include <sys/zfs_context.h>
27eda14cbcSMatt Macy #include <sys/trace_zfs.h>
28eda14cbcSMatt Macy 
29eda14cbcSMatt Macy typedef struct zfs_dbgmsg {
30eda14cbcSMatt Macy 	procfs_list_node_t	zdm_node;
31eda14cbcSMatt Macy 	uint64_t		zdm_timestamp;
32be181ee2SMartin Matuska 	uint_t			zdm_size;
3315f0b8c3SMartin Matuska 	char			zdm_msg[]; /* variable length allocation */
34eda14cbcSMatt Macy } zfs_dbgmsg_t;
35eda14cbcSMatt Macy 
36e92ffd9bSMartin Matuska static procfs_list_t zfs_dbgmsgs;
37be181ee2SMartin Matuska static uint_t zfs_dbgmsg_size = 0;
38dbd5678dSMartin Matuska static uint_t zfs_dbgmsg_maxsize = 4<<20; /* 4MB */
39eda14cbcSMatt Macy 
40eda14cbcSMatt Macy /*
41eda14cbcSMatt Macy  * Internal ZFS debug messages are enabled by default.
42eda14cbcSMatt Macy  *
43eda14cbcSMatt Macy  * # Print debug messages
44eda14cbcSMatt Macy  * cat /proc/spl/kstat/zfs/dbgmsg
45eda14cbcSMatt Macy  *
46eda14cbcSMatt Macy  * # Disable the kernel debug message log.
47eda14cbcSMatt Macy  * echo 0 > /sys/module/zfs/parameters/zfs_dbgmsg_enable
48eda14cbcSMatt Macy  *
49eda14cbcSMatt Macy  * # Clear the kernel debug message log.
50eda14cbcSMatt Macy  * echo 0 >/proc/spl/kstat/zfs/dbgmsg
51eda14cbcSMatt Macy  */
52e92ffd9bSMartin Matuska int zfs_dbgmsg_enable = B_TRUE;
53eda14cbcSMatt Macy 
54eda14cbcSMatt Macy static int
55eda14cbcSMatt Macy zfs_dbgmsg_show_header(struct seq_file *f)
56eda14cbcSMatt Macy {
57eda14cbcSMatt Macy 	seq_printf(f, "%-12s %-8s\n", "timestamp", "message");
58eda14cbcSMatt Macy 	return (0);
59eda14cbcSMatt Macy }
60eda14cbcSMatt Macy 
61eda14cbcSMatt Macy static int
62eda14cbcSMatt Macy zfs_dbgmsg_show(struct seq_file *f, void *p)
63eda14cbcSMatt Macy {
64eda14cbcSMatt Macy 	zfs_dbgmsg_t *zdm = (zfs_dbgmsg_t *)p;
65eda14cbcSMatt Macy 	seq_printf(f, "%-12llu %-s\n",
66eda14cbcSMatt Macy 	    (u_longlong_t)zdm->zdm_timestamp, zdm->zdm_msg);
67eda14cbcSMatt Macy 	return (0);
68eda14cbcSMatt Macy }
69eda14cbcSMatt Macy 
70eda14cbcSMatt Macy static void
71be181ee2SMartin Matuska zfs_dbgmsg_purge(uint_t max_size)
72eda14cbcSMatt Macy {
73eda14cbcSMatt Macy 	while (zfs_dbgmsg_size > max_size) {
74eda14cbcSMatt Macy 		zfs_dbgmsg_t *zdm = list_remove_head(&zfs_dbgmsgs.pl_list);
75eda14cbcSMatt Macy 		if (zdm == NULL)
76eda14cbcSMatt Macy 			return;
77eda14cbcSMatt Macy 
78be181ee2SMartin Matuska 		uint_t size = zdm->zdm_size;
79eda14cbcSMatt Macy 		kmem_free(zdm, size);
80eda14cbcSMatt Macy 		zfs_dbgmsg_size -= size;
81eda14cbcSMatt Macy 	}
82eda14cbcSMatt Macy }
83eda14cbcSMatt Macy 
84eda14cbcSMatt Macy static int
85eda14cbcSMatt Macy zfs_dbgmsg_clear(procfs_list_t *procfs_list)
86eda14cbcSMatt Macy {
87e92ffd9bSMartin Matuska 	(void) procfs_list;
88eda14cbcSMatt Macy 	mutex_enter(&zfs_dbgmsgs.pl_lock);
89eda14cbcSMatt Macy 	zfs_dbgmsg_purge(0);
90eda14cbcSMatt Macy 	mutex_exit(&zfs_dbgmsgs.pl_lock);
91eda14cbcSMatt Macy 	return (0);
92eda14cbcSMatt Macy }
93eda14cbcSMatt Macy 
94eda14cbcSMatt Macy void
95eda14cbcSMatt Macy zfs_dbgmsg_init(void)
96eda14cbcSMatt Macy {
97eda14cbcSMatt Macy 	procfs_list_install("zfs",
98c40487d4SMatt Macy 	    NULL,
99eda14cbcSMatt Macy 	    "dbgmsg",
100eda14cbcSMatt Macy 	    0600,
101eda14cbcSMatt Macy 	    &zfs_dbgmsgs,
102eda14cbcSMatt Macy 	    zfs_dbgmsg_show,
103eda14cbcSMatt Macy 	    zfs_dbgmsg_show_header,
104eda14cbcSMatt Macy 	    zfs_dbgmsg_clear,
105eda14cbcSMatt Macy 	    offsetof(zfs_dbgmsg_t, zdm_node));
106eda14cbcSMatt Macy }
107eda14cbcSMatt Macy 
108eda14cbcSMatt Macy void
109eda14cbcSMatt Macy zfs_dbgmsg_fini(void)
110eda14cbcSMatt Macy {
111eda14cbcSMatt Macy 	procfs_list_uninstall(&zfs_dbgmsgs);
112eda14cbcSMatt Macy 	zfs_dbgmsg_purge(0);
113eda14cbcSMatt Macy 
114eda14cbcSMatt Macy 	procfs_list_destroy(&zfs_dbgmsgs);
115eda14cbcSMatt Macy }
116eda14cbcSMatt Macy 
117eda14cbcSMatt Macy void
118eda14cbcSMatt Macy __set_error(const char *file, const char *func, int line, int err)
119eda14cbcSMatt Macy {
120eda14cbcSMatt Macy 	/*
121eda14cbcSMatt Macy 	 * To enable this:
122eda14cbcSMatt Macy 	 *
123eda14cbcSMatt Macy 	 * $ echo 512 >/sys/module/zfs/parameters/zfs_flags
124eda14cbcSMatt Macy 	 */
125eda14cbcSMatt Macy 	if (zfs_flags & ZFS_DEBUG_SET_ERROR)
12633b8c039SMartin Matuska 		__dprintf(B_FALSE, file, func, line, "error %lu",
12733b8c039SMartin Matuska 		    (ulong_t)err);
128eda14cbcSMatt Macy }
129eda14cbcSMatt Macy 
130eda14cbcSMatt Macy void
131eda14cbcSMatt Macy __zfs_dbgmsg(char *buf)
132eda14cbcSMatt Macy {
13315f0b8c3SMartin Matuska 	uint_t size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1;
134eda14cbcSMatt Macy 	zfs_dbgmsg_t *zdm = kmem_zalloc(size, KM_SLEEP);
135eda14cbcSMatt Macy 	zdm->zdm_size = size;
136eda14cbcSMatt Macy 	zdm->zdm_timestamp = gethrestime_sec();
137eda14cbcSMatt Macy 	strcpy(zdm->zdm_msg, buf);
138eda14cbcSMatt Macy 
139eda14cbcSMatt Macy 	mutex_enter(&zfs_dbgmsgs.pl_lock);
140eda14cbcSMatt Macy 	procfs_list_add(&zfs_dbgmsgs, zdm);
141eda14cbcSMatt Macy 	zfs_dbgmsg_size += size;
142be181ee2SMartin Matuska 	zfs_dbgmsg_purge(zfs_dbgmsg_maxsize);
143eda14cbcSMatt Macy 	mutex_exit(&zfs_dbgmsgs.pl_lock);
144eda14cbcSMatt Macy }
145eda14cbcSMatt Macy 
146eda14cbcSMatt Macy void
147eda14cbcSMatt Macy __dprintf(boolean_t dprint, const char *file, const char *func,
148eda14cbcSMatt Macy     int line, const char *fmt, ...)
149eda14cbcSMatt Macy {
150eda14cbcSMatt Macy 	const char *newfile;
151eda14cbcSMatt Macy 	va_list adx;
152eda14cbcSMatt Macy 	size_t size;
153eda14cbcSMatt Macy 	char *buf;
154eda14cbcSMatt Macy 	char *nl;
155eda14cbcSMatt Macy 	int i;
156eda14cbcSMatt Macy 	char *prefix = (dprint) ? "dprintf: " : "";
157eda14cbcSMatt Macy 
158eda14cbcSMatt Macy 	size = 1024;
159eda14cbcSMatt Macy 	buf = kmem_alloc(size, KM_SLEEP);
160eda14cbcSMatt Macy 
161eda14cbcSMatt Macy 	/*
162eda14cbcSMatt Macy 	 * Get rid of annoying prefix to filename.
163eda14cbcSMatt Macy 	 */
164eda14cbcSMatt Macy 	newfile = strrchr(file, '/');
165eda14cbcSMatt Macy 	if (newfile != NULL) {
166eda14cbcSMatt Macy 		newfile = newfile + 1; /* Get rid of leading / */
167eda14cbcSMatt Macy 	} else {
168eda14cbcSMatt Macy 		newfile = file;
169eda14cbcSMatt Macy 	}
170eda14cbcSMatt Macy 
171*e716630dSMartin Matuska 	i = snprintf(buf, size, "%px %s%s:%d:%s(): ",
172*e716630dSMartin Matuska 	    curthread, prefix, newfile, line, func);
173eda14cbcSMatt Macy 
174eda14cbcSMatt Macy 	if (i < size) {
175eda14cbcSMatt Macy 		va_start(adx, fmt);
176eda14cbcSMatt Macy 		(void) vsnprintf(buf + i, size - i, fmt, adx);
177eda14cbcSMatt Macy 		va_end(adx);
178eda14cbcSMatt Macy 	}
179eda14cbcSMatt Macy 
180eda14cbcSMatt Macy 	/*
181eda14cbcSMatt Macy 	 * Get rid of trailing newline for dprintf logs.
182eda14cbcSMatt Macy 	 */
183eda14cbcSMatt Macy 	if (dprint && buf[0] != '\0') {
184eda14cbcSMatt Macy 		nl = &buf[strlen(buf) - 1];
185eda14cbcSMatt Macy 		if (*nl == '\n')
186eda14cbcSMatt Macy 			*nl = '\0';
187eda14cbcSMatt Macy 	}
188eda14cbcSMatt Macy 
189eda14cbcSMatt Macy 	/*
190eda14cbcSMatt Macy 	 * To get this data enable the zfs__dprintf trace point as shown:
191eda14cbcSMatt Macy 	 *
192eda14cbcSMatt Macy 	 * # Enable zfs__dprintf tracepoint, clear the tracepoint ring buffer
193eda14cbcSMatt Macy 	 * $ echo 1 > /sys/kernel/debug/tracing/events/zfs/enable
194eda14cbcSMatt Macy 	 * $ echo 0 > /sys/kernel/debug/tracing/trace
195eda14cbcSMatt Macy 	 *
196eda14cbcSMatt Macy 	 * # Dump the ring buffer.
197eda14cbcSMatt Macy 	 * $ cat /sys/kernel/debug/tracing/trace
198eda14cbcSMatt Macy 	 */
199eda14cbcSMatt Macy 	DTRACE_PROBE1(zfs__dprintf, char *, buf);
200eda14cbcSMatt Macy 
201eda14cbcSMatt Macy 	/*
202eda14cbcSMatt Macy 	 * To get this data:
203eda14cbcSMatt Macy 	 *
204eda14cbcSMatt Macy 	 * $ cat /proc/spl/kstat/zfs/dbgmsg
205eda14cbcSMatt Macy 	 *
206eda14cbcSMatt Macy 	 * To clear the buffer:
207eda14cbcSMatt Macy 	 * $ echo 0 > /proc/spl/kstat/zfs/dbgmsg
208eda14cbcSMatt Macy 	 */
209eda14cbcSMatt Macy 	__zfs_dbgmsg(buf);
210eda14cbcSMatt Macy 
211eda14cbcSMatt Macy 	kmem_free(buf, size);
212eda14cbcSMatt Macy }
213eda14cbcSMatt Macy 
214eda14cbcSMatt Macy module_param(zfs_dbgmsg_enable, int, 0644);
215eda14cbcSMatt Macy MODULE_PARM_DESC(zfs_dbgmsg_enable, "Enable ZFS debug message log");
216eda14cbcSMatt Macy 
217be181ee2SMartin Matuska module_param(zfs_dbgmsg_maxsize, uint, 0644);
218eda14cbcSMatt Macy MODULE_PARM_DESC(zfs_dbgmsg_maxsize, "Maximum ZFS debug log size");
219