aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2018-08-21 08:52:34 -0400
committerJan Kara <jack@suse.cz>2018-08-24 05:13:32 -0400
commitee4af50ca94f58afc3532662779b9cf80bbe27c8 (patch)
tree67727dfd727487005d3619a7b1d2c7a475c7d5d4
parent82c82ab658655befcb6aa47cbdb98dadce1a0cfe (diff)
udf: Fix mounting of Win7 created UDF filesystems
Win7 is creating UDF filesystems with single partition with number 8192. Current partition descriptor scanning code does not handle this well as it incorrectly assumes that partition numbers will form mostly contiguous space of small numbers. This results in unmountable media due to errors like: UDF-fs: error (device dm-1): udf_read_tagged: tag version 0x0000 != 0x0002 || 0x0003, block 0 UDF-fs: warning (device dm-1): udf_fill_super: No fileset found Fix the problem by handling partition descriptors in a way that sparse partition numbering does not matter. Reported-and-tested-by: jean-luc malet <jeanluc.malet@gmail.com> CC: stable@vger.kernel.org Fixes: 7b78fd02fb19530fd101ae137a1f46aa466d9bb6 Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--fs/udf/super.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 68d57b61f3af..6f515651a2c2 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1510,10 +1510,16 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
1510 */ 1510 */
1511#define PART_DESC_ALLOC_STEP 32 1511#define PART_DESC_ALLOC_STEP 32
1512 1512
1513struct part_desc_seq_scan_data {
1514 struct udf_vds_record rec;
1515 u32 partnum;
1516};
1517
1513struct desc_seq_scan_data { 1518struct desc_seq_scan_data {
1514 struct udf_vds_record vds[VDS_POS_LENGTH]; 1519 struct udf_vds_record vds[VDS_POS_LENGTH];
1515 unsigned int size_part_descs; 1520 unsigned int size_part_descs;
1516 struct udf_vds_record *part_descs_loc; 1521 unsigned int num_part_descs;
1522 struct part_desc_seq_scan_data *part_descs_loc;
1517}; 1523};
1518 1524
1519static struct udf_vds_record *handle_partition_descriptor( 1525static struct udf_vds_record *handle_partition_descriptor(
@@ -1522,10 +1528,14 @@ static struct udf_vds_record *handle_partition_descriptor(
1522{ 1528{
1523 struct partitionDesc *desc = (struct partitionDesc *)bh->b_data; 1529 struct partitionDesc *desc = (struct partitionDesc *)bh->b_data;
1524 int partnum; 1530 int partnum;
1531 int i;
1525 1532
1526 partnum = le16_to_cpu(desc->partitionNumber); 1533 partnum = le16_to_cpu(desc->partitionNumber);
1527 if (partnum >= data->size_part_descs) { 1534 for (i = 0; i < data->num_part_descs; i++)
1528 struct udf_vds_record *new_loc; 1535 if (partnum == data->part_descs_loc[i].partnum)
1536 return &(data->part_descs_loc[i].rec);
1537 if (data->num_part_descs >= data->size_part_descs) {
1538 struct part_desc_seq_scan_data *new_loc;
1529 unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP); 1539 unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP);
1530 1540
1531 new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL); 1541 new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL);
@@ -1537,7 +1547,7 @@ static struct udf_vds_record *handle_partition_descriptor(
1537 data->part_descs_loc = new_loc; 1547 data->part_descs_loc = new_loc;
1538 data->size_part_descs = new_size; 1548 data->size_part_descs = new_size;
1539 } 1549 }
1540 return &(data->part_descs_loc[partnum]); 1550 return &(data->part_descs_loc[data->num_part_descs++].rec);
1541} 1551}
1542 1552
1543 1553
@@ -1587,6 +1597,7 @@ static noinline int udf_process_sequence(
1587 1597
1588 memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); 1598 memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
1589 data.size_part_descs = PART_DESC_ALLOC_STEP; 1599 data.size_part_descs = PART_DESC_ALLOC_STEP;
1600 data.num_part_descs = 0;
1590 data.part_descs_loc = kcalloc(data.size_part_descs, 1601 data.part_descs_loc = kcalloc(data.size_part_descs,
1591 sizeof(*data.part_descs_loc), 1602 sizeof(*data.part_descs_loc),
1592 GFP_KERNEL); 1603 GFP_KERNEL);
@@ -1598,7 +1609,6 @@ static noinline int udf_process_sequence(
1598 * are in it. 1609 * are in it.
1599 */ 1610 */
1600 for (; (!done && block <= lastblock); block++) { 1611 for (; (!done && block <= lastblock); block++) {
1601
1602 bh = udf_read_tagged(sb, block, block, &ident); 1612 bh = udf_read_tagged(sb, block, block, &ident);
1603 if (!bh) 1613 if (!bh)
1604 break; 1614 break;
@@ -1670,13 +1680,10 @@ static noinline int udf_process_sequence(
1670 } 1680 }
1671 1681
1672 /* Now handle prevailing Partition Descriptors */ 1682 /* Now handle prevailing Partition Descriptors */
1673 for (i = 0; i < data.size_part_descs; i++) { 1683 for (i = 0; i < data.num_part_descs; i++) {
1674 if (data.part_descs_loc[i].block) { 1684 ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block);
1675 ret = udf_load_partdesc(sb, 1685 if (ret < 0)
1676 data.part_descs_loc[i].block); 1686 return ret;
1677 if (ret < 0)
1678 return ret;
1679 }
1680 } 1687 }
1681 1688
1682 return 0; 1689 return 0;