diff options
-rw-r--r-- | fs/udf/super.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index 9d1b8c2e6c45..1e4543cbcd27 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -1078,21 +1078,39 @@ static int udf_fill_partdesc_info(struct super_block *sb, | |||
1078 | return 0; | 1078 | return 0; |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | 1081 | static void udf_find_vat_block(struct super_block *sb, int p_index, |
1082 | int type1_index, sector_t start_block) | ||
1082 | { | 1083 | { |
1083 | struct udf_sb_info *sbi = UDF_SB(sb); | 1084 | struct udf_sb_info *sbi = UDF_SB(sb); |
1084 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; | 1085 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; |
1086 | sector_t vat_block; | ||
1085 | struct kernel_lb_addr ino; | 1087 | struct kernel_lb_addr ino; |
1088 | |||
1089 | /* | ||
1090 | * VAT file entry is in the last recorded block. Some broken disks have | ||
1091 | * it a few blocks before so try a bit harder... | ||
1092 | */ | ||
1093 | ino.partitionReferenceNum = type1_index; | ||
1094 | for (vat_block = start_block; | ||
1095 | vat_block >= map->s_partition_root && | ||
1096 | vat_block >= start_block - 3 && | ||
1097 | !sbi->s_vat_inode; vat_block--) { | ||
1098 | ino.logicalBlockNum = vat_block - map->s_partition_root; | ||
1099 | sbi->s_vat_inode = udf_iget(sb, &ino); | ||
1100 | } | ||
1101 | } | ||
1102 | |||
1103 | static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | ||
1104 | { | ||
1105 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
1106 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; | ||
1086 | struct buffer_head *bh = NULL; | 1107 | struct buffer_head *bh = NULL; |
1087 | struct udf_inode_info *vati; | 1108 | struct udf_inode_info *vati; |
1088 | uint32_t pos; | 1109 | uint32_t pos; |
1089 | struct virtualAllocationTable20 *vat20; | 1110 | struct virtualAllocationTable20 *vat20; |
1090 | sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; | 1111 | sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; |
1091 | 1112 | ||
1092 | /* VAT file entry is in the last recorded block */ | 1113 | udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block); |
1093 | ino.partitionReferenceNum = type1_index; | ||
1094 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; | ||
1095 | sbi->s_vat_inode = udf_iget(sb, &ino); | ||
1096 | if (!sbi->s_vat_inode && | 1114 | if (!sbi->s_vat_inode && |
1097 | sbi->s_last_block != blocks - 1) { | 1115 | sbi->s_last_block != blocks - 1) { |
1098 | printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" | 1116 | printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" |
@@ -1100,9 +1118,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | |||
1100 | "block of the device (%lu).\n", | 1118 | "block of the device (%lu).\n", |
1101 | (unsigned long)sbi->s_last_block, | 1119 | (unsigned long)sbi->s_last_block, |
1102 | (unsigned long)blocks - 1); | 1120 | (unsigned long)blocks - 1); |
1103 | ino.partitionReferenceNum = type1_index; | 1121 | udf_find_vat_block(sb, p_index, type1_index, blocks - 1); |
1104 | ino.logicalBlockNum = blocks - 1 - map->s_partition_root; | ||
1105 | sbi->s_vat_inode = udf_iget(sb, &ino); | ||
1106 | } | 1122 | } |
1107 | if (!sbi->s_vat_inode) | 1123 | if (!sbi->s_vat_inode) |
1108 | return 1; | 1124 | return 1; |