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