From 75563adbb91d9d199b33f8b9a2fe4e9cafea6a69 Mon Sep 17 00:00:00 2001 From: ChenXiaoSong Date: Tue, 23 Dec 2025 17:24:40 +0800 Subject: [PATCH] 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: David Howells Signed-off-by: ChenXiaoSong Reviewed-by: David Howells Link: https://lore.kernel.org/linux-cifs/20260106071507.1420900-5-chenxiaosong.chenxiaosong@linux.dev/ Signed-off-by: David Howells Signed-off-by: Steve French --- fs/smb/client/smb2maperror.c | 46 ++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/fs/smb/client/smb2maperror.c b/fs/smb/client/smb2maperror.c index c36cfe707bf1..090bbd10623d 100644 --- a/fs/smb/client/smb2maperror.c +++ b/fs/smb/client/smb2maperror.c @@ -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) { - 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; - } - } + 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", + 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), -- 2.47.3