Commit bfb257a5981af805a9394f00f75d3d9f7b611cc0

Authored by Jan Kara
1 parent f4bcbbd92e

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>

Showing 5 changed files with 258 additions and 14 deletions Side-by-side Diff

... ... @@ -1301,6 +1301,15 @@
1301 1301 inode->i_op = &page_symlink_inode_operations;
1302 1302 inode->i_mode = S_IFLNK | S_IRWXUGO;
1303 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 1313 default:
1305 1314 printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
1306 1315 "file type=%d\n", inode->i_ino,
... ... @@ -266,4 +266,59 @@
266 266  
267 267 return 0;
268 268 }
  269 +
  270 +static 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 +
  295 +uint32_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 +}
... ... @@ -950,6 +950,101 @@
950 950 return 0;
951 951 }
952 952  
  953 +static 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 +
  1044 +error_exit:
  1045 + return 1;
  1046 +}
  1047 +
953 1048 static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
954 1049 kernel_lb_addr *root)
955 1050 {
... ... @@ -1169,7 +1264,7 @@
1169 1264 p = (struct partitionDesc *)bh->b_data;
1170 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 1268 for (i = 0; i < sbi->s_partitions; i++) {
1174 1269 map = &sbi->s_partmaps[i];
1175 1270 udf_debug("Searching map: (%d == %d)\n",
... ... @@ -1189,8 +1284,8 @@
1189 1284 ret = udf_fill_partdesc_info(sb, p, i);
1190 1285  
1191 1286 /*
1192   - * Now rescan for VIRTUAL partitions when TYPE1 partitions are
1193   - * already set up
  1287 + * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
  1288 + * PHYSICAL partitions are already set up
1194 1289 */
1195 1290 type1_idx = i;
1196 1291 for (i = 0; i < sbi->s_partitions; i++) {
... ... @@ -1198,7 +1293,8 @@
1198 1293  
1199 1294 if (map->s_partition_num == partitionNumber &&
1200 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 1298 break;
1203 1299 }
1204 1300  
1205 1301  
... ... @@ -1208,16 +1304,28 @@
1208 1304 ret = udf_fill_partdesc_info(sb, p, i);
1209 1305 if (ret)
1210 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 + }
1221 1329 out_bh:
1222 1330 /* In case loading failed, we handle cleanup in udf_fill_super */
1223 1331 brelse(bh);
... ... @@ -1316,6 +1424,50 @@
1316 1424 }
1317 1425 }
1318 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 1471 } else {
1320 1472 udf_debug("Unknown ident: %s\n",
1321 1473 upm2->partIdent.ident);
... ... @@ -1677,6 +1829,7 @@
1677 1829 static void udf_free_partition(struct udf_part_map *map)
1678 1830 {
1679 1831 int i;
  1832 + struct udf_meta_data *mdata;
1680 1833  
1681 1834 if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
1682 1835 iput(map->s_uspace.s_table);
... ... @@ -1689,6 +1842,17 @@
1689 1842 if (map->s_partition_type == UDF_SPARABLE_MAP15)
1690 1843 for (i = 0; i < 4; i++)
1691 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  
1694 1858 static int udf_fill_super(struct super_block *sb, void *options, int silent)
... ... @@ -6,7 +6,7 @@
6 6 /* Since UDF 2.01 is ISO 13346 based... */
7 7 #define UDF_SUPER_MAGIC 0x15013346
8 8  
9   -#define UDF_MAX_READ_VERSION 0x0201
  9 +#define UDF_MAX_READ_VERSION 0x0250
10 10 #define UDF_MAX_WRITE_VERSION 0x0201
11 11  
12 12 #define UDF_FLAG_USE_EXTENDED_FE 0
13 13  
... ... @@ -46,9 +46,22 @@
46 46 #define UDF_VIRTUAL_MAP15 0x1512U
47 47 #define UDF_VIRTUAL_MAP20 0x2012U
48 48 #define UDF_SPARABLE_MAP15 0x1522U
  49 +#define UDF_METADATA_MAP25 0x2511U
49 50  
50 51 #pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */
51 52  
  53 +struct 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 +
52 65 struct udf_sparing_data {
53 66 __u16 s_packet_len;
54 67 struct buffer_head *s_spar_map[4];
... ... @@ -82,6 +95,7 @@
82 95 union {
83 96 struct udf_sparing_data s_sparing;
84 97 struct udf_virtual_data s_virtual;
  98 + struct udf_meta_data s_metadata;
85 99 } s_type_specific;
86 100 __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
87 101 __u16 s_volumeseqnum;
... ... @@ -177,6 +177,8 @@
177 177 uint32_t);
178 178 extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t,
179 179 uint32_t);
  180 +extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t,
  181 + uint32_t);
180 182 extern int udf_relocate_blocks(struct super_block *, long, long *);
181 183  
182 184 /* unicode.c */