xref: /freebsd/sys/contrib/openzfs/module/zfs/zfs_debug_common.c (revision 071ab5a1f3cbfd29c8fbec27f7e619418adaf074)
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) 2025 by Lawrence Livermore National Security, LLC.
24  */
25 /*
26  * This file contains zfs_dbgmsg() specific functions that are not OS or
27  * userspace specific.
28  */
29 #if !defined(_KERNEL)
30 #include <string.h>
31 #endif
32 
33 #include <sys/zfs_context.h>
34 #include <sys/zfs_debug.h>
35 #include <sys/nvpair.h>
36 
37 /*
38  * Given a multi-line string, print out one of the lines and return a pointer
39  * to the next line. Lines are demarcated by '\n'.  Note: this modifies the
40  * input string (buf[]).
41  *
42  * This function is meant to be used in a loop like:
43  * 	while (buf != NULL)
44  * 		buf = kernel_print_one_line(buf);
45  *
46  * This function is useful for printing large, multi-line text buffers.
47  *
48  * Returns the pointer to the beginning of the next line in buf[], or NULL
49  * if it's the last line, or nothing more to print.
50  */
51 static char *
zfs_dbgmsg_one_line(char * buf)52 zfs_dbgmsg_one_line(char *buf)
53 {
54 	char *nl;
55 	if (!buf)
56 		return (NULL);
57 
58 	nl = strchr(buf, '\n');
59 	if (nl == NULL) {
60 		__zfs_dbgmsg(buf);
61 		return (NULL); /* done */
62 	}
63 	*nl = '\0';
64 	__zfs_dbgmsg(buf);
65 
66 	return (nl + 1);
67 }
68 
69 /*
70  * Dump an nvlist tree to dbgmsg.
71  *
72  * This is the zfs_dbgmsg version of userspace's dump_nvlist() from libnvpair.
73  */
74 void
__zfs_dbgmsg_nvlist(nvlist_t * nv)75 __zfs_dbgmsg_nvlist(nvlist_t *nv)
76 {
77 	int len;
78 	char *buf;
79 
80 	len = nvlist_snprintf(NULL, 0, nv, 4);
81 	len++; /* Add null terminator */
82 
83 	buf = vmem_alloc(len, KM_SLEEP);
84 	if (buf == NULL)
85 		return;
86 
87 	(void) nvlist_snprintf(buf, len, nv, 4);
88 
89 	while (buf != NULL)
90 		buf = zfs_dbgmsg_one_line(buf);
91 
92 	vmem_free(buf, len);
93 }
94 
95 #ifdef _KERNEL
96 EXPORT_SYMBOL(__zfs_dbgmsg_nvlist);
97 #endif
98