Hello!
I tested current kernel 5.8 on MIPS BE CPU, and found that name_hash
field of directory entry is computed incorrectly due to lack of
endianess conversion.
It leads to errors in directories listing and opening files:
~# ls /mnt/sda1/
ls: /mnt/sda1/System Volume Information: No such file or directory
ls: /mnt/sda1/node.exe: No such file or directory
ls: /mnt/sda1/node_etw_provider.man: No such file or directory
ls: /mnt/sda1/nodevars.bat: No such file or directory
ls: /mnt/sda1/npm: No such file or directory
ls: /mnt/sda1/npm.cmd: No such file or directory
ls: /mnt/sda1/npx: No such file or directory
ls: /mnt/sda1/npx.cmd: No such file or directory
v2:
- fixed sparse errors
sparse warnings: (new ones prefixed by >>)
>> fs/exfat/nls.c:522:27: sparse: sparse: incorrect type in assignment
(different base types) @@ expected unsigned short @@ got
restricted __le16 [usertype] @@
>> fs/exfat/nls.c:522:27: sparse: expected unsigned short
>> fs/exfat/nls.c:522:27: sparse: got restricted __le16 [usertype]
fs/exfat/nls.c:614:32: sparse: sparse: incorrect type in assignment
(different base types) @@ expected unsigned short @@ got
restricted __le16 [usertype] @@
fs/exfat/nls.c:614:32: sparse: expected unsigned short
fs/exfat/nls.c:614:32: sparse: got restricted __le16 [usertype]
Sincerely yours,
Ilya Ponetayev
>From f6d2c94c57189c162ccb531d10909d6d7f77c058 Mon Sep 17 00:00:00 2001
From: Ilya Ponetayev <i.ponetaev@xxxxxxxxxxxxxx>
Date: Tue, 7 Jul 2020 23:02:30 +0300
Subject: [PATCH] exfat: fix name_hash computation on big endian systems
On-disk format for name_hash field is LE, so it must be explicitly transformed
on BE system for proper result.
Signed-off-by: Chen Minqiang <ptpt52@xxxxxxxxx>
Signed-off-by: Ilya Ponetayev <i.ponetaev@xxxxxxxxxxxxxx>
---
nls.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/nls.c b/nls.c
index d48060a..1a70138 100644
--- a/nls.c
+++ b/nls.c
@@ -494,7 +494,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb,
struct exfat_uni_name *p_uniname, int *p_lossy)
{
int i, unilen, lossy = NLS_NAME_NO_LOSSY;
- unsigned short upname[MAX_NAME_LENGTH + 1];
+ __le16 upname[MAX_NAME_LENGTH + 1];
unsigned short *uniname = p_uniname->name;
WARN_ON(!len);
@@ -518,7 +518,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb,
exfat_wstrchr(bad_uni_chars, *uniname))
lossy |= NLS_NAME_LOSSY;
- upname[i] = exfat_toupper(sb, *uniname);
+ upname[i] = cpu_to_le16(exfat_toupper(sb, *uniname));
uniname++;
}
@@ -596,7 +596,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb,
struct exfat_uni_name *p_uniname, int *p_lossy)
{
int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY;
- unsigned short upname[MAX_NAME_LENGTH + 1];
+ __le16 upname[MAX_NAME_LENGTH + 1];
unsigned short *uniname = p_uniname->name;
struct nls_table *nls = EXFAT_SB(sb)->nls_io;
@@ -610,7 +610,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb,
exfat_wstrchr(bad_uni_chars, *uniname))
lossy |= NLS_NAME_LOSSY;
- upname[unilen] = exfat_toupper(sb, *uniname);
+ upname[unilen] = cpu_to_le16(exfat_toupper(sb, *uniname));
uniname++;
unilen++;
}