1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * debug.c - NTFS kernel debug support. Part of the Linux-NTFS project.
4  *
5  * Copyright (c) 2001-2004 Anton Altaparmakov
6  */
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include "debug.h"
9 
10 /**
11  * __ntfs_warning - output a warning to the syslog
12  * @function:	name of function outputting the warning
13  * @sb:		super block of mounted ntfs filesystem
14  * @fmt:	warning string containing format specifications
15  * @...:	a variable number of arguments specified in @fmt
16  *
17  * Outputs a warning to the syslog for the mounted ntfs filesystem described
18  * by @sb.
19  *
20  * @fmt and the corresponding @... is printf style format string containing
21  * the warning string and the corresponding format arguments, respectively.
22  *
23  * @function is the name of the function from which __ntfs_warning is being
24  * called.
25  *
26  * Note, you should be using debug.h::ntfs_warning(@sb, @fmt, @...) instead
27  * as this provides the @function parameter automatically.
28  */
__ntfs_warning(const char * function,const struct super_block * sb,const char * fmt,...)29 void __ntfs_warning(const char *function, const struct super_block *sb,
30 		const char *fmt, ...)
31 {
32 	struct va_format vaf;
33 	va_list args;
34 	int flen = 0;
35 
36 #ifndef DEBUG
37 	if (!printk_ratelimit())
38 		return;
39 #endif
40 	if (function)
41 		flen = strlen(function);
42 	va_start(args, fmt);
43 	vaf.fmt = fmt;
44 	vaf.va = &args;
45 	if (sb)
46 		pr_warn("(device %s): %s(): %pV\n",
47 			sb->s_id, flen ? function : "", &vaf);
48 	else
49 		pr_warn("%s(): %pV\n", flen ? function : "", &vaf);
50 	va_end(args);
51 }
52 
53 /**
54  * __ntfs_error - output an error to the syslog
55  * @function:	name of function outputting the error
56  * @sb:		super block of mounted ntfs filesystem
57  * @fmt:	error string containing format specifications
58  * @...:	a variable number of arguments specified in @fmt
59  *
60  * Outputs an error to the syslog for the mounted ntfs filesystem described
61  * by @sb.
62  *
63  * @fmt and the corresponding @... is printf style format string containing
64  * the error string and the corresponding format arguments, respectively.
65  *
66  * @function is the name of the function from which __ntfs_error is being
67  * called.
68  *
69  * Note, you should be using debug.h::ntfs_error(@sb, @fmt, @...) instead
70  * as this provides the @function parameter automatically.
71  */
__ntfs_error(const char * function,const struct super_block * sb,const char * fmt,...)72 void __ntfs_error(const char *function, const struct super_block *sb,
73 		const char *fmt, ...)
74 {
75 	struct va_format vaf;
76 	va_list args;
77 	int flen = 0;
78 
79 #ifndef DEBUG
80 	if (!printk_ratelimit())
81 		return;
82 #endif
83 	if (function)
84 		flen = strlen(function);
85 	va_start(args, fmt);
86 	vaf.fmt = fmt;
87 	vaf.va = &args;
88 	if (sb)
89 		pr_err("(device %s): %s(): %pV\n",
90 		       sb->s_id, flen ? function : "", &vaf);
91 	else
92 		pr_err("%s(): %pV\n", flen ? function : "", &vaf);
93 	va_end(args);
94 }
95 
96 #ifdef DEBUG
97 
98 /* If 1, output debug messages, and if 0, don't. */
99 int debug_msgs = 0;
100 
__ntfs_debug(const char * file,int line,const char * function,const char * fmt,...)101 void __ntfs_debug(const char *file, int line, const char *function,
102 		const char *fmt, ...)
103 {
104 	struct va_format vaf;
105 	va_list args;
106 	int flen = 0;
107 
108 	if (!debug_msgs)
109 		return;
110 	if (function)
111 		flen = strlen(function);
112 	va_start(args, fmt);
113 	vaf.fmt = fmt;
114 	vaf.va = &args;
115 	pr_debug("(%s, %d): %s(): %pV", file, line, flen ? function : "", &vaf);
116 	va_end(args);
117 }
118 
119 /* Dump a runlist. Caller has to provide synchronisation for @rl. */
ntfs_debug_dump_runlist(const runlist_element * rl)120 void ntfs_debug_dump_runlist(const runlist_element *rl)
121 {
122 	int i;
123 	const char *lcn_str[5] = { "LCN_HOLE         ", "LCN_RL_NOT_MAPPED",
124 				   "LCN_ENOENT       ", "LCN_unknown      " };
125 
126 	if (!debug_msgs)
127 		return;
128 	pr_debug("Dumping runlist (values in hex):\n");
129 	if (!rl) {
130 		pr_debug("Run list not present.\n");
131 		return;
132 	}
133 	pr_debug("VCN              LCN               Run length\n");
134 	for (i = 0; ; i++) {
135 		LCN lcn = (rl + i)->lcn;
136 
137 		if (lcn < (LCN)0) {
138 			int index = -lcn - 1;
139 
140 			if (index > -LCN_ENOENT - 1)
141 				index = 3;
142 			pr_debug("%-16Lx %s %-16Lx%s\n",
143 					(long long)(rl + i)->vcn, lcn_str[index],
144 					(long long)(rl + i)->length,
145 					(rl + i)->length ? "" :
146 						" (runlist end)");
147 		} else
148 			pr_debug("%-16Lx %-16Lx  %-16Lx%s\n",
149 					(long long)(rl + i)->vcn,
150 					(long long)(rl + i)->lcn,
151 					(long long)(rl + i)->length,
152 					(rl + i)->length ? "" :
153 						" (runlist end)");
154 		if (!(rl + i)->length)
155 			break;
156 	}
157 }
158 
159 #endif
160