Commit b0516833 authored by Tetsuhiro Kohada's avatar Tetsuhiro Kohada Committed by Namjae Jeon
Browse files

exfat: Unify access to the boot sector



Unify access to boot sector via 'sbi->pbr_bh'.
This fixes vol_flags inconsistency at read failed in fs_set_vol_flags(),
and buffer_head leak in __exfat_fill_super().

Signed-off-by: default avatarTetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp>
Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
parent cd76ac25
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -91,7 +91,6 @@ static int exfat_allocate_bitmap(struct super_block *sb,
		}
	}

	sbi->pbr_bh = NULL;
	return 0;
}

@@ -137,8 +136,6 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi)
{
	int i;

	brelse(sbi->pbr_bh);

	for (i = 0; i < sbi->map_sectors; i++)
		__brelse(sbi->vol_amap[i]);

+16 −27
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ static void exfat_put_super(struct super_block *sb)
		sync_blockdev(sb->s_bdev);
	exfat_set_vol_flags(sb, VOL_CLEAN);
	exfat_free_bitmap(sbi);
	brelse(sbi->pbr_bh);
	mutex_unlock(&sbi->s_lock);

	call_rcu(&sbi->rcu, exfat_delayed_free);
@@ -100,7 +101,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
{
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	struct pbr64 *bpb;
	struct pbr64 *bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
	bool sync = 0;

	/* flags are not changed */
@@ -115,15 +116,6 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
	if (sb_rdonly(sb))
		return 0;

	if (!sbi->pbr_bh) {
		sbi->pbr_bh = sb_bread(sb, 0);
		if (!sbi->pbr_bh) {
			exfat_msg(sb, KERN_ERR, "failed to read boot sector");
			return -ENOMEM;
		}
	}

	bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
	bpb->bsx.vol_flags = cpu_to_le16(new_flag);

	if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh))
@@ -355,10 +347,10 @@ static int exfat_read_root(struct inode *inode)
	return 0;
}

static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
		struct buffer_head **prev_bh)
static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb)
{
	struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data;
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	struct pbr *p_pbr = (struct pbr *) (sbi->pbr_bh)->b_data;
	unsigned short logical_sect = 0;

	logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits;
@@ -378,26 +370,23 @@ static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
	}

	if (logical_sect > sb->s_blocksize) {
		struct buffer_head *bh = NULL;

		__brelse(*prev_bh);
		*prev_bh = NULL;
		brelse(sbi->pbr_bh);
		sbi->pbr_bh = NULL;

		if (!sb_set_blocksize(sb, logical_sect)) {
			exfat_msg(sb, KERN_ERR,
				"unable to set blocksize %u", logical_sect);
			return NULL;
		}
		bh = sb_bread(sb, 0);
		if (!bh) {
		sbi->pbr_bh = sb_bread(sb, 0);
		if (!sbi->pbr_bh) {
			exfat_msg(sb, KERN_ERR,
				"unable to read boot sector (logical sector size = %lu)",
				sb->s_blocksize);
			return NULL;
		}

		*prev_bh = bh;
		p_pbr = (struct pbr *) bh->b_data;
		p_pbr = (struct pbr *)sbi->pbr_bh->b_data;
	}
	return p_pbr;
}
@@ -408,21 +397,20 @@ static int __exfat_fill_super(struct super_block *sb)
	int ret;
	struct pbr *p_pbr;
	struct pbr64 *p_bpb;
	struct buffer_head *bh;
	struct exfat_sb_info *sbi = EXFAT_SB(sb);

	/* set block size to read super block */
	sb_min_blocksize(sb, 512);

	/* read boot sector */
	bh = sb_bread(sb, 0);
	if (!bh) {
	sbi->pbr_bh = sb_bread(sb, 0);
	if (!sbi->pbr_bh) {
		exfat_msg(sb, KERN_ERR, "unable to read boot sector");
		return -EIO;
	}

	/* PRB is read */
	p_pbr = (struct pbr *)bh->b_data;
	p_pbr = (struct pbr *)sbi->pbr_bh->b_data;

	/* check the validity of PBR */
	if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) {
@@ -433,7 +421,7 @@ static int __exfat_fill_super(struct super_block *sb)


	/* check logical sector size */
	p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh);
	p_pbr = exfat_read_pbr_with_logical_sector(sb);
	if (!p_pbr) {
		ret = -EIO;
		goto free_bh;
@@ -514,7 +502,7 @@ static int __exfat_fill_super(struct super_block *sb)
free_upcase_table:
	exfat_free_upcase_table(sbi);
free_bh:
	brelse(bh);
	brelse(sbi->pbr_bh);
	return ret;
}

@@ -606,6 +594,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
free_table:
	exfat_free_upcase_table(sbi);
	exfat_free_bitmap(sbi);
	brelse(sbi->pbr_bh);

check_nls_io:
	unload_nls(sbi->nls_io);