[PATCH 3/5] staging: exfat: consolidate boot sector analysis

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
---
 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

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel



[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux