mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 12:21:37 +00:00
udf: Fix memory leak when mounting
When we are mounting filesystem, we can load one partition table before finding out that we cannot complete processing of logical volume descriptor and trying the reserve descriptor. Free the table properly before trying the reserve descriptor. Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
e124a32043
commit
bff943af6f
122
fs/udf/super.c
122
fs/udf/super.c
@ -252,6 +252,63 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
|
||||
{
|
||||
int i;
|
||||
int nr_groups = bitmap->s_nr_groups;
|
||||
int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) *
|
||||
nr_groups);
|
||||
|
||||
for (i = 0; i < nr_groups; i++)
|
||||
if (bitmap->s_block_bitmap[i])
|
||||
brelse(bitmap->s_block_bitmap[i]);
|
||||
|
||||
if (size <= PAGE_SIZE)
|
||||
kfree(bitmap);
|
||||
else
|
||||
vfree(bitmap);
|
||||
}
|
||||
|
||||
static void udf_free_partition(struct udf_part_map *map)
|
||||
{
|
||||
int i;
|
||||
struct udf_meta_data *mdata;
|
||||
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
|
||||
iput(map->s_uspace.s_table);
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
|
||||
iput(map->s_fspace.s_table);
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
|
||||
udf_sb_free_bitmap(map->s_uspace.s_bitmap);
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
|
||||
udf_sb_free_bitmap(map->s_fspace.s_bitmap);
|
||||
if (map->s_partition_type == UDF_SPARABLE_MAP15)
|
||||
for (i = 0; i < 4; i++)
|
||||
brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
|
||||
else if (map->s_partition_type == UDF_METADATA_MAP25) {
|
||||
mdata = &map->s_type_specific.s_metadata;
|
||||
iput(mdata->s_metadata_fe);
|
||||
mdata->s_metadata_fe = NULL;
|
||||
|
||||
iput(mdata->s_mirror_fe);
|
||||
mdata->s_mirror_fe = NULL;
|
||||
|
||||
iput(mdata->s_bitmap_fe);
|
||||
mdata->s_bitmap_fe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void udf_sb_free_partitions(struct super_block *sb)
|
||||
{
|
||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sbi->s_partitions; i++)
|
||||
udf_free_partition(&sbi->s_partmaps[i]);
|
||||
kfree(sbi->s_partmaps);
|
||||
sbi->s_partmaps = NULL;
|
||||
}
|
||||
|
||||
static int udf_show_options(struct seq_file *seq, struct dentry *root)
|
||||
{
|
||||
struct super_block *sb = root->d_sb;
|
||||
@ -1596,7 +1653,11 @@ static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
|
||||
/* responsible for finding the PartitionDesc(s) */
|
||||
if (!udf_process_sequence(sb, main_s, main_e, fileset))
|
||||
return 1;
|
||||
return !udf_process_sequence(sb, reserve_s, reserve_e, fileset);
|
||||
udf_sb_free_partitions(sb);
|
||||
if (!udf_process_sequence(sb, reserve_s, reserve_e, fileset))
|
||||
return 1;
|
||||
udf_sb_free_partitions(sb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1861,55 +1922,8 @@ u64 lvid_get_unique_id(struct super_block *sb)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
|
||||
{
|
||||
int i;
|
||||
int nr_groups = bitmap->s_nr_groups;
|
||||
int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) *
|
||||
nr_groups);
|
||||
|
||||
for (i = 0; i < nr_groups; i++)
|
||||
if (bitmap->s_block_bitmap[i])
|
||||
brelse(bitmap->s_block_bitmap[i]);
|
||||
|
||||
if (size <= PAGE_SIZE)
|
||||
kfree(bitmap);
|
||||
else
|
||||
vfree(bitmap);
|
||||
}
|
||||
|
||||
static void udf_free_partition(struct udf_part_map *map)
|
||||
{
|
||||
int i;
|
||||
struct udf_meta_data *mdata;
|
||||
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
|
||||
iput(map->s_uspace.s_table);
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
|
||||
iput(map->s_fspace.s_table);
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
|
||||
udf_sb_free_bitmap(map->s_uspace.s_bitmap);
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
|
||||
udf_sb_free_bitmap(map->s_fspace.s_bitmap);
|
||||
if (map->s_partition_type == UDF_SPARABLE_MAP15)
|
||||
for (i = 0; i < 4; i++)
|
||||
brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
|
||||
else if (map->s_partition_type == UDF_METADATA_MAP25) {
|
||||
mdata = &map->s_type_specific.s_metadata;
|
||||
iput(mdata->s_metadata_fe);
|
||||
mdata->s_metadata_fe = NULL;
|
||||
|
||||
iput(mdata->s_mirror_fe);
|
||||
mdata->s_mirror_fe = NULL;
|
||||
|
||||
iput(mdata->s_bitmap_fe);
|
||||
mdata->s_bitmap_fe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
struct inode *inode = NULL;
|
||||
struct udf_options uopt;
|
||||
@ -2071,9 +2085,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
||||
error_out:
|
||||
if (sbi->s_vat_inode)
|
||||
iput(sbi->s_vat_inode);
|
||||
if (sbi->s_partitions)
|
||||
for (i = 0; i < sbi->s_partitions; i++)
|
||||
udf_free_partition(&sbi->s_partmaps[i]);
|
||||
#ifdef CONFIG_UDF_NLS
|
||||
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
|
||||
unload_nls(sbi->s_nls_map);
|
||||
@ -2081,8 +2092,7 @@ error_out:
|
||||
if (!(sb->s_flags & MS_RDONLY))
|
||||
udf_close_lvid(sb);
|
||||
brelse(sbi->s_lvid_bh);
|
||||
|
||||
kfree(sbi->s_partmaps);
|
||||
udf_sb_free_partitions(sb);
|
||||
kfree(sbi);
|
||||
sb->s_fs_info = NULL;
|
||||
|
||||
@ -2123,16 +2133,12 @@ void _udf_warn(struct super_block *sb, const char *function,
|
||||
|
||||
static void udf_put_super(struct super_block *sb)
|
||||
{
|
||||
int i;
|
||||
struct udf_sb_info *sbi;
|
||||
|
||||
sbi = UDF_SB(sb);
|
||||
|
||||
if (sbi->s_vat_inode)
|
||||
iput(sbi->s_vat_inode);
|
||||
if (sbi->s_partitions)
|
||||
for (i = 0; i < sbi->s_partitions; i++)
|
||||
udf_free_partition(&sbi->s_partmaps[i]);
|
||||
#ifdef CONFIG_UDF_NLS
|
||||
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
|
||||
unload_nls(sbi->s_nls_map);
|
||||
@ -2140,7 +2146,7 @@ static void udf_put_super(struct super_block *sb)
|
||||
if (!(sb->s_flags & MS_RDONLY))
|
||||
udf_close_lvid(sb);
|
||||
brelse(sbi->s_lvid_bh);
|
||||
kfree(sbi->s_partmaps);
|
||||
udf_sb_free_partitions(sb);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user