|
56 | 56 | #include <linux/seq_file.h> |
57 | 57 | #include <linux/bitmap.h> |
58 | 58 | #include <linux/crc-itu-t.h> |
| 59 | +#include <linux/log2.h> |
59 | 60 | #include <asm/byteorder.h> |
60 | 61 |
|
61 | 62 | #include "udf_sb.h" |
@@ -1215,11 +1216,59 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) |
1215 | 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 | 1267 | static int udf_load_logicalvol(struct super_block *sb, sector_t block, |
1219 | 1268 | struct kernel_lb_addr *fileset) |
1220 | 1269 | { |
1221 | 1270 | struct logicalVolDesc *lvd; |
1222 | | - int i, j, offset; |
| 1271 | + int i, offset; |
1223 | 1272 | uint8_t type; |
1224 | 1273 | struct udf_sb_info *sbi = UDF_SB(sb); |
1225 | 1274 | struct genericPartitionMap *gpm; |
@@ -1281,38 +1330,9 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, |
1281 | 1330 | } else if (!strncmp(upm2->partIdent.ident, |
1282 | 1331 | UDF_ID_SPARABLE, |
1283 | 1332 | strlen(UDF_ID_SPARABLE))) { |
1284 | | - uint32_t loc; |
1285 | | - struct sparingTable *st; |
1286 | | - struct sparablePartitionMap *spm = |
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; |
| 1333 | + if (udf_load_sparable_map(sb, map, |
| 1334 | + (struct sparablePartitionMap *)gpm) < 0) |
| 1335 | + goto out_bh; |
1316 | 1336 | } else if (!strncmp(upm2->partIdent.ident, |
1317 | 1337 | UDF_ID_METADATA, |
1318 | 1338 | strlen(UDF_ID_METADATA))) { |
|
0 commit comments