aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/super.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-04-01 10:50:35 -0400
committerJan Kara <jack@suse.cz>2008-04-17 08:23:04 -0400
commitc0eb31ed130ab18e1858179a644e39aee2355a13 (patch)
tree16ac06c5760a8e020bcf01a97af4cc2a582ff6ca /fs/udf/super.c
parentd0db181c072259c21a375b290a4574e5ce6d2b5f (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.c135
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 *);
85static int udf_check_valid(struct super_block *, int, int); 85static int udf_check_valid(struct super_block *, int, int);
86static int udf_vrs(struct super_block *sb, int silent); 86static int udf_vrs(struct super_block *sb, int silent);
87static int udf_load_partition(struct super_block *, kernel_lb_addr *); 87static int udf_load_partition(struct super_block *, kernel_lb_addr *);
88static int udf_load_logicalvol(struct super_block *, struct buffer_head *,
89 kernel_lb_addr *);
90static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); 88static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
91static void udf_find_anchor(struct super_block *); 89static void udf_find_anchor(struct super_block *);
92static int udf_find_fileset(struct super_block *, kernel_lb_addr *, 90static int udf_find_fileset(struct super_block *, kernel_lb_addr *,
93 kernel_lb_addr *); 91 kernel_lb_addr *);
94static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
95static void udf_load_fileset(struct super_block *, struct buffer_head *, 92static void udf_load_fileset(struct super_block *, struct buffer_head *,
96 kernel_lb_addr *); 93 kernel_lb_addr *);
97static int udf_load_partdesc(struct super_block *, struct buffer_head *);
98static void udf_open_lvid(struct super_block *); 94static void udf_open_lvid(struct super_block *);
99static void udf_close_lvid(struct super_block *); 95static void udf_close_lvid(struct super_block *);
100static unsigned int udf_count_free(struct super_block *); 96static 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
938static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh) 934static 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
970static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, 976static 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
1021static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) 1027static 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; 1154out_bh:
1155 brelse(bh);
1156 return ret;
1136} 1157}
1137 1158
1138static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, 1159static 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; 1275out_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;