162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * debug.c - NTFS kernel debug support. Part of the Linux-NTFS project.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2001-2004 Anton Altaparmakov
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
862306a36Sopenharmony_ci#include "debug.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/**
1162306a36Sopenharmony_ci * __ntfs_warning - output a warning to the syslog
1262306a36Sopenharmony_ci * @function:	name of function outputting the warning
1362306a36Sopenharmony_ci * @sb:		super block of mounted ntfs filesystem
1462306a36Sopenharmony_ci * @fmt:	warning string containing format specifications
1562306a36Sopenharmony_ci * @...:	a variable number of arguments specified in @fmt
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * Outputs a warning to the syslog for the mounted ntfs filesystem described
1862306a36Sopenharmony_ci * by @sb.
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * @fmt and the corresponding @... is printf style format string containing
2162306a36Sopenharmony_ci * the warning string and the corresponding format arguments, respectively.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * @function is the name of the function from which __ntfs_warning is being
2462306a36Sopenharmony_ci * called.
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * Note, you should be using debug.h::ntfs_warning(@sb, @fmt, @...) instead
2762306a36Sopenharmony_ci * as this provides the @function parameter automatically.
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_civoid __ntfs_warning(const char *function, const struct super_block *sb,
3062306a36Sopenharmony_ci		const char *fmt, ...)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	struct va_format vaf;
3362306a36Sopenharmony_ci	va_list args;
3462306a36Sopenharmony_ci	int flen = 0;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#ifndef DEBUG
3762306a36Sopenharmony_ci	if (!printk_ratelimit())
3862306a36Sopenharmony_ci		return;
3962306a36Sopenharmony_ci#endif
4062306a36Sopenharmony_ci	if (function)
4162306a36Sopenharmony_ci		flen = strlen(function);
4262306a36Sopenharmony_ci	va_start(args, fmt);
4362306a36Sopenharmony_ci	vaf.fmt = fmt;
4462306a36Sopenharmony_ci	vaf.va = &args;
4562306a36Sopenharmony_ci	if (sb)
4662306a36Sopenharmony_ci		pr_warn("(device %s): %s(): %pV\n",
4762306a36Sopenharmony_ci			sb->s_id, flen ? function : "", &vaf);
4862306a36Sopenharmony_ci	else
4962306a36Sopenharmony_ci		pr_warn("%s(): %pV\n", flen ? function : "", &vaf);
5062306a36Sopenharmony_ci	va_end(args);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/**
5462306a36Sopenharmony_ci * __ntfs_error - output an error to the syslog
5562306a36Sopenharmony_ci * @function:	name of function outputting the error
5662306a36Sopenharmony_ci * @sb:		super block of mounted ntfs filesystem
5762306a36Sopenharmony_ci * @fmt:	error string containing format specifications
5862306a36Sopenharmony_ci * @...:	a variable number of arguments specified in @fmt
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci * Outputs an error to the syslog for the mounted ntfs filesystem described
6162306a36Sopenharmony_ci * by @sb.
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * @fmt and the corresponding @... is printf style format string containing
6462306a36Sopenharmony_ci * the error string and the corresponding format arguments, respectively.
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci * @function is the name of the function from which __ntfs_error is being
6762306a36Sopenharmony_ci * called.
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci * Note, you should be using debug.h::ntfs_error(@sb, @fmt, @...) instead
7062306a36Sopenharmony_ci * as this provides the @function parameter automatically.
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_civoid __ntfs_error(const char *function, const struct super_block *sb,
7362306a36Sopenharmony_ci		const char *fmt, ...)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	struct va_format vaf;
7662306a36Sopenharmony_ci	va_list args;
7762306a36Sopenharmony_ci	int flen = 0;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#ifndef DEBUG
8062306a36Sopenharmony_ci	if (!printk_ratelimit())
8162306a36Sopenharmony_ci		return;
8262306a36Sopenharmony_ci#endif
8362306a36Sopenharmony_ci	if (function)
8462306a36Sopenharmony_ci		flen = strlen(function);
8562306a36Sopenharmony_ci	va_start(args, fmt);
8662306a36Sopenharmony_ci	vaf.fmt = fmt;
8762306a36Sopenharmony_ci	vaf.va = &args;
8862306a36Sopenharmony_ci	if (sb)
8962306a36Sopenharmony_ci		pr_err("(device %s): %s(): %pV\n",
9062306a36Sopenharmony_ci		       sb->s_id, flen ? function : "", &vaf);
9162306a36Sopenharmony_ci	else
9262306a36Sopenharmony_ci		pr_err("%s(): %pV\n", flen ? function : "", &vaf);
9362306a36Sopenharmony_ci	va_end(args);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#ifdef DEBUG
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/* If 1, output debug messages, and if 0, don't. */
9962306a36Sopenharmony_ciint debug_msgs = 0;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_civoid __ntfs_debug(const char *file, int line, const char *function,
10262306a36Sopenharmony_ci		const char *fmt, ...)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	struct va_format vaf;
10562306a36Sopenharmony_ci	va_list args;
10662306a36Sopenharmony_ci	int flen = 0;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	if (!debug_msgs)
10962306a36Sopenharmony_ci		return;
11062306a36Sopenharmony_ci	if (function)
11162306a36Sopenharmony_ci		flen = strlen(function);
11262306a36Sopenharmony_ci	va_start(args, fmt);
11362306a36Sopenharmony_ci	vaf.fmt = fmt;
11462306a36Sopenharmony_ci	vaf.va = &args;
11562306a36Sopenharmony_ci	pr_debug("(%s, %d): %s(): %pV", file, line, flen ? function : "", &vaf);
11662306a36Sopenharmony_ci	va_end(args);
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/* Dump a runlist. Caller has to provide synchronisation for @rl. */
12062306a36Sopenharmony_civoid ntfs_debug_dump_runlist(const runlist_element *rl)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	int i;
12362306a36Sopenharmony_ci	const char *lcn_str[5] = { "LCN_HOLE         ", "LCN_RL_NOT_MAPPED",
12462306a36Sopenharmony_ci				   "LCN_ENOENT       ", "LCN_unknown      " };
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (!debug_msgs)
12762306a36Sopenharmony_ci		return;
12862306a36Sopenharmony_ci	pr_debug("Dumping runlist (values in hex):\n");
12962306a36Sopenharmony_ci	if (!rl) {
13062306a36Sopenharmony_ci		pr_debug("Run list not present.\n");
13162306a36Sopenharmony_ci		return;
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci	pr_debug("VCN              LCN               Run length\n");
13462306a36Sopenharmony_ci	for (i = 0; ; i++) {
13562306a36Sopenharmony_ci		LCN lcn = (rl + i)->lcn;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		if (lcn < (LCN)0) {
13862306a36Sopenharmony_ci			int index = -lcn - 1;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci			if (index > -LCN_ENOENT - 1)
14162306a36Sopenharmony_ci				index = 3;
14262306a36Sopenharmony_ci			pr_debug("%-16Lx %s %-16Lx%s\n",
14362306a36Sopenharmony_ci					(long long)(rl + i)->vcn, lcn_str[index],
14462306a36Sopenharmony_ci					(long long)(rl + i)->length,
14562306a36Sopenharmony_ci					(rl + i)->length ? "" :
14662306a36Sopenharmony_ci						" (runlist end)");
14762306a36Sopenharmony_ci		} else
14862306a36Sopenharmony_ci			pr_debug("%-16Lx %-16Lx  %-16Lx%s\n",
14962306a36Sopenharmony_ci					(long long)(rl + i)->vcn,
15062306a36Sopenharmony_ci					(long long)(rl + i)->lcn,
15162306a36Sopenharmony_ci					(long long)(rl + i)->length,
15262306a36Sopenharmony_ci					(rl + i)->length ? "" :
15362306a36Sopenharmony_ci						" (runlist end)");
15462306a36Sopenharmony_ci		if (!(rl + i)->length)
15562306a36Sopenharmony_ci			break;
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci#endif
160