linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification
@ 2020-03-11 10:52 Tetsuhiro Kohada
  2020-03-11 10:52 ` [PATCH 2/5] staging: exfat: separate and move exFAT-mount core processing Tetsuhiro Kohada
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Tetsuhiro Kohada @ 2020-03-11 10:52 UTC (permalink / raw)
  To: Kohada.Tetsuhiro
  Cc: Mori.Takahiro, motai.hirotaka, Valdis Kletnieks,
	Greg Kroah-Hartman, linux-fsdevel, devel, linux-kernel

Redefine 'pbr_sector_t' as 'boot_sector_t' to comply with exFAT specification.
 - Redefine 'pbr_sector_t' as 'boot_sector_t'.
 - Rename variable names including 'pbr'.
 - Replace GET**()/SET**() macro with cpu_to_le**()/le**_ to_cpu().
 - Remove fs_info_t.PBR_sector (always 0).
 - Remove unused definitions.

Reviewed-by: Takahiro Mori <Mori.Takahiro@ab.MitsubishiElectric.co.jp>
Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp>
---
 drivers/staging/exfat/exfat.h       | 139 +++++++---------------------
 drivers/staging/exfat/exfat_core.c  |  62 ++++++-------
 drivers/staging/exfat/exfat_super.c |  14 ++-
 3 files changed, 65 insertions(+), 150 deletions(-)

diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
index c863d7566b57..0f730090cb30 100644
--- a/drivers/staging/exfat/exfat.h
+++ b/drivers/staging/exfat/exfat.h
@@ -35,17 +35,12 @@
 #define DENTRY_SIZE		32	/* dir entry size */
 #define DENTRY_SIZE_BITS	5
 
-/* PBR entries */
-#define PBR_SIGNATURE	0xAA55
-#define EXT_SIGNATURE	0xAA550000
-#define VOL_LABEL	"NO NAME    "	/* size should be 11 */
-#define OEM_NAME	"MSWIN4.1"	/* size should be 8 */
-#define STR_FAT12	"FAT12   "	/* size should be 8 */
-#define STR_FAT16	"FAT16   "	/* size should be 8 */
-#define STR_FAT32	"FAT32   "	/* size should be 8 */
-#define STR_EXFAT	"EXFAT   "	/* size should be 8 */
-#define VOL_CLEAN	0x0000
-#define VOL_DIRTY	0x0002
+/* exFAT: 3 Main and Backup Boot Regions */
+#define BOOT_SIGNATURE		0xAA55
+#define EXBOOT_SIGNATURE	0xAA550000
+#define STR_EXFAT		"EXFAT   "	/* size should be 8 */
+#define VOL_CLEAN		0x0000
+#define VOL_DIRTY		0x0002
 
 /* max number of clusters */
 #define FAT12_THRESHOLD		4087		/* 2^12 - 1 + 2 (clu 0 & 1) */
@@ -81,7 +76,7 @@
 
 /* checksum types */
 #define CS_DIR_ENTRY		0
-#define CS_PBR_SECTOR		1
+#define CS_BOOT_SECTOR		1
 #define CS_DEFAULT		2
 
 #define CLUSTER_16(x)		((u16)(x))
@@ -267,98 +262,29 @@ struct timestamp_t {
 	u16      year;       /* 0 ~ 127 (since 1980) */
 };
 
-/* MS_DOS FAT partition boot record (512 bytes) */
-struct pbr_sector_t {
-	u8       jmp_boot[3];
-	u8       oem_name[8];
-	u8       bpb[109];
-	u8       boot_code[390];
-	u8       signature[2];
-};
-
-/* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */
-struct bpb16_t {
-	u8       sector_size[2];
-	u8       sectors_per_clu;
-	u8       num_reserved[2];
-	u8       num_fats;
-	u8       num_root_entries[2];
-	u8       num_sectors[2];
-	u8       media_type;
-	u8       num_fat_sectors[2];
-	u8       sectors_in_track[2];
-	u8       num_heads[2];
-	u8       num_hid_sectors[4];
-	u8       num_huge_sectors[4];
-
-	u8       phy_drv_no;
-	u8       reserved;
-	u8       ext_signature;
-	u8       vol_serial[4];
-	u8       vol_label[11];
-	u8       vol_type[8];
-};
-
-/* MS-DOS FAT32 BIOS parameter block (79 bytes) */
-struct bpb32_t {
-	u8       sector_size[2];
-	u8       sectors_per_clu;
-	u8       num_reserved[2];
-	u8       num_fats;
-	u8       num_root_entries[2];
-	u8       num_sectors[2];
-	u8       media_type;
-	u8       num_fat_sectors[2];
-	u8       sectors_in_track[2];
-	u8       num_heads[2];
-	u8       num_hid_sectors[4];
-	u8       num_huge_sectors[4];
-	u8       num_fat32_sectors[4];
-	u8       ext_flags[2];
-	u8       fs_version[2];
-	u8       root_cluster[4];
-	u8       fsinfo_sector[2];
-	u8       backup_sector[2];
-	u8       reserved[12];
-
-	u8       phy_drv_no;
-	u8       ext_reserved;
-	u8       ext_signature;
-	u8       vol_serial[4];
-	u8       vol_label[11];
-	u8       vol_type[8];
-};
-
-/* MS-DOS EXFAT BIOS parameter block (109 bytes) */
-struct bpbex_t {
-	u8       reserved1[53];
-	u8       vol_offset[8];
-	u8       vol_length[8];
-	u8       fat_offset[4];
-	u8       fat_length[4];
-	u8       clu_offset[4];
-	u8       clu_count[4];
-	u8       root_cluster[4];
-	u8       vol_serial[4];
-	u8       fs_version[2];
-	u8       vol_flags[2];
-	u8       sector_size_bits;
-	u8       sectors_per_clu_bits;
-	u8       num_fats;
-	u8       phy_drv_no;
-	u8       perc_in_use;
-	u8       reserved2[7];
-};
-
-/* MS-DOS FAT file system information sector (512 bytes) */
-struct fsi_sector_t {
-	u8       signature1[4];
-	u8       reserved1[480];
-	u8       signature2[4];
-	u8       free_cluster[4];
-	u8       next_cluster[4];
-	u8       reserved2[14];
-	u8       signature3[2];
+/* exFAT: 3.1 Main and Backup Boot Sector (512 bytes) */
+struct boot_sector_t {
+	__u8	jmp_boot[3];
+	__u8	fs_name[8];
+	__u8	must_be_zero[53];
+	__le64	partition_offset;
+	__le64	vol_length;
+	__le32	fat_offset;
+	__le32	fat_length;
+	__le32	clu_offset;
+	__le32	clu_count;
+	__le32	root_cluster;
+	__le32	vol_serial;
+	__le16	fs_revision;
+	__le16	vol_flags;
+	__u8	bytes_per_sector_shift;
+	__u8	sectors_per_clu_shift;
+	__u8	num_fats;
+	__u8	drv_sel;
+	__u8	percent_in_use;
+	__u8	reserved[7];
+	__u8	boot_code[390];
+	__le16	boot_signature;
 };
 
 /* MS-DOS FAT directory entry (32 bytes) */
@@ -469,7 +395,6 @@ struct fs_info_t {
 	u32      sectors_per_clu;        /* cluster size in sectors */
 	u32      sectors_per_clu_bits;
 
-	u32      PBR_sector;             /* PBR sector */
 	u32      FAT1_start_sector;      /* FAT1 start sector */
 	u32      FAT2_start_sector;      /* FAT2 start sector */
 	u32      root_start_sector;      /* root dir start sector */
@@ -481,7 +406,7 @@ struct fs_info_t {
 	u32      dentries_per_clu;       /* num of dentries per cluster */
 
 	u32      vol_flag;               /* volume dirty flag */
-	struct buffer_head *pbr_bh;         /* PBR sector */
+	struct buffer_head *boot_bh;     /* BOOT sector */
 
 	u32      map_clu;                /* allocation bitmap start cluster */
 	u32      map_sectors;            /* num of allocation bitmap sectors */
@@ -691,7 +616,7 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
 		 struct uni_name_t *p_uniname);
 
 /* file operation functions */
-s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
+s32 exfat_mount(struct super_block *sb, struct boot_sector_t *p_boot);
 s32 create_dir(struct inode *inode, struct chain_t *p_dir,
 	       struct uni_name_t *p_uniname, struct file_id_t *fid);
 s32 create_file(struct inode *inode, struct chain_t *p_dir,
diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
index 374a4fe183f5..ca1039b7977c 100644
--- a/drivers/staging/exfat/exfat_core.c
+++ b/drivers/staging/exfat/exfat_core.c
@@ -81,8 +81,7 @@ static inline void exfat_bitmap_clear(u8 *bitmap, int i)
 
 void fs_set_vol_flags(struct super_block *sb, u32 new_flag)
 {
-	struct pbr_sector_t *p_pbr;
-	struct bpbex_t *p_bpb;
+	struct boot_sector_t *p_boot;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 
 	if (p_fs->vol_flag == new_flag)
@@ -90,23 +89,21 @@ void fs_set_vol_flags(struct super_block *sb, u32 new_flag)
 
 	p_fs->vol_flag = new_flag;
 
-	if (!p_fs->pbr_bh) {
-		if (sector_read(sb, p_fs->PBR_sector,
-				&p_fs->pbr_bh, 1) != 0)
+	if (!p_fs->boot_bh) {
+		if (sector_read(sb, 0, &p_fs->boot_bh, 1) != 0)
 			return;
 	}
 
-	p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data;
-	p_bpb = (struct bpbex_t *)p_pbr->bpb;
-	SET16(p_bpb->vol_flags, (u16)new_flag);
+	p_boot = (struct boot_sector_t *)p_fs->boot_bh->b_data;
+	p_boot->vol_flags = cpu_to_le16(new_flag);
 
 	/* XXX duyoung
 	 * what can we do here? (cuz fs_set_vol_flags() is void)
 	 */
-	if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
-		sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
+	if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->boot_bh)))
+		sector_write(sb, 0, p_fs->boot_bh, 1);
 	else
-		sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
+		sector_write(sb, 0, p_fs->boot_bh, 0);
 }
 
 void fs_error(struct super_block *sb)
@@ -535,7 +532,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
 					}
 				}
 
-				p_fs->pbr_bh = NULL;
+				p_fs->boot_bh = NULL;
 				return 0;
 			}
 		}
@@ -552,7 +549,7 @@ void free_alloc_bitmap(struct super_block *sb)
 	int i;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 
-	brelse(p_fs->pbr_bh);
+	brelse(p_fs->boot_bh);
 
 	for (i = 0; i < p_fs->map_sectors; i++)
 		__brelse(p_fs->vol_amap[i]);
@@ -2063,45 +2060,44 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
 	return 0;
 }
 
-s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+s32 exfat_mount(struct super_block *sb, struct boot_sector_t *p_boot)
 {
-	struct bpbex_t *p_bpb = (struct bpbex_t *)p_pbr->bpb;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
 
-	if (p_bpb->num_fats == 0)
+	if (p_boot->num_fats == 0)
 		return -EFSCORRUPTED;
 
-	p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits;
-	p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits;
+	p_fs->sectors_per_clu = 1 << p_boot->sectors_per_clu_shift;
+	p_fs->sectors_per_clu_bits = p_boot->sectors_per_clu_shift;
 	p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
 				  p_bd->sector_size_bits;
 	p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
 
-	p_fs->num_FAT_sectors = GET32(p_bpb->fat_length);
+	p_fs->num_FAT_sectors = le32_to_cpu(p_boot->fat_length);
 
-	p_fs->FAT1_start_sector = p_fs->PBR_sector + GET32(p_bpb->fat_offset);
-	if (p_bpb->num_fats == 1)
+	p_fs->FAT1_start_sector = le32_to_cpu(p_boot->fat_offset);
+	if (p_boot->num_fats == 1)
 		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
 	else
 		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
 					  p_fs->num_FAT_sectors;
 
-	p_fs->root_start_sector = p_fs->PBR_sector + GET32(p_bpb->clu_offset);
+	p_fs->root_start_sector = le32_to_cpu(p_boot->clu_offset);
 	p_fs->data_start_sector = p_fs->root_start_sector;
 
-	p_fs->num_sectors = GET64(p_bpb->vol_length);
-	p_fs->num_clusters = GET32(p_bpb->clu_count) + 2;
+	p_fs->num_sectors = le64_to_cpu(p_boot->vol_length);
+	p_fs->num_clusters = le32_to_cpu(p_boot->clu_count) + 2;
 	/* because the cluster index starts with 2 */
 
-	p_fs->vol_id = GET32(p_bpb->vol_serial);
+	p_fs->vol_id = le32_to_cpu(p_boot->vol_serial);
 
-	p_fs->root_dir = GET32(p_bpb->root_cluster);
+	p_fs->root_dir = le32_to_cpu(p_boot->root_cluster);
 	p_fs->dentries_in_root = 0;
 	p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
 				       DENTRY_SIZE_BITS);
 
-	p_fs->vol_flag = (u32)GET16(p_bpb->vol_flags);
+	p_fs->vol_flag = (u32)le16_to_cpu(p_boot->vol_flags);
 	p_fs->clu_srch_ptr = 2;
 	p_fs->used_clusters = UINT_MAX;
 
@@ -2431,8 +2427,7 @@ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
 	s32 ret = -EIO;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 
-	if ((sec >= (p_fs->PBR_sector + p_fs->num_sectors)) &&
-	    (p_fs->num_sectors > 0)) {
+	if ((sec >= p_fs->num_sectors) && (p_fs->num_sectors > 0)) {
 		pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n",
 		       __func__, (unsigned long long)sec);
 		fs_error(sb);
@@ -2454,8 +2449,7 @@ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
 	s32 ret = -EIO;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 
-	if (sec >= (p_fs->PBR_sector + p_fs->num_sectors) &&
-	    (p_fs->num_sectors > 0)) {
+	if (sec >= p_fs->num_sectors && (p_fs->num_sectors > 0)) {
 		pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n",
 		       __func__, (unsigned long long)sec);
 		fs_error(sb);
@@ -2483,8 +2477,7 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
 	s32 ret = -EIO;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 
-	if (((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors)) &&
-	    (p_fs->num_sectors > 0)) {
+	if (((sec + num_secs) > p_fs->num_sectors) && (p_fs->num_sectors > 0)) {
 		pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n",
 		       __func__, (unsigned long long)sec, num_secs);
 		fs_error(sb);
@@ -2506,8 +2499,7 @@ int multi_sector_write(struct super_block *sb, sector_t sec,
 	s32 ret = -EIO;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 
-	if ((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors) &&
-	    (p_fs->num_sectors > 0)) {
+	if ((sec + num_secs) > p_fs->num_sectors && (p_fs->num_sectors > 0)) {
 		pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n",
 		       __func__, (unsigned long long)sec, num_secs);
 		fs_error(sb);
diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
index 75813d0fe7a7..bd257d401f7b 100644
--- a/drivers/staging/exfat/exfat_super.c
+++ b/drivers/staging/exfat/exfat_super.c
@@ -344,7 +344,7 @@ static inline void exfat_save_attr(struct inode *inode, u32 attr)
 static int ffsMountVol(struct super_block *sb)
 {
 	int i, ret;
-	struct pbr_sector_t *p_pbr;
+	struct boot_sector_t *p_boot;
 	struct buffer_head *tmp_bh = NULL;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
@@ -376,12 +376,10 @@ static int ffsMountVol(struct super_block *sb)
 		goto out;
 	}
 
-	p_fs->PBR_sector = 0;
+	p_boot = (struct boot_sector_t *)tmp_bh->b_data;
 
-	p_pbr = (struct pbr_sector_t *)tmp_bh->b_data;
-
-	/* check the validity of PBR */
-	if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) {
+	/* check the validity of BOOT sector */
+	if (le16_to_cpu(p_boot->boot_signature) != BOOT_SIGNATURE) {
 		brelse(tmp_bh);
 		exfat_bdev_close(sb);
 		ret = -EFSCORRUPTED;
@@ -390,7 +388,7 @@ static int ffsMountVol(struct super_block *sb)
 
 	/* fill fs_struct */
 	for (i = 0; i < 53; i++)
-		if (p_pbr->bpb[i])
+		if (p_boot->must_be_zero[i])
 			break;
 
 	if (i < 53) {
@@ -399,7 +397,7 @@ static int ffsMountVol(struct super_block *sb)
 		pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
 		goto out;
 	} else {
-		ret = exfat_mount(sb, p_pbr);
+		ret = exfat_mount(sb, p_boot);
 	}
 
 	brelse(tmp_bh);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/5] staging: exfat: separate and move exFAT-mount core processing.
  2020-03-11 10:52 [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Tetsuhiro Kohada
@ 2020-03-11 10:52 ` Tetsuhiro Kohada
  2020-03-11 10:52 ` [PATCH 3/5] staging: exfat: consolidate boot sector analysis Tetsuhiro Kohada
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Tetsuhiro Kohada @ 2020-03-11 10:52 UTC (permalink / raw)
  To: Kohada.Tetsuhiro
  Cc: Mori.Takahiro, motai.hirotaka, Valdis Kletnieks,
	Greg Kroah-Hartman, linux-fsdevel, devel, linux-kernel

Separate the mount process related to the exFAT specification in ffsMountVol() and move it to exfat_mount.c.

 - Rename exfat_mount() to read_boot_sector().
 - Separate exFAT-mount core process and move to exfat_mount.c as NEW exfat_mount().
 - Move free_upcase_table()/free_alloc_bitmap() to exfat_mount.c as exfat_umount().
 - Change some functions to static.

This also fixes the exfat_bdev_close() leak. :-)

Reviewed-by: Takahiro Mori <Mori.Takahiro@ab.MitsubishiElectric.co.jp>
Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp>
---
 drivers/staging/exfat/exfat.h       | 11 +---
 drivers/staging/exfat/exfat_core.c  | 82 +++++++++++++++++++++++++++--
 drivers/staging/exfat/exfat_super.c | 66 ++---------------------
 3 files changed, 83 insertions(+), 76 deletions(-)

diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
index 0f730090cb30..95c2a6ef0e71 100644
--- a/drivers/staging/exfat/exfat.h
+++ b/drivers/staging/exfat/exfat.h
@@ -581,14 +581,6 @@ void fs_error(struct super_block *sb);
 s32 count_num_clusters(struct super_block *sb, struct chain_t *dir);
 void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
 
-/* allocation bitmap management functions */
-s32 load_alloc_bitmap(struct super_block *sb);
-void free_alloc_bitmap(struct super_block *sb);
-
-/* upcase table management functions */
-s32 load_upcase_table(struct super_block *sb);
-void free_upcase_table(struct super_block *sb);
-
 /* dir entry management functions */
 struct timestamp_t *tm_current(struct timestamp_t *tm);
 
@@ -616,7 +608,8 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
 		 struct uni_name_t *p_uniname);
 
 /* file operation functions */
-s32 exfat_mount(struct super_block *sb, struct boot_sector_t *p_boot);
+s32 exfat_mount(struct super_block *sb);
+void exfat_umount(struct super_block *sb);
 s32 create_dir(struct inode *inode, struct chain_t *p_dir,
 	       struct uni_name_t *p_uniname, struct file_id_t *fid);
 s32 create_file(struct inode *inode, struct chain_t *p_dir,
diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
index ca1039b7977c..2d88ce85217c 100644
--- a/drivers/staging/exfat/exfat_core.c
+++ b/drivers/staging/exfat/exfat_core.c
@@ -472,7 +472,7 @@ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len)
  *  Allocation Bitmap Management Functions
  */
 
-s32 load_alloc_bitmap(struct super_block *sb)
+static s32 load_alloc_bitmap(struct super_block *sb)
 {
 	int i, j, ret;
 	u32 map_size;
@@ -544,7 +544,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
 	return -EFSCORRUPTED;
 }
 
-void free_alloc_bitmap(struct super_block *sb)
+static void free_alloc_bitmap(struct super_block *sb)
 {
 	int i;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -561,6 +561,8 @@ void free_alloc_bitmap(struct super_block *sb)
 /*
  *  Upcase table Management Functions
  */
+static void free_upcase_table(struct super_block *sb);
+
 static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
 			       u32 num_sectors, u32 utbl_checksum)
 {
@@ -706,7 +708,7 @@ static s32 __load_default_upcase_table(struct super_block *sb)
 	return ret;
 }
 
-s32 load_upcase_table(struct super_block *sb)
+static s32 load_upcase_table(struct super_block *sb)
 {
 	int i;
 	u32 tbl_clu, tbl_size;
@@ -754,7 +756,7 @@ s32 load_upcase_table(struct super_block *sb)
 	return __load_default_upcase_table(sb);
 }
 
-void free_upcase_table(struct super_block *sb)
+static void free_upcase_table(struct super_block *sb)
 {
 	u32 i;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -2060,7 +2062,8 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
 	return 0;
 }
 
-s32 exfat_mount(struct super_block *sb, struct boot_sector_t *p_boot)
+static s32 read_boot_sector(struct super_block *sb,
+			    struct boot_sector_t *p_boot)
 {
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
@@ -2104,6 +2107,75 @@ s32 exfat_mount(struct super_block *sb, struct boot_sector_t *p_boot)
 	return 0;
 }
 
+s32 exfat_mount(struct super_block *sb)
+{
+	int i, ret;
+	struct boot_sector_t *p_boot;
+	struct buffer_head *tmp_bh = NULL;
+	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+
+	/* read Sector 0 */
+	if (sector_read(sb, 0, &tmp_bh, 1) != 0) {
+		ret = -EIO;
+		goto out;
+	}
+
+	p_boot = (struct boot_sector_t *)tmp_bh->b_data;
+
+	/* check the validity of BOOT sector */
+	if (le16_to_cpu(p_boot->boot_signature) != BOOT_SIGNATURE) {
+		brelse(tmp_bh);
+		ret = -EFSCORRUPTED;
+		goto out;
+	}
+
+	/* fill fs_struct */
+	for (i = 0; i < 53; i++)
+		if (p_boot->must_be_zero[i])
+			break;
+
+	if (i < 53) {
+		/* Not sure how we'd get here, but complain if it does */
+		ret = -EINVAL;
+		pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
+		goto out;
+	} else {
+		ret = read_boot_sector(sb, p_boot);
+	}
+
+	brelse(tmp_bh);
+
+	if (ret)
+		goto out;
+
+	ret = load_alloc_bitmap(sb);
+	if (ret)
+		goto out;
+
+	ret = load_upcase_table(sb);
+	if (ret) {
+		free_alloc_bitmap(sb);
+		goto out;
+	}
+
+	if (p_fs->dev_ejected) {
+		free_upcase_table(sb);
+		free_alloc_bitmap(sb);
+		ret = -EIO;
+		goto out;
+	}
+
+	pr_info("[EXFAT] mounted successfully\n");
+out:
+	return ret;
+}
+
+void exfat_umount(struct super_block *sb)
+{
+	free_upcase_table(sb);
+	free_alloc_bitmap(sb);
+}
+
 s32 create_dir(struct inode *inode, struct chain_t *p_dir,
 	       struct uni_name_t *p_uniname, struct file_id_t *fid)
 {
diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
index bd257d401f7b..978e1d5172ee 100644
--- a/drivers/staging/exfat/exfat_super.c
+++ b/drivers/staging/exfat/exfat_super.c
@@ -343,9 +343,7 @@ static inline void exfat_save_attr(struct inode *inode, u32 attr)
 
 static int ffsMountVol(struct super_block *sb)
 {
-	int i, ret;
-	struct boot_sector_t *p_boot;
-	struct buffer_head *tmp_bh = NULL;
+	int ret;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
 
@@ -370,66 +368,11 @@ static int ffsMountVol(struct super_block *sb)
 	if (p_bd->sector_size > sb->s_blocksize)
 		sb_set_blocksize(sb, p_bd->sector_size);
 
-	/* read Sector 0 */
-	if (sector_read(sb, 0, &tmp_bh, 1) != 0) {
-		ret = -EIO;
-		goto out;
-	}
-
-	p_boot = (struct boot_sector_t *)tmp_bh->b_data;
-
-	/* check the validity of BOOT sector */
-	if (le16_to_cpu(p_boot->boot_signature) != BOOT_SIGNATURE) {
-		brelse(tmp_bh);
-		exfat_bdev_close(sb);
-		ret = -EFSCORRUPTED;
-		goto out;
-	}
-
-	/* fill fs_struct */
-	for (i = 0; i < 53; i++)
-		if (p_boot->must_be_zero[i])
-			break;
-
-	if (i < 53) {
-		/* Not sure how we'd get here, but complain if it does */
-		ret = -EINVAL;
-		pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
-		goto out;
-	} else {
-		ret = exfat_mount(sb, p_boot);
-	}
-
-	brelse(tmp_bh);
-
-	if (ret) {
-		exfat_bdev_close(sb);
-		goto out;
-	}
-
-	ret = load_alloc_bitmap(sb);
-	if (ret) {
-		exfat_bdev_close(sb);
-		goto out;
-	}
-	ret = load_upcase_table(sb);
+	ret = exfat_mount(sb);
+out:
 	if (ret) {
-		free_alloc_bitmap(sb);
 		exfat_bdev_close(sb);
-		goto out;
 	}
-
-	if (p_fs->dev_ejected) {
-		free_upcase_table(sb);
-		free_alloc_bitmap(sb);
-		exfat_bdev_close(sb);
-		ret = -EIO;
-		goto out;
-	}
-
-	pr_info("[EXFAT] mounted successfully\n");
-
-out:
 	mutex_unlock(&z_mutex);
 
 	return ret;
@@ -450,8 +393,7 @@ static int ffsUmountVol(struct super_block *sb)
 	fs_sync(sb, true);
 	fs_set_vol_flags(sb, VOL_CLEAN);
 
-	free_upcase_table(sb);
-	free_alloc_bitmap(sb);
+	exfat_umount(sb);
 
 	exfat_fat_release_all(sb);
 	exfat_buf_release_all(sb);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/5] staging: exfat: consolidate boot sector analysis
  2020-03-11 10:52 [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Tetsuhiro Kohada
  2020-03-11 10:52 ` [PATCH 2/5] staging: exfat: separate and move exFAT-mount core processing Tetsuhiro Kohada
