diff options
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r-- | fs/udf/super.c | 190 |
1 files changed, 177 insertions, 13 deletions
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 | ||
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 | static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, | 1048 | static 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 | } | ||
1221 | out_bh: | 1329 | out_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) | |||
1677 | static void udf_free_partition(struct udf_part_map *map) | 1829 | static 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 | ||
1694 | static int udf_fill_super(struct super_block *sb, void *options, int silent) | 1858 | static int udf_fill_super(struct super_block *sb, void *options, int silent) |