X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fudf%2Fsuper.c;h=7a5f69be6ac2127de968661bd6d5e134712940b3;hb=1df5a8d004f64b1aa3fb93e0556886ba00ebc979;hp=14f965e8a738f415c25ac9f317a8b526a7dbcb70;hpb=c82a127505d39fa81c886eceed6fdf8c1ff4a06b;p=linux-2.6 diff --git a/fs/udf/super.c b/fs/udf/super.c index 14f965e8a7..7a5f69be6a 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include "udf_sb.h" @@ -239,7 +240,7 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count) sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map), GFP_KERNEL); if (!sbi->s_partmaps) { - udf_error(sb, __FUNCTION__, + udf_error(sb, __func__, "Unable to allocate space for %d partition maps", count); sbi->s_partitions = 0; @@ -587,7 +588,7 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) static int udf_vrs(struct super_block *sb, int silent) { struct volStructDesc *vsd = NULL; - int sector = 32768; + loff_t sector = 32768; int sectorsize; struct buffer_head *bh = NULL; int iso9660 = 0; @@ -608,7 +609,8 @@ static int udf_vrs(struct super_block *sb, int silent) sector += (sbi->s_session << sb->s_blocksize_bits); udf_debug("Starting at sector %u (%ld byte sectors)\n", - (sector >> sb->s_blocksize_bits), sb->s_blocksize); + (unsigned int)(sector >> sb->s_blocksize_bits), + sb->s_blocksize); /* Process the sequence (if applicable) */ for (; !nsr02 && !nsr03; sector += sectorsize) { /* Read a block */ @@ -950,6 +952,101 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) return 0; } +static int udf_load_metadata_files(struct super_block *sb, int partition) +{ + struct udf_sb_info *sbi = UDF_SB(sb); + struct udf_part_map *map; + struct udf_meta_data *mdata; + kernel_lb_addr addr; + int fe_error = 0; + + map = &sbi->s_partmaps[partition]; + mdata = &map->s_type_specific.s_metadata; + + /* metadata address */ + addr.logicalBlockNum = mdata->s_meta_file_loc; + addr.partitionReferenceNum = map->s_partition_num; + + udf_debug("Metadata file location: block = %d part = %d\n", + addr.logicalBlockNum, addr.partitionReferenceNum); + + mdata->s_metadata_fe = udf_iget(sb, addr); + + if (mdata->s_metadata_fe == NULL) { + udf_warning(sb, __func__, "metadata inode efe not found, " + "will try mirror inode."); + fe_error = 1; + } else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type != + ICBTAG_FLAG_AD_SHORT) { + udf_warning(sb, __func__, "metadata inode efe does not have " + "short allocation descriptors!"); + fe_error = 1; + iput(mdata->s_metadata_fe); + mdata->s_metadata_fe = NULL; + } + + /* mirror file entry */ + addr.logicalBlockNum = mdata->s_mirror_file_loc; + addr.partitionReferenceNum = map->s_partition_num; + + udf_debug("Mirror metadata file location: block = %d part = %d\n", + addr.logicalBlockNum, addr.partitionReferenceNum); + + mdata->s_mirror_fe = udf_iget(sb, addr); + + if (mdata->s_mirror_fe == NULL) { + if (fe_error) { + udf_error(sb, __func__, "mirror inode efe not found " + "and metadata inode is missing too, exiting..."); + goto error_exit; + } else + udf_warning(sb, __func__, "mirror inode efe not found," + " but metadata inode is OK"); + } else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type != + ICBTAG_FLAG_AD_SHORT) { + udf_warning(sb, __func__, "mirror inode efe does not have " + "short allocation descriptors!"); + iput(mdata->s_mirror_fe); + mdata->s_mirror_fe = NULL; + if (fe_error) + goto error_exit; + } + + /* + * bitmap file entry + * Note: + * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102) + */ + if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) { + addr.logicalBlockNum = mdata->s_bitmap_file_loc; + addr.partitionReferenceNum = map->s_partition_num; + + udf_debug("Bitmap file location: block = %d part = %d\n", + addr.logicalBlockNum, addr.partitionReferenceNum); + + mdata->s_bitmap_fe = udf_iget(sb, addr); + + if (mdata->s_bitmap_fe == NULL) { + if (sb->s_flags & MS_RDONLY) + udf_warning(sb, __func__, "bitmap inode efe " + "not found but it's ok since the disc" + " is mounted read-only"); + else { + udf_error(sb, __func__, "bitmap inode efe not " + "found and attempted read-write mount"); + goto error_exit; + } + } + } + + udf_debug("udf_load_metadata_files Ok\n"); + + return 0; + +error_exit: + return 1; +} + static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, kernel_lb_addr *root) { @@ -989,7 +1086,7 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) bitmap = vmalloc(size); /* TODO: get rid of vmalloc */ if (bitmap == NULL) { - udf_error(sb, __FUNCTION__, + udf_error(sb, __func__, "Unable to allocate space for bitmap " "and %d buffer_head pointers", nr_groups); return NULL; @@ -1022,8 +1119,8 @@ static int udf_fill_partdesc_info(struct super_block *sb, if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE)) map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE; - udf_debug("Partition (%d:%d type %x) starts at physical %d, " - "block length %d\n", partitionNumber, p_index, + udf_debug("Partition (%d type %x) starts at physical %d, " + "block length %d\n", p_index, map->s_partition_type, map->s_partition_root, map->s_partition_len); @@ -1107,7 +1204,10 @@ 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]; kernel_lb_addr ino; - struct buffer_head *bh; + struct buffer_head *bh = NULL; + struct udf_inode_info *vati; + uint32_t pos; + struct virtualAllocationTable20 *vat20; /* VAT file entry is in the last recorded block */ ino.partitionReferenceNum = type1_index; @@ -1117,23 +1217,24 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) return 1; if (map->s_partition_type == UDF_VIRTUAL_MAP15) { - map->s_type_specific.s_virtual.s_start_offset = - udf_ext0_offset(sbi->s_vat_inode); + map->s_type_specific.s_virtual.s_start_offset = 0; map->s_type_specific.s_virtual.s_num_entries = (sbi->s_vat_inode->i_size - 36) >> 2; } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { - uint32_t pos; - struct virtualAllocationTable20 *vat20; + vati = UDF_I(sbi->s_vat_inode); + if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { + pos = udf_block_map(sbi->s_vat_inode, 0); + bh = sb_bread(sb, pos); + if (!bh) + return 1; + vat20 = (struct virtualAllocationTable20 *)bh->b_data; + } else { + vat20 = (struct virtualAllocationTable20 *) + vati->i_ext.i_data; + } - pos = udf_block_map(sbi->s_vat_inode, 0); - bh = sb_bread(sb, pos); - if (!bh) - return 1; - vat20 = (struct virtualAllocationTable20 *)bh->b_data + - udf_ext0_offset(sbi->s_vat_inode); map->s_type_specific.s_virtual.s_start_offset = - le16_to_cpu(vat20->lengthHeader) + - udf_ext0_offset(sbi->s_vat_inode); + le16_to_cpu(vat20->lengthHeader); map->s_type_specific.s_virtual.s_num_entries = (sbi->s_vat_inode->i_size - map->s_type_specific.s_virtual. @@ -1163,7 +1264,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) p = (struct partitionDesc *)bh->b_data; partitionNumber = le16_to_cpu(p->partitionNumber); - /* First scan for TYPE1 and SPARABLE partitions */ + /* First scan for TYPE1, SPARABLE and METADATA partitions */ for (i = 0; i < sbi->s_partitions; i++) { map = &sbi->s_partmaps[i]; udf_debug("Searching map: (%d == %d)\n", @@ -1183,8 +1284,8 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) ret = udf_fill_partdesc_info(sb, p, i); /* - * Now rescan for VIRTUAL partitions when TYPE1 partitions are - * already set up + * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and + * PHYSICAL partitions are already set up */ type1_idx = i; for (i = 0; i < sbi->s_partitions; i++) { @@ -1192,7 +1293,8 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) if (map->s_partition_num == partitionNumber && (map->s_partition_type == UDF_VIRTUAL_MAP15 || - map->s_partition_type == UDF_VIRTUAL_MAP20)) + map->s_partition_type == UDF_VIRTUAL_MAP20 || + map->s_partition_type == UDF_METADATA_MAP25)) break; } @@ -1203,7 +1305,27 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) if (ret) goto out_bh; - ret = udf_load_vat(sb, i, type1_idx); + if (map->s_partition_type == UDF_METADATA_MAP25) { + ret = udf_load_metadata_files(sb, i); + if (ret) { + printk(KERN_ERR "UDF-fs: error loading MetaData " + "partition map %d\n", i); + goto out_bh; + } + } else { + ret = udf_load_vat(sb, i, type1_idx); + if (ret) + goto out_bh; + /* + * Mark filesystem read-only if we have a partition with + * virtual map since we don't handle writing to it (we + * overwrite blocks instead of relocating them). + */ + sb->s_flags |= MS_RDONLY; + printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only " + "because writing to pseudooverwrite partition is " + "not implemented.\n"); + } out_bh: /* In case loading failed, we handle cleanup in udf_fill_super */ brelse(bh); @@ -1302,6 +1424,50 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, } } map->s_partition_func = udf_get_pblock_spar15; + } else if (!strncmp(upm2->partIdent.ident, + UDF_ID_METADATA, + strlen(UDF_ID_METADATA))) { + struct udf_meta_data *mdata = + &map->s_type_specific.s_metadata; + struct metadataPartitionMap *mdm = + (struct metadataPartitionMap *) + &(lvd->partitionMaps[offset]); + udf_debug("Parsing Logical vol part %d " + "type %d id=%s\n", i, type, + UDF_ID_METADATA); + + map->s_partition_type = UDF_METADATA_MAP25; + map->s_partition_func = udf_get_pblock_meta25; + + mdata->s_meta_file_loc = + le32_to_cpu(mdm->metadataFileLoc); + mdata->s_mirror_file_loc = + le32_to_cpu(mdm->metadataMirrorFileLoc); + mdata->s_bitmap_file_loc = + le32_to_cpu(mdm->metadataBitmapFileLoc); + mdata->s_alloc_unit_size = + le32_to_cpu(mdm->allocUnitSize); + mdata->s_align_unit_size = + le16_to_cpu(mdm->alignUnitSize); + mdata->s_dup_md_flag = + mdm->flags & 0x01; + + udf_debug("Metadata Ident suffix=0x%x\n", + (le16_to_cpu( + ((__le16 *) + mdm->partIdent.identSuffix)[0]))); + udf_debug("Metadata part num=%d\n", + le16_to_cpu(mdm->partitionNum)); + udf_debug("Metadata part alloc unit size=%d\n", + le32_to_cpu(mdm->allocUnitSize)); + udf_debug("Metadata file loc=%d\n", + le32_to_cpu(mdm->metadataFileLoc)); + udf_debug("Mirror file loc=%d\n", + le32_to_cpu(mdm->metadataMirrorFileLoc)); + udf_debug("Bitmap file loc=%d\n", + le32_to_cpu(mdm->metadataBitmapFileLoc)); + udf_debug("Duplicate Flag: %d %d\n", + mdata->s_dup_md_flag, mdm->flags); } else { udf_debug("Unknown ident: %s\n", upm2->partIdent.ident); @@ -1600,8 +1766,8 @@ static void udf_open_lvid(struct super_block *sb) lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN; lvid->descTag.descCRC = cpu_to_le16( - udf_crc((char *)lvid + sizeof(tag), - le16_to_cpu(lvid->descTag.descCRCLength), 0)); + crc_itu_t(0, (char *)lvid + sizeof(tag), + le16_to_cpu(lvid->descTag.descCRCLength))); lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); mark_buffer_dirty(bh); @@ -1635,9 +1801,8 @@ static void udf_close_lvid(struct super_block *sb) lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); lvid->descTag.descCRC = cpu_to_le16( - udf_crc((char *)lvid + sizeof(tag), - le16_to_cpu(lvid->descTag.descCRCLength), - 0)); + crc_itu_t(0, (char *)lvid + sizeof(tag), + le16_to_cpu(lvid->descTag.descCRCLength))); lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); mark_buffer_dirty(bh); @@ -1663,6 +1828,7 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) static void udf_free_partition(struct udf_part_map *map) { int i; + struct udf_meta_data *mdata; if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) iput(map->s_uspace.s_table); @@ -1675,6 +1841,17 @@ static void udf_free_partition(struct udf_part_map *map) if (map->s_partition_type == UDF_SPARABLE_MAP15) for (i = 0; i < 4; i++) brelse(map->s_type_specific.s_sparing.s_spar_map[i]); + else if (map->s_partition_type == UDF_METADATA_MAP25) { + mdata = &map->s_type_specific.s_metadata; + iput(mdata->s_metadata_fe); + mdata->s_metadata_fe = NULL; + + iput(mdata->s_mirror_fe); + mdata->s_mirror_fe = NULL; + + iput(mdata->s_bitmap_fe); + mdata->s_bitmap_fe = NULL; + } } static int udf_fill_super(struct super_block *sb, void *options, int silent) @@ -1756,6 +1933,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) /* Fill in the rest of the superblock */ sb->s_op = &udf_sb_ops; + sb->s_export_op = &udf_export_ops; sb->dq_op = NULL; sb->s_dirt = 0; sb->s_magic = UDF_SUPER_MAGIC;