Merge remote-tracking branches 'spi/fix/ep93xx', 'spi/fix/rockchip', 'spi/fix/sunxi...
[cascardo/linux.git] / fs / udf / super.c
index 36661ac..4942549 100644 (file)
 #define VSD_FIRST_SECTOR_OFFSET                32768
 #define VSD_MAX_SECTOR_OFFSET          0x800000
 
+/*
+ * Maximum number of Terminating Descriptor / Logical Volume Integrity
+ * Descriptor redirections. The chosen numbers are arbitrary - just that we
+ * hopefully don't limit any real use of rewritten inode on write-once media
+ * but avoid looping for too long on corrupted media.
+ */
+#define UDF_MAX_TD_NESTING 64
+#define UDF_MAX_LVID_NESTING 1000
+
 enum { UDF_MAX_LINKS = 0xffff };
 
 /* These are the "meat" - everything else is stuffing */
@@ -942,13 +951,13 @@ out2:
 }
 
 struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
-                                       u32 meta_file_loc, u32 partition_num)
+                                       u32 meta_file_loc, u32 partition_ref)
 {
        struct kernel_lb_addr addr;
        struct inode *metadata_fe;
 
        addr.logicalBlockNum = meta_file_loc;
-       addr.partitionReferenceNum = partition_num;
+       addr.partitionReferenceNum = partition_ref;
 
        metadata_fe = udf_iget_special(sb, &addr);
 
@@ -965,7 +974,8 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
        return metadata_fe;
 }
 
-static int udf_load_metadata_files(struct super_block *sb, int partition)
+static int udf_load_metadata_files(struct super_block *sb, int partition,
+                                  int type1_index)
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct udf_part_map *map;
@@ -975,20 +985,21 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
 
        map = &sbi->s_partmaps[partition];
        mdata = &map->s_type_specific.s_metadata;
+       mdata->s_phys_partition_ref = type1_index;
 
        /* metadata address */
        udf_debug("Metadata file location: block = %d part = %d\n",
-                 mdata->s_meta_file_loc, map->s_partition_num);
+                 mdata->s_meta_file_loc, mdata->s_phys_partition_ref);
 
        fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc,
-                                        map->s_partition_num);
+                                        mdata->s_phys_partition_ref);
        if (IS_ERR(fe)) {
                /* mirror file entry */
                udf_debug("Mirror metadata file location: block = %d part = %d\n",
-                         mdata->s_mirror_file_loc, map->s_partition_num);
+                         mdata->s_mirror_file_loc, mdata->s_phys_partition_ref);
 
                fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc,
-                                                map->s_partition_num);
+                                                mdata->s_phys_partition_ref);
 
                if (IS_ERR(fe)) {
                        udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
@@ -1006,7 +1017,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
        */
        if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
                addr.logicalBlockNum = mdata->s_bitmap_file_loc;
-               addr.partitionReferenceNum = map->s_partition_num;
+               addr.partitionReferenceNum = mdata->s_phys_partition_ref;
 
                udf_debug("Bitmap file location: block = %d part = %d\n",
                          addr.logicalBlockNum, addr.partitionReferenceNum);
@@ -1274,7 +1285,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, SPARABLE and METADATA partitions */
+       /* First scan for TYPE1 and SPARABLE partitions */
        for (i = 0; i < sbi->s_partitions; i++) {
                map = &sbi->s_partmaps[i];
                udf_debug("Searching map: (%d == %d)\n",
@@ -1324,7 +1335,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
                goto out_bh;
 
        if (map->s_partition_type == UDF_METADATA_MAP25) {
-               ret = udf_load_metadata_files(sb, i);
+               ret = udf_load_metadata_files(sb, i, type1_idx);
                if (ret < 0) {
                        udf_err(sb, "error loading MetaData partition map %d\n",
                                i);
@@ -1541,42 +1552,52 @@ out_bh:
 }
 
 /*
- * udf_load_logicalvolint
- *
+ * Find the prevailing Logical Volume Integrity Descriptor.
  */
 static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc)
 {
-       struct buffer_head *bh = NULL;
+       struct buffer_head *bh, *final_bh;
        uint16_t ident;
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct logicalVolIntegrityDesc *lvid;
+       int indirections = 0;
+
+       while (++indirections <= UDF_MAX_LVID_NESTING) {
+               final_bh = NULL;
+               while (loc.extLength > 0 &&
+                       (bh = udf_read_tagged(sb, loc.extLocation,
+                                       loc.extLocation, &ident))) {
+                       if (ident != TAG_IDENT_LVID) {
+                               brelse(bh);
+                               break;
+                       }
+
+                       brelse(final_bh);
+                       final_bh = bh;
 
-       while (loc.extLength > 0 &&
-              (bh = udf_read_tagged(sb, loc.extLocation,
-                                    loc.extLocation, &ident)) &&
-              ident == TAG_IDENT_LVID) {
-               sbi->s_lvid_bh = bh;
-               lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
+                       loc.extLength -= sb->s_blocksize;
+                       loc.extLocation++;
+               }
 
-               if (lvid->nextIntegrityExt.extLength)
-                       udf_load_logicalvolint(sb,
-                               leea_to_cpu(lvid->nextIntegrityExt));
+               if (!final_bh)
+                       return;
 
-               if (sbi->s_lvid_bh != bh)
-                       brelse(bh);
-               loc.extLength -= sb->s_blocksize;
-               loc.extLocation++;
+               brelse(sbi->s_lvid_bh);
+               sbi->s_lvid_bh = final_bh;
+
+               lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data;
+               if (lvid->nextIntegrityExt.extLength == 0)
+                       return;
+
+               loc = leea_to_cpu(lvid->nextIntegrityExt);
        }
-       if (sbi->s_lvid_bh != bh)
-               brelse(bh);
+
+       udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n",
+               UDF_MAX_LVID_NESTING);
+       brelse(sbi->s_lvid_bh);
+       sbi->s_lvid_bh = NULL;
 }
 
-/*
- * Maximum number of Terminating Descriptor redirections. The chosen number is
- * arbitrary - just that we hopefully don't limit any real use of rewritten
- * inode on write-once media but avoid looping for too long on corrupted media.
- */
-#define UDF_MAX_TD_NESTING 64
 
 /*
  * Process a main/reserve volume descriptor sequence.