diff options
author | Jan Kara <jack@suse.cz> | 2008-04-08 20:37:21 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2008-04-17 14:29:36 +0200 |
commit | bfb257a5981af805a9394f00f75d3d9f7b611cc0 (patch) | |
tree | 2f91577f4c2a706ece3553372c737daf05885375 /fs/udf/partition.c | |
parent | udf: Fix handling of multisession media (diff) | |
download | linux-bfb257a5981af805a9394f00f75d3d9f7b611cc0.tar.xz linux-bfb257a5981af805a9394f00f75d3d9f7b611cc0.zip |
udf: Add read-only support for 2.50 UDF media
This patch implements parsing of metadata partitions and reading of Metadata
File thus allowing to read UDF 2.50 media. Error resilience is implemented
through accessing the Metadata Mirror File in case the data the Metadata File
cannot be read. The patch is based on the original patch by Sebastian Manciulea
<manciuleas@yahoo.com> and Mircea Fedoreanu <mirceaf_spl@yahoo.com>.
Signed-off-by: Sebastian Manciulea <manciuleas@yahoo.com>
Signed-off-by: Mircea Fedoreanu <mirceaf_spl@yahoo.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/partition.c')
-rw-r--r-- | fs/udf/partition.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/fs/udf/partition.c b/fs/udf/partition.c index b2e6e1eddb90..2dfe4be2eeb2 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c @@ -266,3 +266,58 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block) return 0; } + +static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, + uint16_t partition, uint32_t offset) +{ + struct super_block *sb = inode->i_sb; + struct udf_part_map *map; + kernel_lb_addr eloc; + uint32_t elen; + sector_t ext_offset; + struct extent_position epos = {}; + uint32_t phyblock; + + if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) != + (EXT_RECORDED_ALLOCATED >> 30)) + phyblock = 0xFFFFFFFF; + else { + map = &UDF_SB(sb)->s_partmaps[partition]; + /* map to sparable/physical partition desc */ + phyblock = udf_get_pblock(sb, eloc.logicalBlockNum, + map->s_partition_num, ext_offset + offset); + } + + brelse(epos.bh); + return phyblock; +} + +uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block, + uint16_t partition, uint32_t offset) +{ + struct udf_sb_info *sbi = UDF_SB(sb); + struct udf_part_map *map; + struct udf_meta_data *mdata; + uint32_t retblk; + struct inode *inode; + + udf_debug("READING from METADATA\n"); + + map = &sbi->s_partmaps[partition]; + mdata = &map->s_type_specific.s_metadata; + inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe; + + /* 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"); + inode = mdata->s_mirror_fe; + if (!inode) + return 0xFFFFFFFF; + retblk = udf_try_read_meta(inode, block, partition, offset); + } + + return retblk; +} |