|
Kmods SIG |
9e3ffb |
From 5875bf287d95314c58add01184f361cc5aa38429 Mon Sep 17 00:00:00 2001
|
|
Kmods SIG |
9e3ffb |
From: Tetsuhiro Kohada <kohada.t2@gmail.com>
|
|
Kmods SIG |
9e3ffb |
Date: Fri, 29 May 2020 19:14:59 +0900
|
|
Kmods SIG |
9e3ffb |
Subject: [Backport 5875bf287d95] exfat: standardize checksum calculation
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
To clarify that it is a 16-bit checksum, the parts related to the 16-bit
|
|
Kmods SIG |
9e3ffb |
checksum are renamed and change type to u16.
|
|
Kmods SIG |
9e3ffb |
Furthermore, replace checksum calculation in exfat_load_upcase_table()
|
|
Kmods SIG |
9e3ffb |
with exfat_calc_checksum32().
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
Signed-off-by: Tetsuhiro Kohada <kohada.t2@gmail.com>
|
|
Kmods SIG |
9e3ffb |
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
|
|
Kmods SIG |
9e3ffb |
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
|
Kmods SIG |
9e3ffb |
---
|
|
Kmods SIG |
9e3ffb |
src/dir.c | 12 ++++++------
|
|
Kmods SIG |
9e3ffb |
src/exfat_fs.h | 5 ++---
|
|
Kmods SIG |
9e3ffb |
src/misc.c | 10 ++++------
|
|
Kmods SIG |
9e3ffb |
src/nls.c | 19 +++++++------------
|
|
Kmods SIG |
9e3ffb |
4 files changed, 19 insertions(+), 27 deletions(-)
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
diff --git a/src/dir.c b/src/dir.c
|
|
Kmods SIG |
9e3ffb |
index 2902d285bf20412af3a57b0e96a6768e49d6c5ac..de43534aa2997aa87994a9447f95578de9931258 100644
|
|
Kmods SIG |
9e3ffb |
--- a/src/dir.c
|
|
Kmods SIG |
9e3ffb |
+++ b/src/dir.c
|
|
Kmods SIG |
9e3ffb |
@@ -491,7 +491,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
|
|
Kmods SIG |
9e3ffb |
int ret = 0;
|
|
Kmods SIG |
9e3ffb |
int i, num_entries;
|
|
Kmods SIG |
9e3ffb |
sector_t sector;
|
|
Kmods SIG |
9e3ffb |
- unsigned short chksum;
|
|
Kmods SIG |
9e3ffb |
+ u16 chksum;
|
|
Kmods SIG |
9e3ffb |
struct exfat_dentry *ep, *fep;
|
|
Kmods SIG |
9e3ffb |
struct buffer_head *fbh, *bh;
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
@@ -500,7 +500,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
|
|
Kmods SIG |
9e3ffb |
return -EIO;
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
num_entries = fep->dentry.file.num_ext + 1;
|
|
Kmods SIG |
9e3ffb |
- chksum = exfat_calc_chksum_2byte(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY);
|
|
Kmods SIG |
9e3ffb |
+ chksum = exfat_calc_chksum16(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY);
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
for (i = 1; i < num_entries; i++) {
|
|
Kmods SIG |
9e3ffb |
ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, NULL);
|
|
Kmods SIG |
9e3ffb |
@@ -508,7 +508,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
|
|
Kmods SIG |
9e3ffb |
ret = -EIO;
|
|
Kmods SIG |
9e3ffb |
goto release_fbh;
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
- chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum,
|
|
Kmods SIG |
9e3ffb |
+ chksum = exfat_calc_chksum16(ep, DENTRY_SIZE, chksum,
|
|
Kmods SIG |
9e3ffb |
CS_DEFAULT);
|
|
Kmods SIG |
9e3ffb |
brelse(bh);
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
@@ -593,8 +593,8 @@ void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es)
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
for (i = 0; i < es->num_entries; i++) {
|
|
Kmods SIG |
9e3ffb |
ep = exfat_get_dentry_cached(es, i);
|
|
Kmods SIG |
9e3ffb |
- chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum,
|
|
Kmods SIG |
9e3ffb |
- chksum_type);
|
|
Kmods SIG |
9e3ffb |
+ chksum = exfat_calc_chksum16(ep, DENTRY_SIZE, chksum,
|
|
Kmods SIG |
9e3ffb |
+ chksum_type);
|
|
Kmods SIG |
9e3ffb |
chksum_type = CS_DEFAULT;
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
ep = exfat_get_dentry_cached(es, 0);
|
|
Kmods SIG |
9e3ffb |
@@ -1000,7 +1000,7 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
if (entry_type == TYPE_STREAM) {
|
|
Kmods SIG |
9e3ffb |
- unsigned short name_hash;
|
|
Kmods SIG |
9e3ffb |
+ u16 name_hash;
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
if (step != DIRENT_STEP_STRM) {
|
|
Kmods SIG |
9e3ffb |
step = DIRENT_STEP_FILE;
|
|
Kmods SIG |
9e3ffb |
diff --git a/src/exfat_fs.h b/src/exfat_fs.h
|
|
Kmods SIG |
9e3ffb |
index 8c2a70bfaa10d4743c46aad74254e363d4079c74..595f3117f4924893a07eba48b55ef3d7d6edbee6 100644
|
|
Kmods SIG |
9e3ffb |
--- a/src/exfat_fs.h
|
|
Kmods SIG |
9e3ffb |
+++ b/src/exfat_fs.h
|
|
Kmods SIG |
9e3ffb |
@@ -137,7 +137,7 @@ struct exfat_dentry_namebuf {
|
|
Kmods SIG |
9e3ffb |
struct exfat_uni_name {
|
|
Kmods SIG |
9e3ffb |
/* +3 for null and for converting */
|
|
Kmods SIG |
9e3ffb |
unsigned short name[MAX_NAME_LENGTH + 3];
|
|
Kmods SIG |
9e3ffb |
- unsigned short name_hash;
|
|
Kmods SIG |
9e3ffb |
+ u16 name_hash;
|
|
Kmods SIG |
9e3ffb |
unsigned char name_len;
|
|
Kmods SIG |
9e3ffb |
};
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
@@ -512,8 +512,7 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
|
Kmods SIG |
9e3ffb |
void exfat_truncate_atime(struct timespec64 *ts);
|
|
Kmods SIG |
9e3ffb |
void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
|
Kmods SIG |
9e3ffb |
u8 *tz, __le16 *time, __le16 *date, u8 *time_cs);
|
|
Kmods SIG |
9e3ffb |
-unsigned short exfat_calc_chksum_2byte(void *data, int len,
|
|
Kmods SIG |
9e3ffb |
- unsigned short chksum, int type);
|
|
Kmods SIG |
9e3ffb |
+u16 exfat_calc_chksum16(void *data, int len, u16 chksum, int type);
|
|
Kmods SIG |
9e3ffb |
u32 exfat_calc_chksum32(void *data, int len, u32 chksum, int type);
|
|
Kmods SIG |
9e3ffb |
void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync);
|
|
Kmods SIG |
9e3ffb |
void exfat_chain_set(struct exfat_chain *ec, unsigned int dir,
|
|
Kmods SIG |
9e3ffb |
diff --git a/src/misc.c b/src/misc.c
|
|
Kmods SIG |
9e3ffb |
index b82d2dd5bd7cb291ffe5ed5091c9214593c32a69..17d41f3d3709287f6654dd52bd540e3f60fee285 100644
|
|
Kmods SIG |
9e3ffb |
--- a/src/misc.c
|
|
Kmods SIG |
9e3ffb |
+++ b/src/misc.c
|
|
Kmods SIG |
9e3ffb |
@@ -136,17 +136,15 @@ void exfat_truncate_atime(struct timespec64 *ts)
|
|
Kmods SIG |
9e3ffb |
ts->tv_nsec = 0;
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
-unsigned short exfat_calc_chksum_2byte(void *data, int len,
|
|
Kmods SIG |
9e3ffb |
- unsigned short chksum, int type)
|
|
Kmods SIG |
9e3ffb |
+u16 exfat_calc_chksum16(void *data, int len, u16 chksum, int type)
|
|
Kmods SIG |
9e3ffb |
{
|
|
Kmods SIG |
9e3ffb |
int i;
|
|
Kmods SIG |
9e3ffb |
- unsigned char *c = (unsigned char *)data;
|
|
Kmods SIG |
9e3ffb |
+ u8 *c = (u8 *)data;
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
for (i = 0; i < len; i++, c++) {
|
|
Kmods SIG |
9e3ffb |
- if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY))
|
|
Kmods SIG |
9e3ffb |
+ if (unlikely(type == CS_DIR_ENTRY && (i == 2 || i == 3)))
|
|
Kmods SIG |
9e3ffb |
continue;
|
|
Kmods SIG |
9e3ffb |
- chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) +
|
|
Kmods SIG |
9e3ffb |
- (unsigned short)*c;
|
|
Kmods SIG |
9e3ffb |
+ chksum = ((chksum << 15) | (chksum >> 1)) + *c;
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
return chksum;
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
diff --git a/src/nls.c b/src/nls.c
|
|
Kmods SIG |
9e3ffb |
index 1ebda90cbdd7c81c507f662332a53eb52bf92606..19321773dd078a42f8c9659e15032502b33bddcd 100644
|
|
Kmods SIG |
9e3ffb |
--- a/src/nls.c
|
|
Kmods SIG |
9e3ffb |
+++ b/src/nls.c
|
|
Kmods SIG |
9e3ffb |
@@ -527,7 +527,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb,
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
*uniname = '\0';
|
|
Kmods SIG |
9e3ffb |
p_uniname->name_len = unilen;
|
|
Kmods SIG |
9e3ffb |
- p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
|
|
Kmods SIG |
9e3ffb |
+ p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0,
|
|
Kmods SIG |
9e3ffb |
CS_DEFAULT);
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
if (p_lossy)
|
|
Kmods SIG |
9e3ffb |
@@ -623,7 +623,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb,
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
*uniname = '\0';
|
|
Kmods SIG |
9e3ffb |
p_uniname->name_len = unilen;
|
|
Kmods SIG |
9e3ffb |
- p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
|
|
Kmods SIG |
9e3ffb |
+ p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0,
|
|
Kmods SIG |
9e3ffb |
CS_DEFAULT);
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
if (p_lossy)
|
|
Kmods SIG |
9e3ffb |
@@ -655,7 +655,8 @@ static int exfat_load_upcase_table(struct super_block *sb,
|
|
Kmods SIG |
9e3ffb |
{
|
|
Kmods SIG |
9e3ffb |
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
|
Kmods SIG |
9e3ffb |
unsigned int sect_size = sb->s_blocksize;
|
|
Kmods SIG |
9e3ffb |
- unsigned int i, index = 0, checksum = 0;
|
|
Kmods SIG |
9e3ffb |
+ unsigned int i, index = 0;
|
|
Kmods SIG |
9e3ffb |
+ u32 chksum = 0;
|
|
Kmods SIG |
9e3ffb |
int ret;
|
|
Kmods SIG |
9e3ffb |
unsigned char skip = false;
|
|
Kmods SIG |
9e3ffb |
unsigned short *upcase_table;
|
|
Kmods SIG |
9e3ffb |
@@ -681,13 +682,6 @@ static int exfat_load_upcase_table(struct super_block *sb,
|
|
Kmods SIG |
9e3ffb |
for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) {
|
|
Kmods SIG |
9e3ffb |
unsigned short uni = get_unaligned_le16(bh->b_data + i);
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
- checksum = ((checksum & 1) ? 0x80000000 : 0) +
|
|
Kmods SIG |
9e3ffb |
- (checksum >> 1) +
|
|
Kmods SIG |
9e3ffb |
- *(((unsigned char *)bh->b_data) + i);
|
|
Kmods SIG |
9e3ffb |
- checksum = ((checksum & 1) ? 0x80000000 : 0) +
|
|
Kmods SIG |
9e3ffb |
- (checksum >> 1) +
|
|
Kmods SIG |
9e3ffb |
- *(((unsigned char *)bh->b_data) + (i + 1));
|
|
Kmods SIG |
9e3ffb |
-
|
|
Kmods SIG |
9e3ffb |
if (skip) {
|
|
Kmods SIG |
9e3ffb |
index += uni;
|
|
Kmods SIG |
9e3ffb |
skip = false;
|
|
Kmods SIG |
9e3ffb |
@@ -701,13 +695,14 @@ static int exfat_load_upcase_table(struct super_block *sb,
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
brelse(bh);
|
|
Kmods SIG |
9e3ffb |
+ chksum = exfat_calc_chksum32(bh->b_data, i, chksum, CS_DEFAULT);
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
- if (index >= 0xFFFF && utbl_checksum == checksum)
|
|
Kmods SIG |
9e3ffb |
+ if (index >= 0xFFFF && utbl_checksum == chksum)
|
|
Kmods SIG |
9e3ffb |
return 0;
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
exfat_err(sb, "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)",
|
|
Kmods SIG |
9e3ffb |
- index, checksum, utbl_checksum);
|
|
Kmods SIG |
9e3ffb |
+ index, chksum, utbl_checksum);
|
|
Kmods SIG |
9e3ffb |
ret = -EINVAL;
|
|
Kmods SIG |
9e3ffb |
free_table:
|
|
Kmods SIG |
9e3ffb |
exfat_free_upcase_table(sbi);
|
|
Kmods SIG |
9e3ffb |
--
|
|
Kmods SIG |
9e3ffb |
2.31.1
|
|
Kmods SIG |
9e3ffb |
|