Commit 75563adb authored by ChenXiaoSong's avatar ChenXiaoSong Committed by Steve French
Browse files

smb/client: use bsearch() to find target in smb2_error_map_table



The smb2_error_map_table array currently has 1740 elements. When searching
for the last element, the original loop-based search method requires 1740
comparisons, while binary search algorithm requires only 10 comparisons.

Suggested-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarChenXiaoSong <chenxiaosong@kylinos.cn>
Reviewed-by: default avatarDavid Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/linux-cifs/20260106071507.1420900-5-chenxiaosong.chenxiaosong@linux.dev/


Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 453382f1
Loading
Loading
Loading
Loading
+34 −12
Original line number Diff line number Diff line
@@ -30,13 +30,36 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
#include "smb2_mapping_table.c"
};

static __always_inline int cmp_smb2_status(const void *_key, const void *_pivot)
{
	__u32 key = *(__u32 *)_key;
	const struct status_to_posix_error *pivot = _pivot;

	if (key < pivot->smb2_status)
		return -1;
	if (key > pivot->smb2_status)
		return 1;
	return 0;
}

static const struct status_to_posix_error *smb2_get_err_map(__u32 smb2_status)
{
	const struct status_to_posix_error *err_map;

	err_map = __inline_bsearch(&smb2_status, smb2_error_map_table,
				   ARRAY_SIZE(smb2_error_map_table),
				   sizeof(struct status_to_posix_error),
				   cmp_smb2_status);
	return err_map;
}

int
map_smb2_to_linux_error(char *buf, bool log_err)
{
	struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
	unsigned int i;
	int rc = -EIO;
	__le32 smb2err = shdr->Status;
	const struct status_to_posix_error *err_map;

	if (smb2err == 0) {
		trace_smb3_cmd_done(le32_to_cpu(shdr->Id.SyncId.TreeId),
@@ -50,21 +73,20 @@ map_smb2_to_linux_error(char *buf, bool log_err)
		   (smb2err != STATUS_END_OF_FILE)) ||
		  (cifsFYI & CIFS_RC);

	for (i = 0; i < sizeof(smb2_error_map_table) /
			sizeof(struct status_to_posix_error); i++) {
		if (smb2_error_map_table[i].smb2_status == smb2err) {
	err_map = smb2_get_err_map(le32_to_cpu(smb2err));
	if (!err_map)
		goto out;

	rc = err_map->posix_error;
	if (log_err)
				pr_notice("Status code returned 0x%08x %s\n", smb2err,
					  smb2_error_map_table[i].status_string);
			rc = smb2_error_map_table[i].posix_error;
			break;
		}
	}
		pr_notice("Status code returned 0x%08x %s\n",
			  err_map->smb2_status, err_map->status_string);

out:
	/* on error mapping not found  - return EIO */

	cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n",
		 __le32_to_cpu(smb2err), rc);
		 le32_to_cpu(smb2err), rc);

	trace_smb3_cmd_err(le32_to_cpu(shdr->Id.SyncId.TreeId),
			   le64_to_cpu(shdr->SessionId),