diff options
| -rw-r--r-- | fs/udf/super.c | 86 |
1 files changed, 53 insertions, 33 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index ce911f50b39d..8d86a8706c0e 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #include <linux/seq_file.h> | 56 | #include <linux/seq_file.h> |
| 57 | #include <linux/bitmap.h> | 57 | #include <linux/bitmap.h> |
| 58 | #include <linux/crc-itu-t.h> | 58 | #include <linux/crc-itu-t.h> |
| 59 | #include <linux/log2.h> | ||
| 59 | #include <asm/byteorder.h> | 60 | #include <asm/byteorder.h> |
| 60 | 61 | ||
| 61 | #include "udf_sb.h" | 62 | #include "udf_sb.h" |
| @@ -1215,11 +1216,59 @@ out_bh: | |||
| 1215 | return ret; | 1216 | return ret; |
| 1216 | } | 1217 | } |
| 1217 | 1218 | ||
| 1219 | static int udf_load_sparable_map(struct super_block *sb, | ||
| 1220 | struct udf_part_map *map, | ||
| 1221 | struct sparablePartitionMap *spm) | ||
| 1222 | { | ||
| 1223 | uint32_t loc; | ||
| 1224 | uint16_t ident; | ||
| 1225 | struct sparingTable *st; | ||
| 1226 | struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing; | ||
| 1227 | int i; | ||
| 1228 | struct buffer_head *bh; | ||
| 1229 | |||
| 1230 | map->s_partition_type = UDF_SPARABLE_MAP15; | ||
| 1231 | sdata->s_packet_len = le16_to_cpu(spm->packetLength); | ||
| 1232 | if (!is_power_of_2(sdata->s_packet_len)) { | ||
| 1233 | udf_err(sb, "error loading logical volume descriptor: " | ||
| 1234 | "Invalid packet length %u\n", | ||
| 1235 | (unsigned)sdata->s_packet_len); | ||
| 1236 | return -EIO; | ||
| 1237 | } | ||
| 1238 | if (spm->numSparingTables > 4) { | ||
| 1239 | udf_err(sb, "error loading logical volume descriptor: " | ||
| 1240 | "Too many sparing tables (%d)\n", | ||
| 1241 | (int)spm->numSparingTables); | ||
| 1242 | return -EIO; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | for (i = 0; i < spm->numSparingTables; i++) { | ||
| 1246 | loc = le32_to_cpu(spm->locSparingTable[i]); | ||
| 1247 | bh = udf_read_tagged(sb, loc, loc, &ident); | ||
| 1248 | if (!bh) | ||
| 1249 | continue; | ||
| 1250 | |||
| 1251 | st = (struct sparingTable *)bh->b_data; | ||
| 1252 | if (ident != 0 || | ||
| 1253 | strncmp(st->sparingIdent.ident, UDF_ID_SPARING, | ||
| 1254 | strlen(UDF_ID_SPARING)) || | ||
| 1255 | sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > | ||
| 1256 | sb->s_blocksize) { | ||
| 1257 | brelse(bh); | ||
| 1258 | continue; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | sdata->s_spar_map[i] = bh; | ||
| 1262 | } | ||
| 1263 | map->s_partition_func = udf_get_pblock_spar15; | ||
| 1264 | return 0; | ||
| 1265 | } | ||
| 1266 | |||
| 1218 | static int udf_load_logicalvol(struct super_block *sb, sector_t block, | 1267 | static int udf_load_logicalvol(struct super_block *sb, sector_t block, |
| 1219 | struct kernel_lb_addr *fileset) | 1268 | struct kernel_lb_addr *fileset) |
| 1220 | { | 1269 | { |
| 1221 | struct logicalVolDesc *lvd; | 1270 | struct logicalVolDesc *lvd; |
| 1222 | int i, j, offset; | 1271 | int i, offset; |
| 1223 | uint8_t type; | 1272 | uint8_t type; |
| 1224 | struct udf_sb_info *sbi = UDF_SB(sb); | 1273 | struct udf_sb_info *sbi = UDF_SB(sb); |
| 1225 | struct genericPartitionMap *gpm; | 1274 | struct genericPartitionMap *gpm; |
| @@ -1281,38 +1330,9 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, | |||
| 1281 | } else if (!strncmp(upm2->partIdent.ident, | 1330 | } else if (!strncmp(upm2->partIdent.ident, |
| 1282 | UDF_ID_SPARABLE, | 1331 | UDF_ID_SPARABLE, |
| 1283 | strlen(UDF_ID_SPARABLE))) { | 1332 | strlen(UDF_ID_SPARABLE))) { |
| 1284 | uint32_t loc; | 1333 | if (udf_load_sparable_map(sb, map, |
| 1285 | struct sparingTable *st; | 1334 | (struct sparablePartitionMap *)gpm) < 0) |
| 1286 | struct sparablePartitionMap *spm = | 1335 | goto out_bh; |
| 1287 | (struct sparablePartitionMap *)gpm; | ||
| 1288 | |||
| 1289 | map->s_partition_type = UDF_SPARABLE_MAP15; | ||
| 1290 | map->s_type_specific.s_sparing.s_packet_len = | ||
| 1291 | le16_to_cpu(spm->packetLength); | ||
| 1292 | for (j = 0; j < spm->numSparingTables; j++) { | ||
| 1293 | struct buffer_head *bh2; | ||
| 1294 | |||
| 1295 | loc = le32_to_cpu( | ||
| 1296 | spm->locSparingTable[j]); | ||
| 1297 | bh2 = udf_read_tagged(sb, loc, loc, | ||
| 1298 | &ident); | ||
| 1299 | map->s_type_specific.s_sparing. | ||
| 1300 | s_spar_map[j] = bh2; | ||
| 1301 | |||
| 1302 | if (bh2 == NULL) | ||
| 1303 | continue; | ||
| 1304 | |||
| 1305 | st = (struct sparingTable *)bh2->b_data; | ||
| 1306 | if (ident != 0 || strncmp( | ||
| 1307 | st->sparingIdent.ident, | ||
| 1308 | UDF_ID_SPARING, | ||
| 1309 | strlen(UDF_ID_SPARING))) { | ||
| 1310 | brelse(bh2); | ||
| 1311 | map->s_type_specific.s_sparing. | ||
| 1312 | s_spar_map[j] = NULL; | ||
| 1313 | } | ||
| 1314 | } | ||
| 1315 | map->s_partition_func = udf_get_pblock_spar15; | ||
| 1316 | } else if (!strncmp(upm2->partIdent.ident, | 1336 | } else if (!strncmp(upm2->partIdent.ident, |
| 1317 | UDF_ID_METADATA, | 1337 | UDF_ID_METADATA, |
| 1318 | strlen(UDF_ID_METADATA))) { | 1338 | strlen(UDF_ID_METADATA))) { |
