xref: /freebsd/sys/contrib/openzfs/module/zfs/zfs_debug_common.c (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * This file and its contents are supplied under the terms of the
4  * Common Development and Distribution License ("CDDL"), version 1.0.
5  * You may only use this file in accordance with the terms of version
6  * 1.0 of the CDDL.
7  *
8  * A full copy of the text of the CDDL should have accompanied this
9  * source.  A copy of the CDDL is also available via the Internet at
10  * https://opensource.org/license/CDDL-1.0.
11  */
12 /*
13  * Copyright (c) 2025 by Lawrence Livermore National Security, LLC.
14  */
15 /*
16  * This file contains zfs_dbgmsg() specific functions that are not OS or
17  * userspace specific.
18  */
19 #if !defined(_KERNEL)
20 #include <string.h>
21 #endif
22 
23 #include <sys/zfs_context.h>
24 #include <sys/zfs_debug.h>
25 #include <sys/nvpair.h>
26 
27 /*
28  * Given a multi-line string, print out one of the lines and return a pointer
29  * to the next line. Lines are demarcated by '\n'.  Note: this modifies the
30  * input string (buf[]).
31  *
32  * This function is meant to be used in a loop like:
33  * 	while (buf != NULL)
34  * 		buf = kernel_print_one_line(buf);
35  *
36  * This function is useful for printing large, multi-line text buffers.
37  *
38  * Returns the pointer to the beginning of the next line in buf[], or NULL
39  * if it's the last line, or nothing more to print.
40  */
41 static char *
zfs_dbgmsg_one_line(char * buf)42 zfs_dbgmsg_one_line(char *buf)
43 {
44 	char *nl;
45 	if (!buf)
46 		return (NULL);
47 
48 	nl = strchr(buf, '\n');
49 	if (nl == NULL) {
50 		__zfs_dbgmsg(buf);
51 		return (NULL); /* done */
52 	}
53 	*nl = '\0';
54 	__zfs_dbgmsg(buf);
55 
56 	return (nl + 1);
57 }
58 
59 /*
60  * Dump an nvlist tree to dbgmsg.
61  *
62  * This is the zfs_dbgmsg version of userspace's dump_nvlist() from libnvpair.
63  */
64 void
__zfs_dbgmsg_nvlist(nvlist_t * nv)65 __zfs_dbgmsg_nvlist(nvlist_t *nv)
66 {
67 	int len;
68 	char *buf;
69 
70 	len = nvlist_snprintf(NULL, 0, nv, 4);
71 	len++; /* Add null terminator */
72 
73 	buf = vmem_alloc(len, KM_SLEEP);
74 	if (buf == NULL)
75 		return;
76 
77 	(void) nvlist_snprintf(buf, len, nv, 4);
78 
79 	while (buf != NULL)
80 		buf = zfs_dbgmsg_one_line(buf);
81 
82 	vmem_free(buf, len);
83 }
84 
85 #ifdef _KERNEL
86 EXPORT_SYMBOL(__zfs_dbgmsg_nvlist);
87 #endif
88