[PATCH 4/4] exfat: standardize checksum calculation

From: Tetsuhiro Kohada
Date: Mon May 25 2020 - 07:51:23 EST


To clarify that it is a 16-bit checksum, the parts related to the 16-bit
checksum are renamed and change type to u16.
Furthermore, replace checksum calculation in exfat_load_upcase_table()
with exfat_calc_checksum32().

Signed-off-by: Tetsuhiro Kohada <kohada.t2@xxxxxxxxx>
---
fs/exfat/dir.c | 12 ++++++------
fs/exfat/exfat_fs.h | 5 ++---
fs/exfat/misc.c | 10 ++++------
fs/exfat/nls.c | 19 +++++++------------
4 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index b5a237c33d50..b673362a895c 100644
--- a/fs/exfat/dir.c
+++ b/fs/exfat/dir.c
@@ -496,7 +496,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
int ret = 0;
int i, num_entries;
sector_t sector;
- unsigned short chksum;
+ u16 chksum;
struct exfat_dentry *ep, *fep;
struct buffer_head *fbh, *bh;

@@ -505,7 +505,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
return -EIO;

num_entries = fep->dentry.file.num_ext + 1;
- chksum = exfat_calc_chksum_2byte(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY);
+ chksum = exfat_calc_chksum16(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY);

for (i = 1; i < num_entries; i++) {
ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, NULL);
@@ -513,7 +513,7 @@ int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
ret = -EIO;
goto release_fbh;
}
- chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum,
+ chksum = exfat_calc_chksum16(ep, DENTRY_SIZE, chksum,
CS_DEFAULT);
brelse(bh);
}
@@ -600,10 +600,10 @@ int exfat_update_dir_chksum_with_entry_set(struct super_block *sb,
int chksum_type = CS_DIR_ENTRY, i, num_entries = es->num_entries;
unsigned int buf_off = (off - es->offset);
unsigned int remaining_byte_in_sector, copy_entries, clu;
- unsigned short chksum = 0;
+ u16 chksum = 0;

for (i = 0; i < num_entries; i++) {
- chksum = exfat_calc_chksum_2byte(&es->entries[i], DENTRY_SIZE,
+ chksum = exfat_calc_chksum16(&es->entries[i], DENTRY_SIZE,
chksum, chksum_type);
chksum_type = CS_DEFAULT;
}
@@ -1047,7 +1047,7 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
}

if (entry_type == TYPE_STREAM) {
- unsigned short name_hash;
+ u16 name_hash;

if (step != DIRENT_STEP_STRM) {
step = DIRENT_STEP_FILE;
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index 15817281b3c8..993d13bbebec 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -139,7 +139,7 @@ struct exfat_dentry_namebuf {
struct exfat_uni_name {
/* +3 for null and for converting */
unsigned short name[MAX_NAME_LENGTH + 3];
- unsigned short name_hash;
+ u16 name_hash;
unsigned char name_len;
};

@@ -515,8 +515,7 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
void exfat_truncate_atime(struct timespec64 *ts);
void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
u8 *tz, __le16 *time, __le16 *date, u8 *time_cs);
-unsigned short exfat_calc_chksum_2byte(void *data, int len,
- unsigned short chksum, int type);
+u16 exfat_calc_chksum16(void *data, int len, u16 chksum, int type);
u32 exfat_calc_chksum32(void *data, int len, u32 chksum, int type);
void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync);
void exfat_chain_set(struct exfat_chain *ec, unsigned int dir,
diff --git a/fs/exfat/misc.c b/fs/exfat/misc.c
index b82d2dd5bd7c..17d41f3d3709 100644
--- a/fs/exfat/misc.c
+++ b/fs/exfat/misc.c
@@ -136,17 +136,15 @@ void exfat_truncate_atime(struct timespec64 *ts)
ts->tv_nsec = 0;
}

-unsigned short exfat_calc_chksum_2byte(void *data, int len,
- unsigned short chksum, int type)
+u16 exfat_calc_chksum16(void *data, int len, u16 chksum, int type)
{
int i;
- unsigned char *c = (unsigned char *)data;
+ u8 *c = (u8 *)data;

for (i = 0; i < len; i++, c++) {
- if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY))
+ if (unlikely(type == CS_DIR_ENTRY && (i == 2 || i == 3)))
continue;
- chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) +
- (unsigned short)*c;
+ chksum = ((chksum << 15) | (chksum >> 1)) + *c;
}
return chksum;
}
diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
index 1ebda90cbdd7..19321773dd07 100644
--- a/fs/exfat/nls.c
+++ b/fs/exfat/nls.c
@@ -527,7 +527,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb,

*uniname = '\0';
p_uniname->name_len = unilen;
- p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
+ p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0,
CS_DEFAULT);

if (p_lossy)
@@ -623,7 +623,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb,

*uniname = '\0';
p_uniname->name_len = unilen;
- p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
+ p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0,
CS_DEFAULT);

if (p_lossy)
@@ -655,7 +655,8 @@ static int exfat_load_upcase_table(struct super_block *sb,
{
struct exfat_sb_info *sbi = EXFAT_SB(sb);
unsigned int sect_size = sb->s_blocksize;
- unsigned int i, index = 0, checksum = 0;
+ unsigned int i, index = 0;
+ u32 chksum = 0;
int ret;
unsigned char skip = false;
unsigned short *upcase_table;
@@ -681,13 +682,6 @@ static int exfat_load_upcase_table(struct super_block *sb,
for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) {
unsigned short uni = get_unaligned_le16(bh->b_data + i);

- checksum = ((checksum & 1) ? 0x80000000 : 0) +
- (checksum >> 1) +
- *(((unsigned char *)bh->b_data) + i);
- checksum = ((checksum & 1) ? 0x80000000 : 0) +
- (checksum >> 1) +
- *(((unsigned char *)bh->b_data) + (i + 1));
-
if (skip) {
index += uni;
skip = false;
@@ -701,13 +695,14 @@ static int exfat_load_upcase_table(struct super_block *sb,
}
}
brelse(bh);
+ chksum = exfat_calc_chksum32(bh->b_data, i, chksum, CS_DEFAULT);
}

- if (index >= 0xFFFF && utbl_checksum == checksum)
+ if (index >= 0xFFFF && utbl_checksum == chksum)
return 0;

exfat_err(sb, "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)",
- index, checksum, utbl_checksum);
+ index, chksum, utbl_checksum);
ret = -EINVAL;
free_table:
exfat_free_upcase_table(sbi);
--
2.25.1