[PATCH v3 11/13] smb/client: use binary search for SMB1 DOS/SRV error mapping

huiwen.he
2026-04-02T14:20:15Z

Currently, map_smb_to_linux_error() uses linear searches for both
mapping_table_ERRDOS[] and mapping_table_ERRSRV[].

Refactor this by introducing search_mapping_table_ERRDOS() and
search_mapping_table_ERRSRV() that implements binary search(as the tables
are sorted).This improves lookup performance and reduces code duplication.

Also remove the sentinel entries from the mapping tables as they are no
longer needed with ARRAY_SIZE().

Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/client/smb1maperror.c | 67 ++++++++++++++++++++----------------
1 file changed, 37 insertions(+), 30 deletions(-)

diff --git a/fs/smb/client/smb1maperror.c b/fs/smb/client/smb1maperror.c
index 294ac9646bff..28e1c84fa83b 100644
--- a/fs/smb/client/smb1maperror.c
+++ b/fs/smb/client/smb1maperror.c
@@ -9,6 +9,7 @@
* Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
*/

+#include <linux/bsearch.h>
#include "cifsproto.h"
#include "smb1proto.h"
#include "smberr.h"
@@ -20,13 +21,24 @@ struct smb_to_posix_error {
int posix_code;
};

+static __always_inline int smb1_posix_error_cmp(const void *_key, const void *_pivot)
+{
+ __u16 key = *(__u16 *)_key;
+ const struct smb_to_posix_error *pivot = _pivot;
+
+ if (key < pivot->smb_err)
+ return -1;
+ if (key > pivot->smb_err)
+ return 1;
+ return 0;
+}
+
static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
/*
* Automatically generated by the `gen_smb1_mapping` script,
* sorted by DOS error code (ascending).
*/
#include "smb1_err_dos_map.c"
- {0, 0}
};

static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
@@ -35,7 +47,6 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
* sorted by SRV error code (ascending).
*/
#include "smb1_err_srv_map.c"
- {0, 0}
};

/*****************************************************************************
@@ -72,14 +83,32 @@ search_ntstatus_to_dos_map(__u32 ntstatus)
ntstatus_to_dos_cmp);
}

+static const struct smb_to_posix_error *
+search_mapping_table_ERRDOS(__u16 smb_err)
+{
+ return __inline_bsearch(&smb_err, mapping_table_ERRDOS,
+ ARRAY_SIZE(mapping_table_ERRDOS),
+ sizeof(struct smb_to_posix_error),
+ smb1_posix_error_cmp);
+}
+
+static const struct smb_to_posix_error *
+search_mapping_table_ERRSRV(__u16 smb_err)
+{
+ return __inline_bsearch(&smb_err, mapping_table_ERRSRV,
+ ARRAY_SIZE(mapping_table_ERRSRV),
+ sizeof(struct smb_to_posix_error),
+ smb1_posix_error_cmp);
+}
+
int
map_smb_to_linux_error(char *buf, bool logErr)
{
struct smb_hdr *smb = (struct smb_hdr *)buf;
- unsigned int i;
int rc = -EIO; /* if transport error smb error may not be set */
__u8 smberrclass;
__u16 smberrcode;
+ const struct smb_to_posix_error *err_map = NULL;

/* BB if NT Status codes - map NT BB */

@@ -112,38 +141,16 @@ map_smb_to_linux_error(char *buf, bool logErr)

/* old style errors */

- /* DOS class smb error codes - map DOS */
if (smberrclass == ERRDOS) {
+ /* DOS class smb error codes - map DOS */
/* 1 byte field no need to byte reverse */
- for (i = 0;
- i <
- sizeof(mapping_table_ERRDOS) /
- sizeof(struct smb_to_posix_error); i++) {
- if (mapping_table_ERRDOS[i].smb_err == 0)
- break;
- else if (mapping_table_ERRDOS[i].smb_err ==
- smberrcode) {
- rc = mapping_table_ERRDOS[i].posix_code;
- break;
- }
- /* else try next error mapping one to see if match */
- }
+ err_map = search_mapping_table_ERRDOS(smberrcode);
} else if (smberrclass == ERRSRV) {
/* server class of error codes */
- for (i = 0;
- i <
- sizeof(mapping_table_ERRSRV) /
- sizeof(struct smb_to_posix_error); i++) {
- if (mapping_table_ERRSRV[i].smb_err == 0)
- break;
- else if (mapping_table_ERRSRV[i].smb_err ==
- smberrcode) {
- rc = mapping_table_ERRSRV[i].posix_code;
- break;
- }
- /* else try next error mapping to see if match */
- }
+ err_map = search_mapping_table_ERRSRV(smberrcode);
}
+ if (err_map)
+ rc = err_map->posix_code;
/* else ERRHRD class errors or junk - return EIO */

/* special cases for NT status codes which cannot be translated to DOS codes */
--
2.53.0