diff options
author | Jan Kara <jack@suse.cz> | 2008-04-01 10:50:35 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2008-04-17 08:23:04 -0400 |
commit | c0eb31ed130ab18e1858179a644e39aee2355a13 (patch) | |
tree | 16ac06c5760a8e020bcf01a97af4cc2a582ff6ca /fs/udf/super.c | |
parent | d0db181c072259c21a375b290a4574e5ce6d2b5f (diff) |
udf: Cleanup volume descriptor sequence processing
Cleanup processing of volume descriptor sequence so that it is more readable,
make code handle errors (e.g. media problems) better.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r-- | fs/udf/super.c | 135 |
1 files changed, 81 insertions, 54 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index 137153c5005..500d1e4cc1c 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -85,16 +85,12 @@ static int udf_remount_fs(struct super_block *, int *, char *); | |||
85 | static int udf_check_valid(struct super_block *, int, int); | 85 | static int udf_check_valid(struct super_block *, int, int); |
86 | static int udf_vrs(struct super_block *sb, int silent); | 86 | static int udf_vrs(struct super_block *sb, int silent); |
87 | static int udf_load_partition(struct super_block *, kernel_lb_addr *); | 87 | static int udf_load_partition(struct super_block *, kernel_lb_addr *); |
88 | static int udf_load_logicalvol(struct super_block *, struct buffer_head *, | ||
89 | kernel_lb_addr *); | ||
90 | static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); | 88 | static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); |
91 | static void udf_find_anchor(struct super_block *); | 89 | static void udf_find_anchor(struct super_block *); |
92 | static int udf_find_fileset(struct super_block *, kernel_lb_addr *, | 90 | static int udf_find_fileset(struct super_block *, kernel_lb_addr *, |
93 | kernel_lb_addr *); | 91 | kernel_lb_addr *); |
94 | static void udf_load_pvoldesc(struct super_block *, struct buffer_head *); | ||
95 | static void udf_load_fileset(struct super_block *, struct buffer_head *, | 92 | static void udf_load_fileset(struct super_block *, struct buffer_head *, |
96 | kernel_lb_addr *); | 93 | kernel_lb_addr *); |
97 | static int udf_load_partdesc(struct super_block *, struct buffer_head *); | ||
98 | static void udf_open_lvid(struct super_block *); | 94 | static void udf_open_lvid(struct super_block *); |
99 | static void udf_close_lvid(struct super_block *); | 95 | static void udf_close_lvid(struct super_block *); |
100 | static unsigned int udf_count_free(struct super_block *); | 96 | static unsigned int udf_count_free(struct super_block *); |
@@ -935,11 +931,18 @@ static int udf_find_fileset(struct super_block *sb, | |||
935 | return 1; | 931 | return 1; |
936 | } | 932 | } |
937 | 933 | ||
938 | static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh) | 934 | static int udf_load_pvoldesc(struct super_block *sb, sector_t block) |
939 | { | 935 | { |
940 | struct primaryVolDesc *pvoldesc; | 936 | struct primaryVolDesc *pvoldesc; |
941 | struct ustr instr; | 937 | struct ustr instr; |
942 | struct ustr outstr; | 938 | struct ustr outstr; |
939 | struct buffer_head *bh; | ||
940 | uint16_t ident; | ||
941 | |||
942 | bh = udf_read_tagged(sb, block, block, &ident); | ||
943 | if (!bh) | ||
944 | return 1; | ||
945 | BUG_ON(ident != TAG_IDENT_PVD); | ||
943 | 946 | ||
944 | pvoldesc = (struct primaryVolDesc *)bh->b_data; | 947 | pvoldesc = (struct primaryVolDesc *)bh->b_data; |
945 | 948 | ||
@@ -965,6 +968,9 @@ static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh) | |||
965 | if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128)) | 968 | if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128)) |
966 | if (udf_CS0toUTF8(&outstr, &instr)) | 969 | if (udf_CS0toUTF8(&outstr, &instr)) |
967 | udf_debug("volSetIdent[] = '%s'\n", outstr.u_name); | 970 | udf_debug("volSetIdent[] = '%s'\n", outstr.u_name); |
971 | |||
972 | brelse(bh); | ||
973 | return 0; | ||
968 | } | 974 | } |
969 | 975 | ||
970 | static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, | 976 | static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, |
@@ -1018,16 +1024,27 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) | |||
1018 | return bitmap; | 1024 | return bitmap; |
1019 | } | 1025 | } |
1020 | 1026 | ||
1021 | static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | 1027 | static int udf_load_partdesc(struct super_block *sb, sector_t block) |
1022 | { | 1028 | { |
1029 | struct buffer_head *bh; | ||
1023 | struct partitionHeaderDesc *phd; | 1030 | struct partitionHeaderDesc *phd; |
1024 | struct partitionDesc *p = (struct partitionDesc *)bh->b_data; | 1031 | struct partitionDesc *p; |
1025 | struct udf_part_map *map; | 1032 | struct udf_part_map *map; |
1026 | struct udf_sb_info *sbi = UDF_SB(sb); | 1033 | struct udf_sb_info *sbi = UDF_SB(sb); |
1027 | bool found = false; | 1034 | bool found = false; |
1028 | int i; | 1035 | int i; |
1029 | u16 partitionNumber = le16_to_cpu(p->partitionNumber); | 1036 | uint16_t partitionNumber; |
1037 | uint16_t ident; | ||
1038 | int ret = 0; | ||
1039 | |||
1040 | bh = udf_read_tagged(sb, block, block, &ident); | ||
1041 | if (!bh) | ||
1042 | return 1; | ||
1043 | if (ident != TAG_IDENT_PD) | ||
1044 | goto out_bh; | ||
1030 | 1045 | ||
1046 | p = (struct partitionDesc *)bh->b_data; | ||
1047 | partitionNumber = le16_to_cpu(p->partitionNumber); | ||
1031 | for (i = 0; i < sbi->s_partitions; i++) { | 1048 | for (i = 0; i < sbi->s_partitions; i++) { |
1032 | map = &sbi->s_partmaps[i]; | 1049 | map = &sbi->s_partmaps[i]; |
1033 | udf_debug("Searching map: (%d == %d)\n", | 1050 | udf_debug("Searching map: (%d == %d)\n", |
@@ -1040,7 +1057,7 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
1040 | if (!found) { | 1057 | if (!found) { |
1041 | udf_debug("Partition (%d) not found in partition map\n", | 1058 | udf_debug("Partition (%d) not found in partition map\n", |
1042 | partitionNumber); | 1059 | partitionNumber); |
1043 | return 0; | 1060 | goto out_bh; |
1044 | } | 1061 | } |
1045 | 1062 | ||
1046 | map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */ | 1063 | map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */ |
@@ -1062,7 +1079,7 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
1062 | 1079 | ||
1063 | if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) && | 1080 | if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) && |
1064 | strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03)) | 1081 | strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03)) |
1065 | return 0; | 1082 | goto out_bh; |
1066 | 1083 | ||
1067 | phd = (struct partitionHeaderDesc *)p->partitionContentsUse; | 1084 | phd = (struct partitionHeaderDesc *)p->partitionContentsUse; |
1068 | if (phd->unallocSpaceTable.extLength) { | 1085 | if (phd->unallocSpaceTable.extLength) { |
@@ -1076,7 +1093,8 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
1076 | if (!map->s_uspace.s_table) { | 1093 | if (!map->s_uspace.s_table) { |
1077 | udf_debug("cannot load unallocSpaceTable (part %d)\n", | 1094 | udf_debug("cannot load unallocSpaceTable (part %d)\n", |
1078 | i); | 1095 | i); |
1079 | return 1; | 1096 | ret = 1; |
1097 | goto out_bh; | ||
1080 | } | 1098 | } |
1081 | map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE; | 1099 | map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE; |
1082 | udf_debug("unallocSpaceTable (part %d) @ %ld\n", | 1100 | udf_debug("unallocSpaceTable (part %d) @ %ld\n", |
@@ -1110,7 +1128,8 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
1110 | map->s_fspace.s_table = udf_iget(sb, loc); | 1128 | map->s_fspace.s_table = udf_iget(sb, loc); |
1111 | if (!map->s_fspace.s_table) { | 1129 | if (!map->s_fspace.s_table) { |
1112 | udf_debug("cannot load freedSpaceTable (part %d)\n", i); | 1130 | udf_debug("cannot load freedSpaceTable (part %d)\n", i); |
1113 | return 1; | 1131 | ret = 1; |
1132 | goto out_bh; | ||
1114 | } | 1133 | } |
1115 | 1134 | ||
1116 | map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE; | 1135 | map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE; |
@@ -1132,10 +1151,12 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | |||
1132 | } | 1151 | } |
1133 | } | 1152 | } |
1134 | 1153 | ||
1135 | return 0; | 1154 | out_bh: |
1155 | brelse(bh); | ||
1156 | return ret; | ||
1136 | } | 1157 | } |
1137 | 1158 | ||
1138 | static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | 1159 | static int udf_load_logicalvol(struct super_block *sb, sector_t block, |
1139 | kernel_lb_addr *fileset) | 1160 | kernel_lb_addr *fileset) |
1140 | { | 1161 | { |
1141 | struct logicalVolDesc *lvd; | 1162 | struct logicalVolDesc *lvd; |
@@ -1143,12 +1164,21 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1143 | uint8_t type; | 1164 | uint8_t type; |
1144 | struct udf_sb_info *sbi = UDF_SB(sb); | 1165 | struct udf_sb_info *sbi = UDF_SB(sb); |
1145 | struct genericPartitionMap *gpm; | 1166 | struct genericPartitionMap *gpm; |
1167 | uint16_t ident; | ||
1168 | struct buffer_head *bh; | ||
1169 | int ret = 0; | ||
1146 | 1170 | ||
1171 | bh = udf_read_tagged(sb, block, block, &ident); | ||
1172 | if (!bh) | ||
1173 | return 1; | ||
1174 | BUG_ON(ident != TAG_IDENT_LVD); | ||
1147 | lvd = (struct logicalVolDesc *)bh->b_data; | 1175 | lvd = (struct logicalVolDesc *)bh->b_data; |
1148 | 1176 | ||
1149 | i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); | 1177 | i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); |
1150 | if (i != 0) | 1178 | if (i != 0) { |
1151 | return i; | 1179 | ret = i; |
1180 | goto out_bh; | ||
1181 | } | ||
1152 | 1182 | ||
1153 | for (i = 0, offset = 0; | 1183 | for (i = 0, offset = 0; |
1154 | i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); | 1184 | i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); |
@@ -1187,7 +1217,6 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1187 | UDF_ID_SPARABLE, | 1217 | UDF_ID_SPARABLE, |
1188 | strlen(UDF_ID_SPARABLE))) { | 1218 | strlen(UDF_ID_SPARABLE))) { |
1189 | uint32_t loc; | 1219 | uint32_t loc; |
1190 | uint16_t ident; | ||
1191 | struct sparingTable *st; | 1220 | struct sparingTable *st; |
1192 | struct sparablePartitionMap *spm = | 1221 | struct sparablePartitionMap *spm = |
1193 | (struct sparablePartitionMap *)gpm; | 1222 | (struct sparablePartitionMap *)gpm; |
@@ -1243,7 +1272,9 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1243 | if (lvd->integritySeqExt.extLength) | 1272 | if (lvd->integritySeqExt.extLength) |
1244 | udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt)); | 1273 | udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt)); |
1245 | 1274 | ||
1246 | return 0; | 1275 | out_bh: |
1276 | brelse(bh); | ||
1277 | return ret; | ||
1247 | } | 1278 | } |
1248 | 1279 | ||
1249 | /* | 1280 | /* |
@@ -1301,19 +1332,25 @@ static noinline int udf_process_sequence(struct super_block *sb, long block, | |||
1301 | struct generic_desc *gd; | 1332 | struct generic_desc *gd; |
1302 | struct volDescPtr *vdp; | 1333 | struct volDescPtr *vdp; |
1303 | int done = 0; | 1334 | int done = 0; |
1304 | int i, j; | ||
1305 | uint32_t vdsn; | 1335 | uint32_t vdsn; |
1306 | uint16_t ident; | 1336 | uint16_t ident; |
1307 | long next_s = 0, next_e = 0; | 1337 | long next_s = 0, next_e = 0; |
1308 | 1338 | ||
1309 | memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); | 1339 | memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); |
1310 | 1340 | ||
1311 | /* Read the main descriptor sequence */ | 1341 | /* |
1342 | * Read the main descriptor sequence and find which descriptors | ||
1343 | * are in it. | ||
1344 | */ | ||
1312 | for (; (!done && block <= lastblock); block++) { | 1345 | for (; (!done && block <= lastblock); block++) { |
1313 | 1346 | ||
1314 | bh = udf_read_tagged(sb, block, block, &ident); | 1347 | bh = udf_read_tagged(sb, block, block, &ident); |
1315 | if (!bh) | 1348 | if (!bh) { |
1316 | break; | 1349 | printk(KERN_ERR "udf: Block %Lu of volume descriptor " |
1350 | "sequence is corrupted or we could not read " | ||
1351 | "it.\n", (unsigned long long)block); | ||
1352 | return 1; | ||
1353 | } | ||
1317 | 1354 | ||
1318 | /* Process each descriptor (ISO 13346 3/8.3-8.4) */ | 1355 | /* Process each descriptor (ISO 13346 3/8.3-8.4) */ |
1319 | gd = (struct generic_desc *)bh->b_data; | 1356 | gd = (struct generic_desc *)bh->b_data; |
@@ -1379,41 +1416,31 @@ static noinline int udf_process_sequence(struct super_block *sb, long block, | |||
1379 | } | 1416 | } |
1380 | brelse(bh); | 1417 | brelse(bh); |
1381 | } | 1418 | } |
1382 | for (i = 0; i < VDS_POS_LENGTH; i++) { | 1419 | /* |
1383 | if (!vds[i].block) | 1420 | * Now read interesting descriptors again and process them |
1384 | continue; | 1421 | * in a suitable order |
1422 | */ | ||
1423 | if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) { | ||
1424 | printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n"); | ||
1425 | return 1; | ||
1426 | } | ||
1427 | if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block)) | ||
1428 | return 1; | ||
1385 | 1429 | ||
1386 | bh = udf_read_tagged(sb, vds[i].block, vds[i].block, | 1430 | if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb, |
1387 | &ident); | 1431 | vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset)) |
1432 | return 1; | ||
1388 | 1433 | ||
1389 | if (i == VDS_POS_PRIMARY_VOL_DESC) | 1434 | if (vds[VDS_POS_PARTITION_DESC].block) { |
1390 | udf_load_pvoldesc(sb, bh); | 1435 | /* |
1391 | else if (i == VDS_POS_LOGICAL_VOL_DESC) { | 1436 | * We rescan the whole descriptor sequence to find |
1392 | if (udf_load_logicalvol(sb, bh, fileset)) { | 1437 | * partition descriptor blocks and process them. |
1393 | brelse(bh); | 1438 | */ |
1439 | for (block = vds[VDS_POS_PARTITION_DESC].block; | ||
1440 | block < vds[VDS_POS_TERMINATING_DESC].block; | ||
1441 | block++) | ||
1442 | if (udf_load_partdesc(sb, block)) | ||
1394 | return 1; | 1443 | return 1; |
1395 | } | ||
1396 | } else if (i == VDS_POS_PARTITION_DESC) { | ||
1397 | struct buffer_head *bh2 = NULL; | ||
1398 | if (udf_load_partdesc(sb, bh)) { | ||
1399 | brelse(bh); | ||
1400 | return 1; | ||
1401 | } | ||
1402 | for (j = vds[i].block + 1; | ||
1403 | j < vds[VDS_POS_TERMINATING_DESC].block; | ||
1404 | j++) { | ||
1405 | bh2 = udf_read_tagged(sb, j, j, &ident); | ||
1406 | gd = (struct generic_desc *)bh2->b_data; | ||
1407 | if (ident == TAG_IDENT_PD) | ||
1408 | if (udf_load_partdesc(sb, bh2)) { | ||
1409 | brelse(bh); | ||
1410 | brelse(bh2); | ||
1411 | return 1; | ||
1412 | } | ||
1413 | brelse(bh2); | ||
1414 | } | ||
1415 | } | ||
1416 | brelse(bh); | ||
1417 | } | 1444 | } |
1418 | 1445 | ||
1419 | return 0; | 1446 | return 0; |