@ 2020-03-11 10:52 ` Tetsuhiro Kohada
  2020-03-11 10:52 ` [PATCH 4/5] staging: exfat: add boot region verification Tetsuhiro Kohada
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Tetsuhiro Kohada @ 2020-03-11 10:52 UTC (permalink / raw)
  To: Kohada.Tetsuhiro
  Cc: Mori.Takahiro, motai.hirotaka, Valdis Kletnieks,
	Greg Kroah-Hartman, linux-fsdevel, devel, linux-kernel

Consolidate boot sector analysis into read_boot_sector().

 - Move boot sector analysis from exfat_mount() to read_boot_sector().
 - Fix num_fats check in read_boot_sector().
 - Consolidate p_fs->boot_bh initialization/release into mount/umount.

This fixes vol_flags inconsistency at read failed in fs_set_vol_flags(),
and tmp_bh leak in exfat_mount(). :-)

Reviewed-by: Takahiro Mori <Mori.Takahiro@ab.MitsubishiElectric.co.jp>
Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp>
---
 drivers/staging/exfat/exfat_core.c | 106 ++++++++++++-----------------
 1 file changed, 45 insertions(+), 61 deletions(-)

diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
index 2d88ce85217c..3faa7f35c77c 100644
--- a/drivers/staging/exfat/exfat_core.c
+++ b/drivers/staging/exfat/exfat_core.c
@@ -89,11 +89,6 @@ void fs_set_vol_flags(struct super_block *sb, u32 new_flag)
 
 	p_fs->vol_flag = new_flag;
 
