Commit e971b0b9e0dd50d9ceecb67a6a6ab80a80906033
1 parent
1fefd086df
Exists in
master
and in
7 other branches
udf: Try harder when looking for VAT inode
Some disks do not contain VAT inode in the last recorded block as required by the standard but a few blocks earlier (or the number of recorded blocks is wrong). So look for the VAT inode a bit before the end of the media. Signed-off-by: Jan Kara <jack@suse.cz>
Showing 1 changed file with 24 additions and 8 deletions Side-by-side Diff
fs/udf/super.c
... | ... | @@ -1078,21 +1078,39 @@ |
1078 | 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 | 1084 | struct udf_sb_info *sbi = UDF_SB(sb); |
1084 | 1085 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; |
1086 | + sector_t vat_block; | |
1085 | 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 | 1107 | struct buffer_head *bh = NULL; |
1087 | 1108 | struct udf_inode_info *vati; |
1088 | 1109 | uint32_t pos; |
1089 | 1110 | struct virtualAllocationTable20 *vat20; |
1090 | 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 */ | |
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); | |
1113 | + udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block); | |
1096 | 1114 | if (!sbi->s_vat_inode && |
1097 | 1115 | sbi->s_last_block != blocks - 1) { |
1098 | 1116 | printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" |
... | ... | @@ -1100,9 +1118,7 @@ |
1100 | 1118 | "block of the device (%lu).\n", |
1101 | 1119 | (unsigned long)sbi->s_last_block, |
1102 | 1120 | (unsigned long)blocks - 1); |
1103 | - ino.partitionReferenceNum = type1_index; | |
1104 | - ino.logicalBlockNum = blocks - 1 - map->s_partition_root; | |
1105 | - sbi->s_vat_inode = udf_iget(sb, &ino); | |
1121 | + udf_find_vat_block(sb, p_index, type1_index, blocks - 1); | |
1106 | 1122 | } |
1107 | 1123 | if (!sbi->s_vat_inode) |
1108 | 1124 | return 1; |