diff options
author | Jan Kara <jack@suse.cz> | 2007-08-31 02:56:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-08-31 04:42:22 -0400 |
commit | bcec44770cc65660369ae17b4e44be027a64a46c (patch) | |
tree | 38424fde8e60f70c3bab7180c6dd90fc027f9103 /fs/udf/super.c | |
parent | 989f89c57e6361e7d16fbd9572b5da7d313b073d (diff) |
UDF: handle wrong superblock better
If UDF superblock is incorrect, we can fail to find a table of free /
allocated space and consequently Oops. Handle this situation more
gracefully by ignoring the broken UDF partition.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r-- | fs/udf/super.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index 382be7be5ae3..c68a6e730b97 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -89,7 +89,7 @@ static int udf_find_fileset(struct super_block *, kernel_lb_addr *, | |||
89 | static void udf_load_pvoldesc(struct super_block *, struct buffer_head *); | 89 | static void udf_load_pvoldesc(struct super_block *, struct buffer_head *); |
90 | static void udf_load_fileset(struct super_block *, struct buffer_head *, | 90 | static void udf_load_fileset(struct super_block *, struct buffer_head *, |
91 | kernel_lb_addr *); | 91 | kernel_lb_addr *); |
92 | static void udf_load_partdesc(struct super_block *, struct buffer_head *); | 92 | static int udf_load_partdesc(struct super_block *, struct buffer_head *); |
93 | static void udf_open_lvid(struct super_block *); | 93 | static void udf_open_lvid(struct super_block *); |
94 | static void udf_close_lvid(struct super_block *); | 94 | static void udf_close_lvid(struct super_block *); |
95 | static unsigned int udf_count_free(struct super_block *); | 95 | static unsigned int udf_count_free(struct super_block *); |
@@ -877,7 +877,7 @@ static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, | |||
877 | root->logicalBlockNum, root->partitionReferenceNum); | 877 | root->logicalBlockNum, root->partitionReferenceNum); |
878 | } | 878 | } |
879 | 879 | ||
880 | static void udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | 880 | static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) |
881 | { | 881 | { |
882 | struct partitionDesc *p; | 882 | struct partitionDesc *p; |
883 | int i; | 883 | int i; |
@@ -912,6 +912,11 @@ static void udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
912 | 912 | ||
913 | UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table = | 913 | UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table = |
914 | udf_iget(sb, loc); | 914 | udf_iget(sb, loc); |
915 | if (!UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table) { | ||
916 | udf_debug("cannot load unallocSpaceTable (part %d)\n", | ||
917 | i); | ||
918 | return 1; | ||
919 | } | ||
915 | UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_TABLE; | 920 | UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_TABLE; |
916 | udf_debug("unallocSpaceTable (part %d) @ %ld\n", | 921 | udf_debug("unallocSpaceTable (part %d) @ %ld\n", |
917 | i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table->i_ino); | 922 | i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table->i_ino); |
@@ -938,6 +943,11 @@ static void udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
938 | 943 | ||
939 | UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table = | 944 | UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table = |
940 | udf_iget(sb, loc); | 945 | udf_iget(sb, loc); |
946 | if (!UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table) { | ||
947 | udf_debug("cannot load freedSpaceTable (part %d)\n", | ||
948 | i); | ||
949 | return 1; | ||
950 | } | ||
941 | UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_TABLE; | 951 | UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_TABLE; |
942 | udf_debug("freedSpaceTable (part %d) @ %ld\n", | 952 | udf_debug("freedSpaceTable (part %d) @ %ld\n", |
943 | i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table->i_ino); | 953 | i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table->i_ino); |
@@ -966,6 +976,7 @@ static void udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
966 | le16_to_cpu(p->partitionNumber), i, UDF_SB_PARTTYPE(sb,i), | 976 | le16_to_cpu(p->partitionNumber), i, UDF_SB_PARTTYPE(sb,i), |
967 | UDF_SB_PARTROOT(sb,i), UDF_SB_PARTLEN(sb,i)); | 977 | UDF_SB_PARTROOT(sb,i), UDF_SB_PARTLEN(sb,i)); |
968 | } | 978 | } |
979 | return 0; | ||
969 | } | 980 | } |
970 | 981 | ||
971 | static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | 982 | static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, |
@@ -1177,12 +1188,19 @@ static int udf_process_sequence(struct super_block *sb, long block, long lastblo | |||
1177 | udf_load_logicalvol(sb, bh, fileset); | 1188 | udf_load_logicalvol(sb, bh, fileset); |
1178 | } else if (i == VDS_POS_PARTITION_DESC) { | 1189 | } else if (i == VDS_POS_PARTITION_DESC) { |
1179 | struct buffer_head *bh2 = NULL; | 1190 | struct buffer_head *bh2 = NULL; |
1180 | udf_load_partdesc(sb, bh); | 1191 | if (udf_load_partdesc(sb, bh)) { |
1192 | brelse(bh); | ||
1193 | return 1; | ||
1194 | } | ||
1181 | for (j = vds[i].block + 1; j < vds[VDS_POS_TERMINATING_DESC].block; j++) { | 1195 | for (j = vds[i].block + 1; j < vds[VDS_POS_TERMINATING_DESC].block; j++) { |
1182 | bh2 = udf_read_tagged(sb, j, j, &ident); | 1196 | bh2 = udf_read_tagged(sb, j, j, &ident); |
1183 | gd = (struct generic_desc *)bh2->b_data; | 1197 | gd = (struct generic_desc *)bh2->b_data; |
1184 | if (ident == TAG_IDENT_PD) | 1198 | if (ident == TAG_IDENT_PD) |
1185 | udf_load_partdesc(sb, bh2); | 1199 | if (udf_load_partdesc(sb, bh2)) { |
1200 | brelse(bh); | ||
1201 | brelse(bh2); | ||
1202 | return 1; | ||
1203 | } | ||
1186 | brelse(bh2); | 1204 | brelse(bh2); |
1187 | } | 1205 | } |
1188 | } | 1206 | } |