-	if (!p_fs->boot_bh) {
-		if (sector_read(sb, 0, &p_fs->boot_bh, 1) != 0)
-			return;
-	}
-
 	p_boot = (struct boot_sector_t *)p_fs->boot_bh->b_data;
 	p_boot->vol_flags = cpu_to_le16(new_flag);
 
@@ -531,8 +526,6 @@ static s32 load_alloc_bitmap(struct super_block *sb)
 						return ret;
 					}
 				}
-
-				p_fs->boot_bh = NULL;
 				return 0;
 			}
 		}
@@ -549,9 +542,7 @@ static void free_alloc_bitmap(struct super_block *sb)
 	int i;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 
-	brelse(p_fs->boot_bh);
-
-	for (i = 0; i < p_fs->map_sectors; i++)
+	for (i = 0; i < p_fs->map_sectors && p_fs->vol_amap; i++)
 		__brelse(p_fs->vol_amap[i]);
 
 	kfree(p_fs->vol_amap);
@@ -763,7 +754,7 @@ static void free_upcase_table(struct super_block *sb)
 	u16 **upcase_table;
 
 	upcase_table = p_fs->vol_utbl;
-	for (i = 0; i < UTBL_COL_COUNT; i++)
+	for (i = 0; i < UTBL_COL_COUNT && upcase_table; i++)
 		kfree(upcase_table[i]);
 
 	kfree(p_fs->vol_utbl);
