aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-04-08 14:37:21 -0400
committerJan Kara <jack@suse.cz>2008-04-17 08:29:36 -0400
commitbfb257a5981af805a9394f00f75d3d9f7b611cc0 (patch)
tree2f91577f4c2a706ece3553372c737daf05885375
parentf4bcbbd92ebda971f7c2cd1132b399808ed6cf9b (diff)
udf: Add read-only support for 2.50 UDF media
This patch implements parsing of metadata partitions and reading of Metadata File thus allowing to read UDF 2.50 media. Error resilience is implemented through accessing the Metadata Mirror File in case the data the Metadata File cannot be read. The patch is based on the original patch by Sebastian Manciulea <manciuleas@yahoo.com> and Mircea Fedoreanu <mirceaf_spl@yahoo.com>. Signed-off-by: Sebastian Manciulea <manciuleas@yahoo.com> Signed-off-by: Mircea Fedoreanu <mirceaf_spl@yahoo.com> Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--fs/udf/inode.c9
-rw-r--r--fs/udf/partition.c55
-rw-r--r--fs/udf/super.c190
-rw-r--r--fs/udf/udf_sb.h16
-rw-r--r--fs/udf/udfdecl.h2
5 files changed, 258 insertions, 14 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c150b6df6261..6e151f170c08 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1301,6 +1301,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
1301 inode->i_op = &page_symlink_inode_operations; 1301 inode->i_op = &page_symlink_inode_operations;
1302 inode->i_mode = S_IFLNK | S_IRWXUGO; 1302 inode->i_mode = S_IFLNK | S_IRWXUGO;
1303 break; 1303 break;
1304 case ICBTAG_FILE_TYPE_MAIN:
1305 udf_debug("METADATA FILE-----\n");
1306 break;
1307 case ICBTAG_FILE_TYPE_MIRROR:
1308 udf_debug("METADATA MIRROR FILE-----\n");
1309 break;
1310 case ICBTAG_FILE_TYPE_BITMAP:
1311 udf_debug("METADATA BITMAP FILE-----\n");
1312 break;
1304 default: 1313 default:
1305 printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown " 1314 printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
1306 "file type=%d\n", inode->i_ino, 1315 "file type=%d\n", inode->i_ino,
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
index b2e6e1eddb90..2dfe4be2eeb2 100644
--- a/fs/udf/partition.c
+++ b/fs/udf/partition.c
@@ -266,3 +266,58 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
266 266
267 return 0; 267 return 0;
268} 268}
269
270static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
271 uint16_t partition, uint32_t offset)
272{
273 struct super_block *sb = inode->i_sb;
274 struct udf_part_map *map;
275 kernel_lb_addr eloc;
276 uint32_t elen;
277 sector_t ext_offset;
278 struct extent_position epos = {};
279 uint32_t phyblock;
280
281 if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
282 (EXT_RECORDED_ALLOCATED >> 30))
283 phyblock = 0xFFFFFFFF;
284 else {
285 map = &UDF_SB(sb)->s_partmaps[partition];
286 /* map to sparable/physical partition desc */
287 phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
288 map->s_partition_num, ext_offset + offset);
289 }
290
291 brelse(epos.bh);
292 return phyblock;
293}
294
295uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
296 uint16_t partition, uint32_t offset)
297{
298 struct udf_sb_info *sbi = UDF_SB(sb);
299 struct udf_part_map *map;
300 struct udf_meta_data *mdata;
301 uint32_t retblk;
302 struct inode *inode;
303
304 udf_debug("READING from METADATA\n");
305
306 map = &sbi->s_partmaps[partition];
307 mdata = &map->s_type_specific.s_metadata;
308 inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
309
310 /* We shouldn't mount such media... */
311 BUG_ON(!inode);
312 retblk = udf_try_read_meta(inode, block, partition, offset);
313 if (retblk == 0xFFFFFFFF) {
314 udf_warning(sb, __func__, "error reading from METADATA, "
315 "trying to read from MIRROR");
316 inode = mdata->s_mirror_fe;
317 if (!inode)
318 return 0xFFFFFFFF;
319 retblk = udf_try_read_meta(inode, block, partition, offset);
320 }
321
322 return retblk;
323}
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 787cedf6cc07..29b19678327a 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -950,6 +950,101 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
950 return 0; 950 return 0;
951} 951}
952 952
953static int udf_load_metadata_files(struct super_block *sb, int partition)
954{
955 struct udf_sb_info *sbi = UDF_SB(sb);
956 struct udf_part_map *map;
957 struct udf_meta_data *mdata;
958 kernel_lb_addr addr;
959 int fe_error = 0;
960
961 map = &sbi->s_partmaps[partition];
962 mdata = &map->s_type_specific.s_metadata;
963
964 /* metadata address */
965 addr.logicalBlockNum = mdata->s_meta_file_loc;
966 addr.partitionReferenceNum = map->s_partition_num;
967
968 udf_debug("Metadata file location: block = %d part = %d\n",
969 addr.logicalBlockNum, addr.partitionReferenceNum);
970
971 mdata->s_metadata_fe = udf_iget(sb, addr);
972
973 if (mdata->s_metadata_fe == NULL) {
974 udf_warning(sb, __func__, "metadata inode efe not found, "
975 "will try mirror inode.");
976 fe_error = 1;
977 } else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type !=
978 ICBTAG_FLAG_AD_SHORT) {
979 udf_warning(sb, __func__, "metadata inode efe does not have "
980 "short allocation descriptors!");
981 fe_error = 1;
982 iput(mdata->s_metadata_fe);
983 mdata->s_metadata_fe = NULL;
984 }
985
986 /* mirror file entry */
987 addr.logicalBlockNum = mdata->s_mirror_file_loc;
988 addr.partitionReferenceNum = map->s_partition_num;
989
990 udf_debug("Mirror metadata file location: block = %d part = %d\n",
991 addr.logicalBlockNum, addr.partitionReferenceNum);
992
993 mdata->s_mirror_fe = udf_iget(sb, addr);
994
995 if (mdata->s_mirror_fe == NULL) {
996 if (fe_error) {
997 udf_error(sb, __func__, "mirror inode efe not found "
998 "and metadata inode is missing too, exiting...");
999 goto error_exit;
1000 } else
1001 udf_warning(sb, __func__, "mirror inode efe not found,"
1002 " but metadata inode is OK");
1003 } else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type !=
1004 ICBTAG_FLAG_AD_SHORT) {
1005 udf_warning(sb, __func__, "mirror inode efe does not have "
1006 "short allocation descriptors!");
1007 iput(mdata->s_mirror_fe);
1008 mdata->s_mirror_fe = NULL;
1009 if (fe_error)
1010 goto error_exit;
1011 }
1012
1013 /*
1014 * bitmap file entry
1015 * Note:
1016 * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102)
1017 */
1018 if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
1019 addr.logicalBlockNum = mdata->s_bitmap_file_loc;
1020 addr.partitionReferenceNum = map->s_partition_num;
1021
1022 udf_debug("Bitmap file location: block = %d part = %d\n",
1023 addr.logicalBlockNum, addr.partitionReferenceNum);
1024
1025 mdata->s_bitmap_fe = udf_iget(sb, addr);
1026
1027 if (mdata->s_bitmap_fe == NULL) {
1028 if (sb->s_flags & MS_RDONLY)
1029 udf_warning(sb, __func__, "bitmap inode efe "
1030 "not found but it's ok since the disc"
1031 " is mounted read-only");
1032 else {
1033 udf_error(sb, __func__, "bitmap inode efe not "
1034 "found and attempted read-write mount");
1035 goto error_exit;
1036 }
1037 }
1038 }
1039
1040 udf_debug("udf_load_metadata_files Ok\n");
1041
1042 return 0;
1043
1044error_exit:
1045 return 1;
1046}
1047
953static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, 1048static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
954 kernel_lb_addr *root) 1049 kernel_lb_addr *root)
955{ 1050{
@@ -1169,7 +1264,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
1169 p = (struct partitionDesc *)bh->b_data; 1264 p = (struct partitionDesc *)bh->b_data;
1170 partitionNumber = le16_to_cpu(p->partitionNumber); 1265 partitionNumber = le16_to_cpu(p->partitionNumber);
1171 1266
1172 /* First scan for TYPE1 and SPARABLE partitions */ 1267 /* First scan for TYPE1, SPARABLE and METADATA partitions */
1173 for (i = 0; i < sbi->s_partitions; i++) { 1268 for (i = 0; i < sbi->s_partitions; i++) {
1174 map = &sbi->s_partmaps[i]; 1269 map = &sbi->s_partmaps[i];
1175 udf_debug("Searching map: (%d == %d)\n", 1270 udf_debug("Searching map: (%d == %d)\n",
@@ -1189,8 +1284,8 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
1189 ret = udf_fill_partdesc_info(sb, p, i); 1284 ret = udf_fill_partdesc_info(sb, p, i);
1190 1285
1191 /* 1286 /*
1192 * Now rescan for VIRTUAL partitions when TYPE1 partitions are 1287 * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
1193 * already set up 1288 * PHYSICAL partitions are already set up
1194 */ 1289 */
1195 type1_idx = i; 1290 type1_idx = i;
1196 for (i = 0; i < sbi->s_partitions; i++) { 1291 for (i = 0; i < sbi->s_partitions; i++) {
@@ -1198,7 +1293,8 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
1198 1293
1199 if (map->s_partition_num == partitionNumber && 1294 if (map->s_partition_num == partitionNumber &&
1200 (map->s_partition_type == UDF_VIRTUAL_MAP15 || 1295 (map->s_partition_type == UDF_VIRTUAL_MAP15 ||
1201 map->s_partition_type == UDF_VIRTUAL_MAP20)) 1296 map->s_partition_type == UDF_VIRTUAL_MAP20 ||
1297 map->s_partition_type == UDF_METADATA_MAP25))
1202 break; 1298 break;
1203 } 1299 }
1204 1300
@@ -1208,16 +1304,28 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
1208 ret = udf_fill_partdesc_info(sb, p, i); 1304 ret = udf_fill_partdesc_info(sb, p, i);
1209 if (ret) 1305 if (ret)
1210 goto out_bh; 1306 goto out_bh;
1211 /*
1212 * Mark filesystem read-only if we have a partition with virtual map
1213 * since we don't handle writing to it (we overwrite blocks instead of
1214 * relocating them).
1215 */
1216 sb->s_flags |= MS_RDONLY;
1217 printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only because "
1218 "writing to pseudooverwrite partition is not implemented.\n");
1219 1307
1220 ret = udf_load_vat(sb, i, type1_idx); 1308 if (map->s_partition_type == UDF_METADATA_MAP25) {
1309 ret = udf_load_metadata_files(sb, i);
1310 if (ret) {
1311 printk(KERN_ERR "UDF-fs: error loading MetaData "
1312 "partition map %d\n", i);
1313 goto out_bh;
1314 }
1315 } else {
1316 ret = udf_load_vat(sb, i, type1_idx);
1317 if (ret)
1318 goto out_bh;
1319 /*
1320 * Mark filesystem read-only if we have a partition with
1321 * virtual map since we don't handle writing to it (we
1322 * overwrite blocks instead of relocating them).
1323 */
1324 sb->s_flags |= MS_RDONLY;
1325 printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only "
1326 "because writing to pseudooverwrite partition is "
1327 "not implemented.\n");
1328 }
1221out_bh: 1329out_bh:
1222 /* In case loading failed, we handle cleanup in udf_fill_super */ 1330 /* In case loading failed, we handle cleanup in udf_fill_super */
1223 brelse(bh); 1331 brelse(bh);
@@ -1316,6 +1424,50 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
1316 } 1424 }
1317 } 1425 }
1318 map->s_partition_func = udf_get_pblock_spar15; 1426 map->s_partition_func = udf_get_pblock_spar15;
1427 } else if (!strncmp(upm2->partIdent.ident,
1428 UDF_ID_METADATA,
1429 strlen(UDF_ID_METADATA))) {
1430 struct udf_meta_data *mdata =
1431 &map->s_type_specific.s_metadata;
1432 struct metadataPartitionMap *mdm =
1433 (struct metadataPartitionMap *)
1434 &(lvd->partitionMaps[offset]);
1435 udf_debug("Parsing Logical vol part %d "
1436 "type %d id=%s\n", i, type,
1437 UDF_ID_METADATA);
1438
1439 map->s_partition_type = UDF_METADATA_MAP25;
1440 map->s_partition_func = udf_get_pblock_meta25;
1441
1442 mdata->s_meta_file_loc =
1443 le32_to_cpu(mdm->metadataFileLoc);
1444 mdata->s_mirror_file_loc =
1445 le32_to_cpu(mdm->metadataMirrorFileLoc);
1446 mdata->s_bitmap_file_loc =
1447 le32_to_cpu(mdm->metadataBitmapFileLoc);
1448 mdata->s_alloc_unit_size =
1449 le32_to_cpu(mdm->allocUnitSize);
1450 mdata->s_align_unit_size =
1451 le16_to_cpu(mdm->alignUnitSize);
1452 mdata->s_dup_md_flag =
1453 mdm->flags & 0x01;
1454
1455 udf_debug("Metadata Ident suffix=0x%x\n",
1456 (le16_to_cpu(
1457 ((__le16 *)
1458 mdm->partIdent.identSuffix)[0])));
1459 udf_debug("Metadata part num=%d\n",
1460 le16_to_cpu(mdm->partitionNum));
1461 udf_debug("Metadata part alloc unit size=%d\n",
1462 le32_to_cpu(mdm->allocUnitSize));
1463 udf_debug("Metadata file loc=%d\n",
1464 le32_to_cpu(mdm->metadataFileLoc));
1465 udf_debug("Mirror file loc=%d\n",
1466 le32_to_cpu(mdm->metadataMirrorFileLoc));
1467 udf_debug("Bitmap file loc=%d\n",
1468 le32_to_cpu(mdm->metadataBitmapFileLoc));
1469 udf_debug("Duplicate Flag: %d %d\n",
1470 mdata->s_dup_md_flag, mdm->flags);
1319 } else { 1471 } else {
1320 udf_debug("Unknown ident: %s\n", 1472 udf_debug("Unknown ident: %s\n",
1321 upm2->partIdent.ident); 1473 upm2->partIdent.ident);
@@ -1677,6 +1829,7 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
1677static void udf_free_partition(struct udf_part_map *map) 1829static void udf_free_partition(struct udf_part_map *map)
1678{ 1830{
1679 int i; 1831 int i;
1832 struct udf_meta_data *mdata;
1680 1833
1681 if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) 1834 if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
1682 iput(map->s_uspace.s_table); 1835 iput(map->s_uspace.s_table);
@@ -1689,6 +1842,17 @@ static void udf_free_partition(struct udf_part_map *map)
1689 if (map->s_partition_type == UDF_SPARABLE_MAP15) 1842 if (map->s_partition_type == UDF_SPARABLE_MAP15)
1690 for (i = 0; i < 4; i++) 1843 for (i = 0; i < 4; i++)
1691 brelse(map->s_type_specific.s_sparing.s_spar_map[i]); 1844 brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
1845 else if (map->s_partition_type == UDF_METADATA_MAP25) {
1846 mdata = &map->s_type_specific.s_metadata;
1847 iput(mdata->s_metadata_fe);
1848 mdata->s_metadata_fe = NULL;
1849
1850 iput(mdata->s_mirror_fe);
1851 mdata->s_mirror_fe = NULL;
1852
1853 iput(mdata->s_bitmap_fe);
1854 mdata->s_bitmap_fe = NULL;
1855 }
1692} 1856}
1693 1857
1694static int udf_fill_super(struct super_block *sb, void *options, int silent) 1858static int udf_fill_super(struct super_block *sb, void *options, int silent)
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 8308a12e1232..1c1c514a9725 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -6,7 +6,7 @@
6/* Since UDF 2.01 is ISO 13346 based... */ 6/* Since UDF 2.01 is ISO 13346 based... */
7#define UDF_SUPER_MAGIC 0x15013346 7#define UDF_SUPER_MAGIC 0x15013346
8 8
9#define UDF_MAX_READ_VERSION 0x0201 9#define UDF_MAX_READ_VERSION 0x0250
10#define UDF_MAX_WRITE_VERSION 0x0201 10#define UDF_MAX_WRITE_VERSION 0x0201
11 11
12#define UDF_FLAG_USE_EXTENDED_FE 0 12#define UDF_FLAG_USE_EXTENDED_FE 0
@@ -46,9 +46,22 @@
46#define UDF_VIRTUAL_MAP15 0x1512U 46#define UDF_VIRTUAL_MAP15 0x1512U
47#define UDF_VIRTUAL_MAP20 0x2012U 47#define UDF_VIRTUAL_MAP20 0x2012U
48#define UDF_SPARABLE_MAP15 0x1522U 48#define UDF_SPARABLE_MAP15 0x1522U
49#define UDF_METADATA_MAP25 0x2511U
49 50
50#pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */ 51#pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */
51 52
53struct udf_meta_data {
54 __u32 s_meta_file_loc;
55 __u32 s_mirror_file_loc;
56 __u32 s_bitmap_file_loc;
57 __u32 s_alloc_unit_size;
58 __u16 s_align_unit_size;
59 __u8 s_dup_md_flag;
60 struct inode *s_metadata_fe;
61 struct inode *s_mirror_fe;
62 struct inode *s_bitmap_fe;
63};
64
52struct udf_sparing_data { 65struct udf_sparing_data {
53 __u16 s_packet_len; 66 __u16 s_packet_len;
54 struct buffer_head *s_spar_map[4]; 67 struct buffer_head *s_spar_map[4];
@@ -82,6 +95,7 @@ struct udf_part_map {
82 union { 95 union {
83 struct udf_sparing_data s_sparing; 96 struct udf_sparing_data s_sparing;
84 struct udf_virtual_data s_virtual; 97 struct udf_virtual_data s_virtual;
98 struct udf_meta_data s_metadata;
85 } s_type_specific; 99 } s_type_specific;
86 __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32); 100 __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
87 __u16 s_volumeseqnum; 101 __u16 s_volumeseqnum;
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 2cb2f5de4245..30f664ab0cd9 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -177,6 +177,8 @@ extern uint32_t udf_get_pblock_virt20(struct super_block *, uint32_t, uint16_t,
177 uint32_t); 177 uint32_t);
178extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t, 178extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t,
179 uint32_t); 179 uint32_t);
180extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t,
181 uint32_t);
180extern int udf_relocate_blocks(struct super_block *, long, long *); 182extern int udf_relocate_blocks(struct super_block *, long, long *);
181 183
182/* unicode.c */ 184/* unicode.c */