summaryrefslogtreecommitdiff
path: root/fs/udf
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-04-01 18:08:51 +0200
committerJan Kara <jack@suse.cz>2008-04-17 14:23:04 +0200
commit2e0838fd0c0b8f0753a4be9af9f9712c4be881e1 (patch)
treeeacb67341a7b352bd8c29e9b36179e61a8002291 /fs/udf
parentc0eb31ed130ab18e1858179a644e39aee2355a13 (diff)
downloadlwn-2e0838fd0c0b8f0753a4be9af9f9712c4be881e1.tar.gz
lwn-2e0838fd0c0b8f0753a4be9af9f9712c4be881e1.zip
udf: Improve error recovery on mount
Report error when we fail to allocate memory for a bitmap and properly release allocated memory and inodes for all the partitions in case of mount failure and umount. Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/super.c86
1 files changed, 42 insertions, 44 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 500d1e4cc1c7..d50e3f5c46e8 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1103,16 +1103,18 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
if (phd->unallocSpaceBitmap.extLength) {
struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, i);
+ if (!bitmap) {
+ ret = 1;
+ goto out_bh;
+ }
map->s_uspace.s_bitmap = bitmap;
- if (bitmap != NULL) {
- bitmap->s_extLength = le32_to_cpu(
+ bitmap->s_extLength = le32_to_cpu(
phd->unallocSpaceBitmap.extLength);
- bitmap->s_extPosition = le32_to_cpu(
+ bitmap->s_extPosition = le32_to_cpu(
phd->unallocSpaceBitmap.extPosition);
- map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
- udf_debug("unallocSpaceBitmap (part %d) @ %d\n",
- i, bitmap->s_extPosition);
- }
+ map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
+ udf_debug("unallocSpaceBitmap (part %d) @ %d\n", i,
+ bitmap->s_extPosition);
}
if (phd->partitionIntegrityTable.extLength)
@@ -1139,19 +1141,22 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
if (phd->freedSpaceBitmap.extLength) {
struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, i);
+ if (!bitmap) {
+ ret = 1;
+ goto out_bh;
+ }
map->s_fspace.s_bitmap = bitmap;
- if (bitmap != NULL) {
- bitmap->s_extLength = le32_to_cpu(
+ bitmap->s_extLength = le32_to_cpu(
phd->freedSpaceBitmap.extLength);
- bitmap->s_extPosition = le32_to_cpu(
+ bitmap->s_extPosition = le32_to_cpu(
phd->freedSpaceBitmap.extPosition);
- map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
- udf_debug("freedSpaceBitmap (part %d) @ %d\n",
- i, bitmap->s_extPosition);
- }
+ map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
+ udf_debug("freedSpaceBitmap (part %d) @ %d\n", i,
+ bitmap->s_extPosition);
}
out_bh:
+ /* In case loading failed, we handle cleanup in udf_fill_super */
brelse(bh);
return ret;
}
@@ -1677,6 +1682,23 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
vfree(bitmap);
}
+static void udf_free_partition(struct udf_part_map *map)
+{
+ int i;
+
+ 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]);
+}
+
static int udf_fill_super(struct super_block *sb, void *options, int silent)
{
int i;
@@ -1846,21 +1868,9 @@ 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) {
- struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
- 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]);
- }
+ 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);
@@ -1912,21 +1922,9 @@ static void udf_put_super(struct super_block *sb)
sbi = UDF_SB(sb);
if (sbi->s_vat_inode)
iput(sbi->s_vat_inode);
- if (sbi->s_partitions) {
- struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
- 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]);
- }
+ 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);