diff options
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/super.c | 165 |
1 files changed, 85 insertions, 80 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index c5fef85a9c15..7ec828566df2 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -84,7 +84,6 @@ static void udf_write_super(struct super_block *); | |||
84 | static int udf_remount_fs(struct super_block *, int *, char *); | 84 | 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 *); | ||
88 | static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); | 87 | static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); |
89 | static void udf_find_anchor(struct super_block *); | 88 | static void udf_find_anchor(struct super_block *); |
90 | static int udf_find_fileset(struct super_block *, kernel_lb_addr *, | 89 | static int udf_find_fileset(struct super_block *, kernel_lb_addr *, |
@@ -1125,14 +1124,54 @@ static int udf_fill_partdesc_info(struct super_block *sb, | |||
1125 | return 0; | 1124 | return 0; |
1126 | } | 1125 | } |
1127 | 1126 | ||
1127 | static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | ||
1128 | { | ||
1129 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
1130 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; | ||
1131 | kernel_lb_addr ino; | ||
1132 | struct buffer_head *bh; | ||
1133 | |||
1134 | /* VAT file entry is in the last recorded block */ | ||
1135 | ino.partitionReferenceNum = type1_index; | ||
1136 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; | ||
1137 | sbi->s_vat_inode = udf_iget(sb, ino); | ||
1138 | if (!sbi->s_vat_inode) | ||
1139 | return 1; | ||
1140 | |||
1141 | if (map->s_partition_type == UDF_VIRTUAL_MAP15) { | ||
1142 | map->s_type_specific.s_virtual.s_start_offset = | ||
1143 | udf_ext0_offset(sbi->s_vat_inode); | ||
1144 | map->s_type_specific.s_virtual.s_num_entries = | ||
1145 | (sbi->s_vat_inode->i_size - 36) >> 2; | ||
1146 | } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { | ||
1147 | uint32_t pos; | ||
1148 | struct virtualAllocationTable20 *vat20; | ||
1149 | |||
1150 | pos = udf_block_map(sbi->s_vat_inode, 0); | ||
1151 | bh = sb_bread(sb, pos); | ||
1152 | if (!bh) | ||
1153 | return 1; | ||
1154 | vat20 = (struct virtualAllocationTable20 *)bh->b_data + | ||
1155 | udf_ext0_offset(sbi->s_vat_inode); | ||
1156 | map->s_type_specific.s_virtual.s_start_offset = | ||
1157 | le16_to_cpu(vat20->lengthHeader) + | ||
1158 | udf_ext0_offset(sbi->s_vat_inode); | ||
1159 | map->s_type_specific.s_virtual.s_num_entries = | ||
1160 | (sbi->s_vat_inode->i_size - | ||
1161 | map->s_type_specific.s_virtual. | ||
1162 | s_start_offset) >> 2; | ||
1163 | brelse(bh); | ||
1164 | } | ||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1128 | static int udf_load_partdesc(struct super_block *sb, sector_t block) | 1168 | static int udf_load_partdesc(struct super_block *sb, sector_t block) |
1129 | { | 1169 | { |
1130 | struct buffer_head *bh; | 1170 | struct buffer_head *bh; |
1131 | struct partitionDesc *p; | 1171 | struct partitionDesc *p; |
1132 | struct udf_part_map *map; | 1172 | struct udf_part_map *map; |
1133 | struct udf_sb_info *sbi = UDF_SB(sb); | 1173 | struct udf_sb_info *sbi = UDF_SB(sb); |
1134 | bool found = false; | 1174 | int i, type1_idx; |
1135 | int i; | ||
1136 | uint16_t partitionNumber; | 1175 | uint16_t partitionNumber; |
1137 | uint16_t ident; | 1176 | uint16_t ident; |
1138 | int ret = 0; | 1177 | int ret = 0; |
@@ -1145,22 +1184,59 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) | |||
1145 | 1184 | ||
1146 | p = (struct partitionDesc *)bh->b_data; | 1185 | p = (struct partitionDesc *)bh->b_data; |
1147 | partitionNumber = le16_to_cpu(p->partitionNumber); | 1186 | partitionNumber = le16_to_cpu(p->partitionNumber); |
1187 | |||
1188 | /* First scan for TYPE1 and SPARABLE partitions */ | ||
1148 | for (i = 0; i < sbi->s_partitions; i++) { | 1189 | for (i = 0; i < sbi->s_partitions; i++) { |
1149 | map = &sbi->s_partmaps[i]; | 1190 | map = &sbi->s_partmaps[i]; |
1150 | udf_debug("Searching map: (%d == %d)\n", | 1191 | udf_debug("Searching map: (%d == %d)\n", |
1151 | map->s_partition_num, partitionNumber); | 1192 | map->s_partition_num, partitionNumber); |
1152 | found = map->s_partition_num == partitionNumber; | 1193 | if (map->s_partition_num == partitionNumber && |
1153 | if (found) | 1194 | (map->s_partition_type == UDF_TYPE1_MAP15 || |
1195 | map->s_partition_type == UDF_SPARABLE_MAP15)) | ||
1154 | break; | 1196 | break; |
1155 | } | 1197 | } |
1156 | 1198 | ||
1157 | if (!found) { | 1199 | if (i >= sbi->s_partitions) { |
1158 | udf_debug("Partition (%d) not found in partition map\n", | 1200 | udf_debug("Partition (%d) not found in partition map\n", |
1159 | partitionNumber); | 1201 | partitionNumber); |
1160 | goto out_bh; | 1202 | goto out_bh; |
1161 | } | 1203 | } |
1162 | 1204 | ||
1163 | ret = udf_fill_partdesc_info(sb, p, i); | 1205 | ret = udf_fill_partdesc_info(sb, p, i); |
1206 | |||
1207 | /* | ||
1208 | * Now rescan for VIRTUAL partitions when TYPE1 partitions are | ||
1209 | * already set up | ||
1210 | */ | ||
1211 | type1_idx = i; | ||
1212 | for (i = 0; i < sbi->s_partitions; i++) { | ||
1213 | map = &sbi->s_partmaps[i]; | ||
1214 | |||
1215 | if (map->s_partition_num == partitionNumber && | ||
1216 | (map->s_partition_type == UDF_VIRTUAL_MAP15 || | ||
1217 | map->s_partition_type == UDF_VIRTUAL_MAP20)) | ||
1218 | break; | ||
1219 | } | ||
1220 | |||
1221 | if (i >= sbi->s_partitions) | ||
1222 | goto out_bh; | ||
1223 | |||
1224 | ret = udf_fill_partdesc_info(sb, p, i); | ||
1225 | if (ret) | ||
1226 | goto out_bh; | ||
1227 | |||
1228 | if (!sbi->s_last_block) { | ||
1229 | sbi->s_last_block = udf_get_last_block(sb); | ||
1230 | udf_find_anchor(sb); | ||
1231 | if (!sbi->s_last_block) { | ||
1232 | udf_debug("Unable to determine Lastblock (For " | ||
1233 | "Virtual Partition)\n"); | ||
1234 | ret = 1; | ||
1235 | goto out_bh; | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | ret = udf_load_vat(sb, i, type1_idx); | ||
1164 | out_bh: | 1240 | out_bh: |
1165 | /* In case loading failed, we handle cleanup in udf_fill_super */ | 1241 | /* In case loading failed, we handle cleanup in udf_fill_super */ |
1166 | brelse(bh); | 1242 | brelse(bh); |
@@ -1480,13 +1556,13 @@ static int udf_check_valid(struct super_block *sb, int novrs, int silent) | |||
1480 | return !block; | 1556 | return !block; |
1481 | } | 1557 | } |
1482 | 1558 | ||
1483 | static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset) | 1559 | static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset) |
1484 | { | 1560 | { |
1485 | struct anchorVolDescPtr *anchor; | 1561 | struct anchorVolDescPtr *anchor; |
1486 | uint16_t ident; | 1562 | uint16_t ident; |
1487 | struct buffer_head *bh; | 1563 | struct buffer_head *bh; |
1488 | long main_s, main_e, reserve_s, reserve_e; | 1564 | long main_s, main_e, reserve_s, reserve_e; |
1489 | int i, j; | 1565 | int i; |
1490 | struct udf_sb_info *sbi; | 1566 | struct udf_sb_info *sbi; |
1491 | 1567 | ||
1492 | if (!sb) | 1568 | if (!sb) |
@@ -1535,77 +1611,6 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset) | |||
1535 | } | 1611 | } |
1536 | udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]); | 1612 | udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]); |
1537 | 1613 | ||
1538 | for (i = 0; i < sbi->s_partitions; i++) { | ||
1539 | kernel_lb_addr uninitialized_var(ino); | ||
1540 | struct udf_part_map *map = &sbi->s_partmaps[i]; | ||
1541 | |||
1542 | if (map->s_partition_type != UDF_VIRTUAL_MAP15 && | ||
1543 | map->s_partition_type != UDF_VIRTUAL_MAP20) | ||
1544 | continue; | ||
1545 | |||
1546 | if (!sbi->s_last_block) { | ||
1547 | sbi->s_last_block = udf_get_last_block(sb); | ||
1548 | udf_find_anchor(sb); | ||
1549 | } | ||
1550 | |||
1551 | if (!sbi->s_last_block) { | ||
1552 | udf_debug("Unable to determine Lastblock (For " | ||
1553 | "Virtual Partition)\n"); | ||
1554 | return 1; | ||
1555 | } | ||
1556 | |||
1557 | for (j = 0; j < sbi->s_partitions; j++) { | ||
1558 | struct udf_part_map *map2 = &sbi->s_partmaps[j]; | ||
1559 | if (j != i && | ||
1560 | map->s_volumeseqnum == | ||
1561 | map2->s_volumeseqnum && | ||
1562 | map->s_partition_num == | ||
1563 | map2->s_partition_num) { | ||
1564 | ino.partitionReferenceNum = j; | ||
1565 | ino.logicalBlockNum = | ||
1566 | sbi->s_last_block - | ||
1567 | map2->s_partition_root; | ||
1568 | break; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | if (j == sbi->s_partitions) | ||
1573 | return 1; | ||
1574 | |||
1575 | sbi->s_vat_inode = udf_iget(sb, ino); | ||
1576 | if (!sbi->s_vat_inode) | ||
1577 | return 1; | ||
1578 | |||
1579 | if (map->s_partition_type == UDF_VIRTUAL_MAP15) { | ||
1580 | map->s_type_specific.s_virtual.s_start_offset = | ||
1581 | udf_ext0_offset(sbi->s_vat_inode); | ||
1582 | map->s_type_specific.s_virtual.s_num_entries = | ||
1583 | (sbi->s_vat_inode->i_size - 36) >> 2; | ||
1584 | } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { | ||
1585 | uint32_t pos; | ||
1586 | struct virtualAllocationTable20 *vat20; | ||
1587 | |||
1588 | pos = udf_block_map(sbi->s_vat_inode, 0); | ||
1589 | bh = sb_bread(sb, pos); | ||
1590 | if (!bh) | ||
1591 | return 1; | ||
1592 | vat20 = (struct virtualAllocationTable20 *) | ||
1593 | bh->b_data + | ||
1594 | udf_ext0_offset(sbi->s_vat_inode); | ||
1595 | map->s_type_specific.s_virtual.s_start_offset = | ||
1596 | le16_to_cpu(vat20->lengthHeader) + | ||
1597 | udf_ext0_offset(sbi->s_vat_inode); | ||
1598 | map->s_type_specific.s_virtual.s_num_entries = | ||
1599 | (sbi->s_vat_inode->i_size - | ||
1600 | map->s_type_specific.s_virtual. | ||
1601 | s_start_offset) >> 2; | ||
1602 | brelse(bh); | ||
1603 | } | ||
1604 | map->s_partition_root = udf_get_pblock(sb, 0, i, 0); | ||
1605 | map->s_partition_len = | ||
1606 | sbi->s_partmaps[ino.partitionReferenceNum]. | ||
1607 | s_partition_len; | ||
1608 | } | ||
1609 | return 0; | 1614 | return 0; |
1610 | } | 1615 | } |
1611 | 1616 | ||
@@ -1790,7 +1795,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1790 | sb->s_magic = UDF_SUPER_MAGIC; | 1795 | sb->s_magic = UDF_SUPER_MAGIC; |
1791 | sb->s_time_gran = 1000; | 1796 | sb->s_time_gran = 1000; |
1792 | 1797 | ||
1793 | if (udf_load_partition(sb, &fileset)) { | 1798 | if (udf_load_sequence(sb, &fileset)) { |
1794 | printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); | 1799 | printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); |
1795 | goto error_out; | 1800 | goto error_out; |
1796 | } | 1801 | } |