Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e971b0b9 authored by Jan Kara's avatar Jan Kara
Browse files

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: default avatarJan Kara <jack@suse.cz>
parent 1fefd086
Loading
Loading
Loading
Loading
+24 −8
Original line number Diff line number Diff line
@@ -1078,21 +1078,39 @@ static int udf_fill_partdesc_info(struct super_block *sb,
	return 0;
}

static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
static void udf_find_vat_block(struct super_block *sb, int p_index,
			       int type1_index, sector_t start_block)
{
	struct udf_sb_info *sbi = UDF_SB(sb);
	struct udf_part_map *map = &sbi->s_partmaps[p_index];
	sector_t vat_block;
	struct kernel_lb_addr ino;

	/*
	 * VAT file entry is in the last recorded block. Some broken disks have
	 * it a few blocks before so try a bit harder...
	 */
	ino.partitionReferenceNum = type1_index;
	for (vat_block = start_block;
	     vat_block >= map->s_partition_root &&
	     vat_block >= start_block - 3 &&
	     !sbi->s_vat_inode; vat_block--) {
		ino.logicalBlockNum = vat_block - map->s_partition_root;
		sbi->s_vat_inode = udf_iget(sb, &ino);
	}
}

static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
{
	struct udf_sb_info *sbi = UDF_SB(sb);
	struct udf_part_map *map = &sbi->s_partmaps[p_index];
	struct buffer_head *bh = NULL;
	struct udf_inode_info *vati;
	uint32_t pos;
	struct virtualAllocationTable20 *vat20;
	sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;

	/* VAT file entry is in the last recorded block */
	ino.partitionReferenceNum = type1_index;
	ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
	sbi->s_vat_inode = udf_iget(sb, &ino);
	udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
	if (!sbi->s_vat_inode &&
	    sbi->s_last_block != blocks - 1) {
		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)
		       "block of the device (%lu).\n",
		       (unsigned long)sbi->s_last_block,
		       (unsigned long)blocks - 1);
		ino.partitionReferenceNum = type1_index;
		ino.logicalBlockNum = blocks - 1 - map->s_partition_root;
		sbi->s_vat_inode = udf_iget(sb, &ino);
		udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
	}
	if (!sbi->s_vat_inode)
		return 1;