aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-04-07 20:08:53 -0400
committerJan Kara <jack@suse.cz>2008-04-17 08:25:35 -0400
commitfa5e08156335d0687c85b4e724db9448fb166601 (patch)
tree196b9d20b70129d892ceb3cf43ffb611b0067075 /fs/udf
parent742e1795e2d9dc99657742e5bbbb7907596bf6c3 (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/udf')
-rw-r--r--fs/udf/partition.c10
-rw-r--r--fs/udf/super.c24
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); 95translate:
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);