diff options
Diffstat (limited to 'fs/udf/partition.c')
| -rw-r--r-- | fs/udf/partition.c | 46 | 
1 files changed, 31 insertions, 15 deletions
diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 745eb209be0..d6caf01a209 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c @@ -25,6 +25,7 @@  #include <linux/fs.h>  #include <linux/string.h>  #include <linux/buffer_head.h> +#include <linux/mutex.h>  uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,  			uint16_t partition, uint32_t offset) @@ -32,8 +33,8 @@ uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,  	struct udf_sb_info *sbi = UDF_SB(sb);  	struct udf_part_map *map;  	if (partition >= sbi->s_partitions) { -		udf_debug("block=%d, partition=%d, offset=%d: " -			  "invalid partition\n", block, partition, offset); +		udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n", +			  block, partition, offset);  		return 0xFFFFFFFF;  	}  	map = &sbi->s_partmaps[partition]; @@ -59,8 +60,8 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,  	vdata = &map->s_type_specific.s_virtual;  	if (block > vdata->s_num_entries) { -		udf_debug("Trying to access block beyond end of VAT " -			  "(%d max %d)\n", block, vdata->s_num_entries); +		udf_debug("Trying to access block beyond end of VAT (%d max %d)\n", +			  block, vdata->s_num_entries);  		return 0xFFFFFFFF;  	} @@ -159,7 +160,9 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  	struct udf_sb_info *sbi = UDF_SB(sb);  	u16 reallocationTableLen;  	struct buffer_head *bh; +	int ret = 0; +	mutex_lock(&sbi->s_alloc_mutex);  	for (i = 0; i < sbi->s_partitions; i++) {  		struct udf_part_map *map = &sbi->s_partmaps[i];  		if (old_block > map->s_partition_root && @@ -175,8 +178,10 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  					break;  				} -			if (!st) -				return 1; +			if (!st) { +				ret = 1; +				goto out; +			}  			reallocationTableLen =  					le16_to_cpu(st->reallocationTableLen); @@ -207,14 +212,16 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  						     ((old_block -  							map->s_partition_root) &  						     (sdata->s_packet_len - 1)); -					return 0; +					ret = 0; +					goto out;  				} else if (origLoc == packet) {  					*new_block = le32_to_cpu(  							entry->mappedLocation) +  						     ((old_block -  							map->s_partition_root) &  						     (sdata->s_packet_len - 1)); -					return 0; +					ret = 0; +					goto out;  				} else if (origLoc > packet)  					break;  			} @@ -251,20 +258,24 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  					      st->mapEntry[k].mappedLocation) +  					((old_block - map->s_partition_root) &  					 (sdata->s_packet_len - 1)); -				return 0; +				ret = 0; +				goto out;  			} -			return 1; +			ret = 1; +			goto out;  		} /* if old_block */  	}  	if (i == sbi->s_partitions) {  		/* outside of partitions */  		/* for now, fail =) */ -		return 1; +		ret = 1;  	} -	return 0; +out: +	mutex_unlock(&sbi->s_alloc_mutex); +	return ret;  }  static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, @@ -310,9 +321,14 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,  	/* We shouldn't mount such media... */  	BUG_ON(!inode);  	retblk = udf_try_read_meta(inode, block, partition, offset); -	if (retblk == 0xFFFFFFFF) { -		udf_warning(sb, __func__, "error reading from METADATA, " -			"trying to read from MIRROR"); +	if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) { +		udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n"); +		if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) { +			mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, +				mdata->s_mirror_file_loc, map->s_partition_num); +			mdata->s_flags |= MF_MIRROR_FE_LOADED; +		} +  		inode = mdata->s_mirror_fe;  		if (!inode)  			return 0xFFFFFFFF;  | 
