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.takah...@ab.mitsubishielectric.co.jp>
Signed-off-by: Tetsuhiro Kohada <kohada.tetsuh...@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

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

Reply via email to