summaryrefslogtreecommitdiffstats
path: root/fs/udf/partition.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-04-08 20:37:21 +0200
committerJan Kara <jack@suse.cz>2008-04-17 14:29:36 +0200
commitbfb257a5981af805a9394f00f75d3d9f7b611cc0 (patch)
tree2f91577f4c2a706ece3553372c737daf05885375 /fs/udf/partition.c
parentudf: Fix handling of multisession media (diff)
downloadlinux-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.c55
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;
+}