diff options
author | Jan Kara <jack@suse.cz> | 2008-04-07 20:08:53 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2008-04-17 08:25:35 -0400 |
commit | fa5e08156335d0687c85b4e724db9448fb166601 (patch) | |
tree | 196b9d20b70129d892ceb3cf43ffb611b0067075 /fs | |
parent | 742e1795e2d9dc99657742e5bbbb7907596bf6c3 (diff) |
udf: Handle VAT packed inside inode properly
We didn't handle VAT packed inside the inode - we tried to call udf_block_map()
on such file which lead to strange results at best. Add proper handling of
packed VAT as we do it with other packed files.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/udf/partition.c | 10 | ||||
-rw-r--r-- | fs/udf/super.c | 24 |
2 files changed, 22 insertions, 12 deletions
diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 307c9c33d184..b2e6e1eddb90 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c | |||
@@ -54,11 +54,10 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, | |||
54 | struct udf_sb_info *sbi = UDF_SB(sb); | 54 | struct udf_sb_info *sbi = UDF_SB(sb); |
55 | struct udf_part_map *map; | 55 | struct udf_part_map *map; |
56 | struct udf_virtual_data *vdata; | 56 | struct udf_virtual_data *vdata; |
57 | struct udf_inode_info *iinfo; | 57 | struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode); |
58 | 58 | ||
59 | map = &sbi->s_partmaps[partition]; | 59 | map = &sbi->s_partmaps[partition]; |
60 | vdata = &map->s_type_specific.s_virtual; | 60 | vdata = &map->s_type_specific.s_virtual; |
61 | index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t); | ||
62 | 61 | ||
63 | if (block > vdata->s_num_entries) { | 62 | if (block > vdata->s_num_entries) { |
64 | udf_debug("Trying to access block beyond end of VAT " | 63 | udf_debug("Trying to access block beyond end of VAT " |
@@ -66,6 +65,11 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, | |||
66 | return 0xFFFFFFFF; | 65 | return 0xFFFFFFFF; |
67 | } | 66 | } |
68 | 67 | ||
68 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | ||
69 | loc = le32_to_cpu(((__le32 *)iinfo->i_ext.i_data)[block]); | ||
70 | goto translate; | ||
71 | } | ||
72 | index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t); | ||
69 | if (block >= index) { | 73 | if (block >= index) { |
70 | block -= index; | 74 | block -= index; |
71 | newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t))); | 75 | newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t))); |
@@ -88,7 +92,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, | |||
88 | 92 | ||
89 | brelse(bh); | 93 | brelse(bh); |
90 | 94 | ||
91 | iinfo = UDF_I(sbi->s_vat_inode); | 95 | translate: |
92 | if (iinfo->i_location.partitionReferenceNum == partition) { | 96 | if (iinfo->i_location.partitionReferenceNum == partition) { |
93 | udf_debug("recursive call to udf_get_pblock!\n"); | 97 | udf_debug("recursive call to udf_get_pblock!\n"); |
94 | return 0xFFFFFFFF; | 98 | return 0xFFFFFFFF; |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 14f965e8a738..abdb9b31da46 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -1107,7 +1107,10 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | |||
1107 | struct udf_sb_info *sbi = UDF_SB(sb); | 1107 | struct udf_sb_info *sbi = UDF_SB(sb); |
1108 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; | 1108 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; |
1109 | kernel_lb_addr ino; | 1109 | kernel_lb_addr ino; |
1110 | struct buffer_head *bh; | 1110 | struct buffer_head *bh = NULL; |
1111 | struct udf_inode_info *vati; | ||
1112 | uint32_t pos; | ||
1113 | struct virtualAllocationTable20 *vat20; | ||
1111 | 1114 | ||
1112 | /* VAT file entry is in the last recorded block */ | 1115 | /* VAT file entry is in the last recorded block */ |
1113 | ino.partitionReferenceNum = type1_index; | 1116 | ino.partitionReferenceNum = type1_index; |
@@ -1122,15 +1125,18 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | |||
1122 | map->s_type_specific.s_virtual.s_num_entries = | 1125 | map->s_type_specific.s_virtual.s_num_entries = |
1123 | (sbi->s_vat_inode->i_size - 36) >> 2; | 1126 | (sbi->s_vat_inode->i_size - 36) >> 2; |
1124 | } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { | 1127 | } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { |
1125 | uint32_t pos; | 1128 | vati = UDF_I(sbi->s_vat_inode); |
1126 | struct virtualAllocationTable20 *vat20; | 1129 | if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
1130 | pos = udf_block_map(sbi->s_vat_inode, 0); | ||
1131 | bh = sb_bread(sb, pos); | ||
1132 | if (!bh) | ||
1133 | return 1; | ||
1134 | vat20 = (struct virtualAllocationTable20 *)bh->b_data; | ||
1135 | } else { | ||
1136 | vat20 = (struct virtualAllocationTable20 *) | ||
1137 | vati->i_ext.i_data; | ||
1138 | } | ||
1127 | 1139 | ||
1128 | pos = udf_block_map(sbi->s_vat_inode, 0); | ||
1129 | bh = sb_bread(sb, pos); | ||
1130 | if (!bh) | ||
1131 | return 1; | ||
1132 | vat20 = (struct virtualAllocationTable20 *)bh->b_data + | ||
1133 | udf_ext0_offset(sbi->s_vat_inode); | ||
1134 | map->s_type_specific.s_virtual.s_start_offset = | 1140 | map->s_type_specific.s_virtual.s_start_offset = |
1135 | le16_to_cpu(vat20->lengthHeader) + | 1141 | le16_to_cpu(vat20->lengthHeader) + |
1136 | udf_ext0_offset(sbi->s_vat_inode); | 1142 | udf_ext0_offset(sbi->s_vat_inode); |