@@ -2062,15 +2053,31 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
 	return 0;
 }
 
-static s32 read_boot_sector(struct super_block *sb,
-			    struct boot_sector_t *p_boot)
+static int read_boot_sector(struct super_block *sb)
 {
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+	struct boot_sector_t *p_boot;
+	int i;
+
+	p_boot = (struct boot_sector_t *)p_fs->boot_bh->b_data;
 
-	if (p_boot->num_fats == 0)
+	/* check the validity of BOOT sector */
+	if (le16_to_cpu(p_boot->boot_signature) != BOOT_SIGNATURE)
 		return -EFSCORRUPTED;
 
+	/* check the byte range consumed as BPB for FAT12/16/32 volumes */
+	for (i = 0; i < 53; i++) {
+		if (p_boot->must_be_zero[i]) {
+			pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
+			return -EFSCORRUPTED;
+		}
+	}
+
+	if (p_boot->num_fats != 1 && p_boot->num_fats != 2)
+		return -EFSCORRUPTED;
+
+	/* fill fs_info */
 	p_fs->sectors_per_clu = 1 << p_boot->sectors_per_clu_shift;
 	p_fs->sectors_per_clu_bits = p_boot->sectors_per_clu_shift;
 	p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
@@ -2080,11 +2087,9 @@ static s32 read_boot_sector(struct super_block *sb,
 	p_fs->num_FAT_sectors = le32_to_cpu(p_boot->fat_length);
 
 	p_fs->FAT1_start_sector = le32_to_cpu(p_boot->fat_offset);
-	if (p_boot->num_fats == 1)
-		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
-	else
-		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
-					  p_fs->num_FAT_sectors;
+	p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
+	if (p_boot->num_fats == 2)
+		p_fs->FAT2_start_sector += p_fs->num_FAT_sectors;
 
 	p_fs->root_start_sector = le32_to_cpu(p_boot->clu_offset);
 	p_fs->data_start_sector = p_fs->root_start_sector;
@@ -2109,71 +2114,50 @@ static s32 read_boot_sector(struct super_block *sb,
 
 s32 exfat_mount(struct super_block *sb)
 {
-	int i, ret;
-	struct boot_sector_t *p_boot;
-	struct buffer_head *tmp_bh = NULL;
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+	int ret;
 
-	/* read Sector 0 */
-	if (sector_read(sb, 0, &tmp_bh, 1) != 0) {
-		ret = -EIO;
-		goto out;
-	}
-
-	p_boot = (struct boot_sector_t *)tmp_bh->b_data;
-
-	/* check the validity of BOOT sector */
-	if (le16_to_cpu(p_boot->boot_signature) != BOOT_SIGNATURE) {
-		brelse(tmp_bh);
-		ret = -EFSCORRUPTED;
-		goto out;
-	}
-
-	/* fill fs_struct */
-	for (i = 0; i < 53; i++)
-		if (p_boot->must_be_zero[i])
-			break;
-
-	if (i < 53) {
-		/* Not sure how we'd get here, but complain if it does */
-		ret = -EINVAL;
-		pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
-		goto out;
-	} else {
-		ret = read_boot_sector(sb, p_boot);
-	}
+	p_fs->vol_utbl = NULL;
+	p_fs->vol_amap = NULL;
 
-	brelse(tmp_bh);
+	/* read Sector 0 */
+	ret = sector_read(sb, 0, &p_fs->boot_bh, 1);
+	if (ret)
+		goto err_out;
 
+	ret = read_boot_sector(sb);
 	if (ret)
-		goto out;
+		goto err_out;
 
 	ret = load_alloc_bitmap(sb);
 	if (ret)
-		goto out;
+		goto err_out;
 
 	ret = load_upcase_table(sb);
-	if (ret) {
-		free_alloc_bitmap(sb);
-		goto out;
-	}
+	if (ret)
+		goto err_out;
 
 	if (p_fs->dev_ejected) {
-		free_upcase_table(sb);
-		free_alloc_bitmap(sb);
 		ret = -EIO;
-		goto out;
+		goto err_out;
 	}
 
 	pr_info("[EXFAT] mounted successfully\n");
-out:
+	return 0;
+
+err_out:
+	exfat_umount(sb);
 	return ret;
 }
 
 void exfat_umount(struct super_block *sb)
 {
+	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+
 	free_upcase_table(sb);
 	free_alloc_bitmap(sb);
+	brelse(p_fs->boot_bh);
+	p_fs->boot_bh = NULL;
 }
 
 s32 create_dir(struct inode *inode, struct chain_t *p_dir,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/5] staging: exfat: add boot region verification
  2020-03-11 10:52 [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Tetsuhiro Kohada
  2020-03-11 10:52 ` [PATCH 2/5] staging: exfat: separate and move exFAT-mount core processing Tetsuhiro Kohada
  2020-03-11 10:52 ` [PATCH 3/5] staging: exfat: consolidate boot sector analysis Tetsuhiro Kohada
@ 2020-03-11 10:52 ` Tetsuhiro Kohada
  2020-03-11 10:52 ` [PATCH 5/5] staging: exfat: standardize checksum calculation Tetsuhiro Kohada
  2020-03-11 12:05 ` [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Greg Kroah-Hartman
  4 siblings, 0 replies; 6+ messages in thread
From: Tetsuhiro Kohada @ 2020-03-11 10:52 UTC (permalink / raw)
  To: Kohada.Tetsuhiro
  Cc: Mori.Takahiro, motai.hirotaka, Valdis Kletnieks,
	Greg Kroah-Hartman, linux-fsdevel, devel, linux-kernel

Add Boot-Regions verification specified in exFAT specification.

Reviewed-by: Takahiro Mori <Mori.Takahiro@ab.MitsubishiElectric.co.jp>
Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp>
---
 drivers/staging/exfat/exfat_core.c | 69 ++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
index 3faa7f35c77c..07c876bb1759 100644
--- a/drivers/staging/exfat/exfat_core.c
+++ b/drivers/staging/exfat/exfat_core.c
@@ -2017,7 +2017,20 @@ u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type)
 			chksum = (((chksum & 1) << 15) |
 				  ((chksum & 0xFFFE) >> 1)) + (u16)*c;
 	}
+	return chksum;
+}
 
+u32 calc_checksum32(void *data, int len, u32 chksum, int type)
+{
+	int i;
+	u8 *c = (u8 *)data;
+
+	for (i = 0; i < len; i++, c++) {
+		if (unlikely(type == CS_BOOT_SECTOR &&
+			     (i == 106 || i == 107 || i == 112)))
+			continue;
+		chksum = ((chksum & 1) << 31 | chksum >> 1) + (u32)*c;
+	}
 	return chksum;
 }
 
@@ -2053,6 +2066,58 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
 	return 0;
 }
 
+static int verify_boot_region(struct super_block *sb)
+{
+	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+	struct buffer_head *tmp_bh = NULL;
+	u32 chksum = 0, *p_signatue, *p_chksum;
+	int sn = 0, i, ret;
+
+	/* read boot sector sub-regions */
+	ret = sector_read(sb, sn++, &tmp_bh, 1);
+	if (ret)
+		goto out;
+
+	chksum = calc_checksum32(tmp_bh->b_data, p_bd->sector_size,
+				 chksum, CS_BOOT_SECTOR);
+
+	while (sn < 11) {
+		ret = sector_read(sb, sn++, &tmp_bh, 1);
+		if (ret)
+			goto out;
+
+		chksum = calc_checksum32(tmp_bh->b_data, p_bd->sector_size,
+					 chksum, CS_DEFAULT);
+
+		/* skip OEM Parameters & Reserved sub-regions */
+		if (sn >= 9)
+			continue;
+
+		/* extended boot sector sub-regions */
+		p_signatue = (u32 *)(tmp_bh->b_data + p_bd->sector_size - 4);
+		if (le32_to_cpu(*p_signatue) != EXBOOT_SIGNATURE) {
+			ret = -EFSCORRUPTED;
+			goto out;
+		}
+	}
+
+	/* boot checksum sub-regions */
+	ret = sector_read(sb, sn++, &tmp_bh, 1);
+	if (ret)
+		goto out;
+
+	p_chksum = (u32 *)tmp_bh->b_data;
+	for (i = 0; i < p_bd->sector_size / 4; i++) {
+		if (le32_to_cpu(*p_chksum) != chksum) {
+			ret = -EFSCORRUPTED;
+			goto out;
+		}
+	}
+out:
+	brelse(tmp_bh);
+	return ret;
+}
+
 static int read_boot_sector(struct super_block *sb)
 {
 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -2129,6 +2194,10 @@ s32 exfat_mount(struct super_block *sb)
 	if (ret)
 		goto err_out;
 
+	ret = verify_boot_region(sb);
+	if (ret)
+		goto err_out;
+
 	ret = load_alloc_bitmap(sb);
 	if (ret)
 		goto err_out;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/5] staging: exfat: standardize checksum calculation
  2020-03-11 10:52 [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Tetsuhiro Kohada
                   ` (2 preceding siblings ...)
  2020-03-11 10:52 ` [PATCH 4/5] staging: exfat: add boot region verification Tetsuhiro Kohada
@ 2020-03-11 10:52 ` Tetsuhiro Kohada
  2020-03-11 12:05 ` [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Greg Kroah-Hartman
  4 siblings, 0 replies; 6+ messages in thread
From: Tetsuhiro Kohada @ 2020-03-11 10:52 UTC (permalink / raw)
  To: Kohada.Tetsuhiro
  Cc: Mori.Takahiro, motai.hirotaka, Valdis Kletnieks,
	Greg Kroah-Hartman, linux-fsdevel, devel, linux-kernel

- Remove redundant code of calc_checksum_2byte() and rename to calc_checksum16.
- Replace checksum calculation in __load_upcase_table() with calc_checksum32().

Reviewed-by: Takahiro Mori <Mori.Takahiro@ab.MitsubishiElectric.co.jp>
Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp>
---
 drivers/staging/exfat/exfat.h      |  3 ++-
 drivers/staging/exfat/exfat_core.c | 40 ++++++++----------------------
 drivers/staging/exfat/exfat_nls.c  |  3 +--
 3 files changed, 14 insertions(+), 32 deletions(-)

diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
index 95c2a6ef0e71..4e6e6c4b20e5 100644
--- a/drivers/staging/exfat/exfat.h
+++ b/drivers/staging/exfat/exfat.h
@@ -601,7 +601,8 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir);
 /* name conversion functions */
 s32 get_num_entries(struct super_block *sb, struct chain_t *p_dir,
 		    struct uni_name_t *p_uniname, s32 *entries);
-u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
+u16 calc_checksum16(void *data, int len, u16 chksum, int type);
+u32 calc_checksum32(void *data, int len, u32 chksum, int type);
 
 /* name resolution functions */
 s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
index 07c876bb1759..d14e9b345903 100644
--- a/drivers/staging/exfat/exfat_core.c
+++ b/drivers/staging/exfat/exfat_core.c
@@ -588,14 +588,6 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
 
 		for (i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) {
 			uni = GET16(((u8 *)tmp_bh->b_data) + i);
-
-			checksum = ((checksum & 1) ? 0x80000000 : 0) +
-				   (checksum >> 1) + *(((u8 *)tmp_bh->b_data) +
-						       i);
-			checksum = ((checksum & 1) ? 0x80000000 : 0) +
-				   (checksum >> 1) + *(((u8 *)tmp_bh->b_data) +
-						       (i + 1));
-
 			if (skip) {
 				pr_debug("skip from 0x%X ", index);
 				index += uni;
@@ -626,6 +618,8 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
 				index++;
 			}
 		}
+		checksum = calc_checksum32(tmp_bh->b_data, i, checksum,
+					   CS_DEFAULT);
 	}
 	if (index >= 0xFFFF && utbl_checksum == checksum) {
 		if (tmp_bh)
@@ -1096,8 +1090,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
 	exfat_buf_lock(sb, sector);
 
 	num_entries = (s32)file_ep->num_ext + 1;
-	chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0,
-				     CS_DIR_ENTRY);
+	chksum = calc_checksum16(file_ep, DENTRY_SIZE, 0, CS_DIR_ENTRY);
 
 	for (i = 1; i < num_entries; i++) {
 		ep = get_entry_in_dir(sb, p_dir, entry + i, NULL);
@@ -1106,8 +1099,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
 			return;
 		}
 
-		chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum,
-					     CS_DEFAULT);
+		chksum = calc_checksum16(ep, DENTRY_SIZE, chksum, CS_DEFAULT);
 	}
 
 	SET16_A(file_ep->checksum, chksum);
@@ -1192,8 +1184,7 @@ void update_dir_checksum_with_entry_set(struct super_block *sb,
 	ep = (struct dentry_t *)&es->__buf;
 	for (i = 0; i < es->num_entries; i++) {
 		pr_debug("%s ep %p\n", __func__, ep);
-		chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum,
-					     chksum_type);
+		chksum = calc_checksum16(ep, DENTRY_SIZE, chksum, chksum_type);
 		ep++;
 		chksum_type = CS_DEFAULT;
 	}
@@ -1997,25 +1988,16 @@ s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
 	return (len - 1) / 15 + 3;
 }
 
-u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type)
+u16 calc_checksum16(void *data, int len, u16 chksum, int type)
 {
 	int i;
 	u8 *c = (u8 *)data;
 
-	switch (type) {
-	case CS_DIR_ENTRY:
-		for (i = 0; i < len; i++, c++) {
-			if ((i == 2) || (i == 3))
-				continue;
-			chksum = (((chksum & 1) << 15) |
-				  ((chksum & 0xFFFE) >> 1)) + (u16)*c;
-		}
-		break;
-	default
-			:
-		for (i = 0; i < len; i++, c++)
-			chksum = (((chksum & 1) << 15) |
-				  ((chksum & 0xFFFE) >> 1)) + (u16)*c;
+	for (i = 0; i < len; i++, c++) {
+		if (unlikely(type == CS_DIR_ENTRY &&
+			     (i == 2 || i == 3)))
+			continue;
+		chksum = ((chksum & 1) << 15 | chksum >> 1) + (u16)*c;
 	}
 	return chksum;
 }
diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c
index 91e8b0c4dce7..bda6613b4773 100644
--- a/drivers/staging/exfat/exfat_nls.c
+++ b/drivers/staging/exfat/exfat_nls.c
@@ -204,8 +204,7 @@ void nls_cstring_to_uniname(struct super_block *sb,
 	}
 
 	p_uniname->name_len = j;
-	p_uniname->name_hash = calc_checksum_2byte(upname, j << 1, 0,
-						   CS_DEFAULT);
+	p_uniname->name_hash = calc_checksum16(upname, j << 1, 0, CS_DEFAULT);
 
 	if (p_lossy)
 		*p_lossy = lossy;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification
  2020-03-11 10:52 [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Tetsuhiro Kohada
                   ` (3 preceding siblings ...)
  2020-03-11 10:52 ` [PATCH 5/5] staging: exfat: standardize checksum calculation Tetsuhiro Kohada
@ 2020-03-11 12:05 ` Greg Kroah-Hartman
  4 siblings, 0 replies; 6+ messages in thread
From: Greg Kroah-Hartman @ 2020-03-11 12:05 UTC (permalink / raw)
  To: Tetsuhiro Kohada
  Cc: devel, Valdis Kletnieks, motai.hirotaka, linux-kernel,
	Mori.Takahiro, linux-fsdevel

On Wed, Mar 11, 2020 at 07:52:41PM +0900, Tetsuhiro Kohada wrote:
> Redefine 'pbr_sector_t' as 'boot_sector_t' to comply with exFAT specification.
>  - Redefine 'pbr_sector_t' as 'boot_sector_t'.
>  - Rename variable names including 'pbr'.
>  - Replace GET**()/SET**() macro with cpu_to_le**()/le**_ to_cpu().
>  - Remove fs_info_t.PBR_sector (always 0).
>  - Remove unused definitions.
> 
> Reviewed-by: Takahiro Mori <Mori.Takahiro@ab.MitsubishiElectric.co.jp>
> Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp>
> ---
>  drivers/staging/exfat/exfat.h       | 139 +++++++---------------------
>  drivers/staging/exfat/exfat_core.c  |  62 ++++++-------
>  drivers/staging/exfat/exfat_super.c |  14 ++-
>  3 files changed, 65 insertions(+), 150 deletions(-)

The drivers/staging/exfat/ tree is now gone from my staging-next branch
as there is a "real" version of exfat now in linux-next from the vfs
tree.

I suggest you start working on the fs/extfat/ code.

thanks,


greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-03-11 12:05 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-11 10:52 [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Tetsuhiro Kohada
2020-03-11 10:52 ` [PATCH 2/5] staging: exfat: separate and move exFAT-mount core processing Tetsuhiro Kohada
2020-03-11 10:52 ` [PATCH 3/5] staging: exfat: consolidate boot sector analysis Tetsuhiro Kohada
2020-03-11 10:52 ` [PATCH 4/5] staging: exfat: add boot region verification Tetsuhiro Kohada
2020-03-11 10:52 ` [PATCH 5/5] staging: exfat: standardize checksum calculation Tetsuhiro Kohada
2020-03-11 12:05 ` [PATCH 1/5] staging: exfat: conform 'pbr_sector_t' definition to exFAT specification Greg Kroah-Hartman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).