--- linux/fs/udf/inode.c	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/fs/udf/inode.c	2007-03-01 19:13:09.000000000 +0200
@@ -1171,6 +1171,7 @@
 		case ICBTAG_FILE_TYPE_REALTIME:
 		case ICBTAG_FILE_TYPE_REGULAR:
 		case ICBTAG_FILE_TYPE_UNDEF:
+		case ICBTAG_FILE_TYPE_VAT20:
 		{
 			if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
 				inode->i_data.a_ops = &udf_adinicb_aops;
@@ -1208,6 +1209,21 @@
 			inode->i_mode = S_IFLNK|S_IRWXUGO;
 			break;
 		}
+		case ICBTAG_FILE_TYPE_MAIN:
+		{
+			udf_debug("METADATA FILE-----\n");
+			break;
+		}
+		case ICBTAG_FILE_TYPE_MIRROR:
+		{
+			udf_debug("METADATA MIRROR FILE-----\n");
+			break;
+		}
+		case ICBTAG_FILE_TYPE_BITMAP:
+		{
+			udf_debug("METADATA BITMAP FILE-----\n");
+			break;
+		}
 		default:
 		{
 			printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown file type=%d\n",
@@ -1823,6 +1839,14 @@
 			*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
 			break;
 		}
+		case ICBTAG_FLAG_AD_IN_ICB:
+		{
+			etype = EXT_RECORDED_ALLOCATED;
+			eloc->logicalBlockNum = UDF_I_LOCATION(inode).logicalBlockNum;
+			eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
+			*elen = UDF_I_LENALLOC(inode);
+			break;
+		}
 		default:
 		{
 			udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
--- linux/fs/udf/osta_udf.h	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/fs/udf/osta_udf.h	2007-02-06 19:13:52.000000000 +0200
@@ -149,7 +149,7 @@
 	__le32		locSparingTable[4];
 } __attribute__ ((packed));
 
-/* Metadata Partition Map (UDF 2.4.0 2.2.10) */
+/* Metadata Partition Map (UDF 2.50 2.2.10) */
 struct metadataPartitionMap
 {
 	uint8_t		partitionMapType;
--- linux/fs/udf/partition.c	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/fs/udf/partition.c	2007-02-06 19:13:52.000000000 +0200
@@ -219,3 +219,155 @@
 
 	return 0;
 }
+
+static uint32_t udf_get_addr_from_short_ad(struct super_block *sb, short_ad *p, int desc_count, int block)
+{
+	int i;
+	int crt_blocks=0;
+
+	if (p == NULL)
+		return 0xFFFFFFFF;
+	
+	udf_debug("SHORT AD SEARCHING BLOCK %d\n",block);
+	
+	for (i=0; i<desc_count; i++)
+	{
+		uint32_t extent_len;
+		int blocks_in_extent;
+
+		extent_len = le32_to_cpu(p[i].extLength);
+		/* keep least 30 sign bits (ecma 167 14.14.1.1) */
+		extent_len &= ((1<<30) - 1);
+	
+		blocks_in_extent = extent_len>>sb->s_blocksize_bits;
+		if ((crt_blocks + blocks_in_extent) > block)
+			break;
+		crt_blocks += blocks_in_extent;
+	}
+
+	/* not found */
+	if (i == desc_count)
+	{
+		udf_debug("block %d not found in allocation desc\n",block);
+		return 0xFFFFFFFF;
+	}
+
+	/* block offset in current extent */
+	block -= crt_blocks;
+
+	block = le32_to_cpu(p[i].extPosition) + block;
+	return block;
+}
+
+static uint32_t udf_try_read_meta(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset, struct inode* inode)
+{
+	uint32_t metad_blk;
+	uint32_t phy_blk;
+	struct buffer_head *bh = NULL;
+	
+	metad_blk = 0;
+	
+	switch(UDF_I_ALLOCTYPE(inode))
+	{
+		case ICBTAG_FLAG_AD_SHORT:
+		{
+			short_ad *sa;
+			int len;
+			udf_debug("ICB flag is ICBTAG_FLAG_AD_SHORT\n");
+			len = UDF_I_LENALLOC(inode)/sizeof(short_ad);
+			if (len == 0)
+			{
+				udf_error(sb, __FUNCTION__, "Inode has 0 alloc\n");
+				return 0xFFFFFFFF;
+			}
+			sa = (short_ad*)(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode));
+			if (sa == NULL)
+			{
+				udf_error(sb, __FUNCTION__, "Inode has null alloc desc\n");
+				return 0xFFFFFFFF;
+			}
+				
+			metad_blk = udf_get_addr_from_short_ad(sb, sa, len, block);
+		}
+		break;
+		case ICBTAG_FLAG_AD_LONG:
+			udf_debug("ICB flag is ICBTAG_FLAG_AD_LONG\n");
+			return 0xFFFFFFFF;
+			break;
+		case ICBTAG_FLAG_AD_IN_ICB:
+			udf_debug("ICB flag is ICBTAG_FLAG_AD_IN_ICB\n");
+			break;
+		case ICBTAG_FLAG_AD_EXTENDED:
+			udf_debug("ICB flag is ICBTAG_FLAG_AD_EXTENDED !!!!!!!\n");
+			return 0xFFFFFFFF;
+			break;
+	}
+
+
+	/* map to sparable/physical partition desc */
+	phy_blk = udf_get_pblock(sb, metad_blk, UDF_SB_PARTNUM(sb, partition), offset);
+
+	udf_debug("block=%d partition=%d realblk=%d physical=%d\n",block, partition, metad_blk, phy_blk);
+
+	/* try to read from the physical location */
+	bh = udf_tread(sb, phy_blk);
+
+	if (bh)
+	{
+		udf_debug("udf_try_read_meta SUCCEEDED\n");
+		brelse(bh);
+		return phy_blk;
+	}
+	else
+	{
+		udf_debug("udf_try_read_meta FAILED\n");
+		return 0xFFFFFFFF;
+	}
+}
+
+uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset)
+{
+	uint32_t retblk;
+	struct inode *inode;
+
+	udf_debug("READING from METADATA\n");
+
+	inode = UDF_SB_TYPEMETA(sb,partition).s_metadata_fe;
+
+	if (inode)
+	{
+		retblk = udf_try_read_meta(sb, block, partition, offset, inode);
+
+		if(retblk == 0xFFFFFFFF)
+		{
+			udf_warning(sb, __FUNCTION__, "OOOOPS ... error reading from METADATA, trying to read from MIRROR");
+
+			inode = UDF_SB_TYPEMETA(sb,partition).s_mirror_fe;
+
+			if (inode == NULL)
+			{
+				udf_error(sb, __FUNCTION__, "mirror inode is null");
+				return 0xFFFFFFFF;
+			}
+
+			retblk = udf_try_read_meta(sb, block, partition, offset, inode);
+		}
+	}
+	else 	/* metadata inode is NULL */
+	{
+		udf_warning(sb, __FUNCTION__, "metadata inode is null. hmmm, will try reading from mirror file");
+
+		inode = UDF_SB_TYPEMETA(sb,partition).s_mirror_fe;
+
+		if (inode == NULL)
+		{
+			udf_error(sb, __FUNCTION__, "mirror inode null too??? bad, bad, bad! how did we get here???");
+			return 0xFFFFFFFF;
+		}
+
+		retblk = udf_try_read_meta(sb, block, partition, offset, inode);
+	}
+
+	return retblk;
+}
+
--- linux/fs/udf/super.c	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/fs/udf/super.c	2007-03-01 19:07:42.000000000 +0200
@@ -695,11 +695,6 @@
 					udf_debug("Anchor found at block %d, location mismatch %d.\n",
 						last[i], location);
 			}
-			else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE)
-			{
-				lastblock = last[i];
-				UDF_SB_ANCHOR(sb)[3] = 512;
-			}
 			else
 			{
 				if (last[i] < 256 || !(bh = sb_bread(sb, last[i] - 256)))
@@ -746,7 +741,24 @@
 
 	if (!lastblock)
 	{
-		/* We havn't found the lastblock. check 312 */
+		/* We haven't found the lastblock. Check for VAT presence and then at location 512 for AVDP */
+		if (UDF_SB_LASTBLOCK(sb) && (bh = sb_bread(sb, UDF_SB_LASTBLOCK(sb))))
+		{
+			uint8_t fileType;
+			
+			ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
+			fileType = ((struct fileEntry *)bh->b_data)->icbTag.fileType;
+			brelse(bh);
+
+			if ((ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE) &&
+				(fileType == ICBTAG_FILE_TYPE_VAT20 || fileType == ICBTAG_FILE_TYPE_VAT15))
+			{
+				lastblock = UDF_SB_LASTBLOCK(sb);
+				UDF_SB_ANCHOR(sb)[3] = 512;
+			}
+		}
+		
+		/* We haven't found the lastblock. check 312 */
 		if ((bh = sb_bread(sb, 312 + UDF_SB_SESSION(sb))))
 		{
 			ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
@@ -913,6 +925,103 @@
 	}
 }
 
+static int
+udf_load_metadata_file_entries(struct super_block *sb, int part, kernel_lb_addr *fileset)
+{
+	kernel_lb_addr addr;
+	int fe_error = 0;
+
+	/* metadata address */
+	addr.logicalBlockNum = UDF_SB_TYPEMETA(sb, part).s_meta_file_loc;
+	addr.partitionReferenceNum = UDF_SB_PARTNUM(sb, part);
+	
+	udf_debug("block=%d part=%d\n",addr.logicalBlockNum,addr.partitionReferenceNum);
+	
+	UDF_SB_TYPEMETA(sb, part).s_metadata_fe = udf_iget(sb, addr);
+	
+	if (UDF_SB_TYPEMETA(sb,part).s_metadata_fe == NULL)
+	{
+		udf_warning(sb, __FUNCTION__, "metadata inode efe not found, will try mirror inode.");
+		fe_error = 1;
+		/*goto error_exit;*/
+	}
+
+	/* mirror file entry */
+	addr.logicalBlockNum = UDF_SB_TYPEMETA(sb, part).s_mirror_file_loc;
+	addr.partitionReferenceNum = UDF_SB_PARTNUM(sb, part);
+	
+	udf_debug("block=%d part=%d\n",addr.logicalBlockNum,addr.partitionReferenceNum);
+
+	UDF_SB_TYPEMETA(sb, part).s_mirror_fe = udf_iget(sb, addr);
+	
+	if (UDF_SB_TYPEMETA(sb, part).s_mirror_fe == NULL)
+	{
+		if (fe_error)
+		{
+			udf_error(sb, __FUNCTION__, "mirror inode efe not found and metadata inode is missing too, exiting...");
+			goto error_exit;
+		}
+		else
+			udf_warning(sb, __FUNCTION__, "mirror inode efe not found but metadata inode is OK");
+	}
+
+	/* 
+	   bitmap file entry
+	   Note: Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102) 
+	*/
+	if (UDF_SB_TYPEMETA(sb, part).s_bitmap_file_loc != 0xFFFFFFFF)
+	{
+		addr.logicalBlockNum = UDF_SB_TYPEMETA(sb, part).s_bitmap_file_loc;
+		addr.partitionReferenceNum = UDF_SB_PARTNUM(sb, part);
+		
+		udf_debug("block=%d part=%d\n",addr.logicalBlockNum,addr.partitionReferenceNum);
+	
+		UDF_SB_TYPEMETA(sb, part).s_bitmap_fe = udf_iget(sb, addr);
+		
+		if (UDF_SB_TYPEMETA(sb,part).s_bitmap_fe == NULL)
+		{
+			if (sb->s_flags & MS_RDONLY)
+				udf_warning(sb, __FUNCTION__, "bitmap inode efe not found but it's ok since the disc is mounted read-only");
+			else
+			{
+				udf_error(sb, __FUNCTION__, "bitmap inode efe not found and attempted read-write mount");
+				goto error_exit;
+			}
+		}
+	}
+	udf_debug("udf_load_metadata_file_entries Ok\n");
+	
+	return 0;
+
+error_exit:
+	return 1;
+}
+
+static void
+udf_release_metadata(struct super_block *sb)
+{
+	int i;
+	/* release metadata */
+	udf_debug("Releasing metadata!\n");
+	for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
+	{
+		if(UDF_SB_PARTTYPE(sb,i) == UDF_METADATA_MAP25)
+		{
+			if(UDF_SB_TYPEMETA(sb,i).s_metadata_fe)
+				iput(UDF_SB_TYPEMETA(sb,i).s_metadata_fe);
+			UDF_SB_TYPEMETA(sb,i).s_metadata_fe = NULL;
+
+			if(UDF_SB_TYPEMETA(sb,i).s_mirror_fe)
+				iput(UDF_SB_TYPEMETA(sb,i).s_mirror_fe);
+			UDF_SB_TYPEMETA(sb,i).s_mirror_fe = NULL;
+
+			if(UDF_SB_TYPEMETA(sb,i).s_bitmap_fe)
+				iput(UDF_SB_TYPEMETA(sb,i).s_bitmap_fe);
+			UDF_SB_TYPEMETA(sb,i).s_bitmap_fe = NULL;
+		}
+	}
+}
+
 static void 
 udf_load_fileset(struct super_block *sb, struct buffer_head *bh, kernel_lb_addr *root)
 {
@@ -932,6 +1041,7 @@
 udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
 {
 	struct partitionDesc *p;
+	int matched_part_desc=0;
 	int i;
 
 	p = (struct partitionDesc *)bh->b_data;
@@ -942,6 +1052,8 @@
 			UDF_SB_PARTMAPS(sb)[i].s_partition_num, le16_to_cpu(p->partitionNumber));
 		if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber))
 		{
+			matched_part_desc++;
+			udf_debug("Found desc for part %d id(%d)\n",i,UDF_SB_PARTMAPS(sb)[i].s_partition_num);
 			UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */
 			UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation);
 			if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY)
@@ -1010,19 +1122,22 @@
 					}
 				}
 			}
-			break;
+			/* break; */
 		}
 	}
-	if (i == UDF_SB_NUMPARTS(sb))
+	if (matched_part_desc == 0)
 	{
 		udf_debug("Partition (%d) not found in partition map\n", le16_to_cpu(p->partitionNumber));
 	}
 	else
 	{
+		for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
+		{
 		udf_debug("Partition (%d:%d type %x) starts at physical %d, block length %d\n",
 			le16_to_cpu(p->partitionNumber), i, UDF_SB_PARTTYPE(sb,i),
 			UDF_SB_PARTROOT(sb,i), UDF_SB_PARTLEN(sb,i));
 	}
+	}
 }
 
 static int 
@@ -1059,7 +1174,9 @@
 					UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP15;
 					UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt15;
 				}
-				else if (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0200)
+				else if ((le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0200) ||
+						 (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0250) ||
+						 (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0260))
 				{
 					UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP20;
 					UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt20;
@@ -1092,6 +1209,29 @@
 				}
 				UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_spar15;
 			}
+			else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_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);
+				
+				UDF_SB_PARTTYPE(sb,i) = UDF_METADATA_MAP25;
+				UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_meta25;
+
+				UDF_SB_TYPEMETA(sb,i).s_meta_file_loc = le32_to_cpu(mdm->metadataFileLoc);
+				UDF_SB_TYPEMETA(sb,i).s_mirror_file_loc = le32_to_cpu(mdm->metadataMirrorFileLoc);
+				UDF_SB_TYPEMETA(sb,i).s_bitmap_file_loc = le32_to_cpu(mdm->metadataBitmapFileLoc);
+				UDF_SB_TYPEMETA(sb,i).s_alloc_unit_size = le32_to_cpu(mdm->allocUnitSize);
+				UDF_SB_TYPEMETA(sb,i).s_align_unit_size = le16_to_cpu(mdm->alignUnitSize);
+				UDF_SB_TYPEMETA(sb,i).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", UDF_SB_TYPEMETA(sb,i).s_dup_md_flag, mdm->flags);
+			}
 			else
 			{
 				udf_debug("Unknown ident: %s\n", upm2->partIdent.ident);
@@ -1302,7 +1442,15 @@
 		return 0;
 	}
 	else 
+	{
+		/* 
+			usefull to know the last written block because it helps in udf_find_anchor() 
+			especially when the anchor is not at block 256
+		*/
+		if (!UDF_SB_LASTBLOCK(sb))
+			UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb);
 		return !block;
+	}
 }
 
 static int
@@ -1406,7 +1554,7 @@
 					pos = udf_block_map(UDF_SB_VAT(sb), 0);
 					bh = sb_bread(sb, pos);
 					UDF_SB_TYPEVIRT(sb,i).s_start_offset =
-						le16_to_cpu(((struct virtualAllocationTable20 *)bh->b_data + udf_ext0_offset(UDF_SB_VAT(sb)))->lengthHeader) +
+						le16_to_cpu(((struct virtualAllocationTable20 *)(bh->b_data + udf_ext0_offset(UDF_SB_VAT(sb))))->lengthHeader) +
 							udf_ext0_offset(UDF_SB_VAT(sb));
 					UDF_SB_TYPEVIRT(sb,i).s_num_entries = (UDF_SB_VAT(sb)->i_size -
 						UDF_SB_TYPEVIRT(sb,i).s_start_offset) >> 2;
@@ -1626,6 +1774,17 @@
 		sb->s_flags |= MS_RDONLY;
 	}
 
+	/* check for metadata partitions and load the associated data if there's any found */
+	for (i = 0; i < UDF_SB_NUMPARTS(sb); i++)
+	{
+		if( (UDF_SB_PARTTYPE(sb, i) == UDF_METADATA_MAP25) &&
+			udf_load_metadata_file_entries(sb, i, &fileset) )
+		{
+			printk( "UDF-fs: error loading MetaData partition map %d\n", i );
+			goto error_out;
+		}
+	}
+	
 	if ( udf_find_fileset(sb, &fileset, &rootdir) )
 	{
 		printk("UDF-fs: No fileset found\n");
@@ -1635,10 +1794,36 @@
 	if (!silent)
 	{
 		kernel_timestamp ts;
+		int k;
+		uint8_t vid[128] = "";
+
+		/* 
+		    If there is a VAT table the Logical Volume Identifier from the table
+		    is used instead of the corresponding field in the Logical Volume Descriptor
+		*/
+		for (k=0; k<UDF_SB_NUMPARTS(sb); k++)
+		{
+			if (UDF_SB_PARTTYPE(sb,k) == UDF_VIRTUAL_MAP20)
+			{
+				struct buffer_head *bh = NULL;
+				uint32_t pos;
+
+				pos = udf_block_map(UDF_SB_VAT(sb), 0);
+				bh = sb_bread(sb, pos);
+				memcpy (vid, ((struct virtualAllocationTable20 *)(bh->b_data + udf_ext0_offset(UDF_SB_VAT(sb))))->logicalVolIdent, 128);
+				vid[127] = '\0';		/* just to be sure */
+				brelse(bh);
+				break;
+			}
+		}
+		
+		if (vid[0] == '\0')
+			memcpy (vid, UDF_SB_VOLIDENT(sb), 32);
+
 		udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb));
 		udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
 			UDFFS_VERSION, UDFFS_DATE,
-			UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
+			vid, ts.year, ts.month, ts.day, ts.hour, ts.minute,
 			ts.typeAndTimezone);
 	}
 	if (!(sb->s_flags & MS_RDONLY))
@@ -1667,6 +1852,7 @@
 	return 0;
 
 error_out:
+	udf_release_metadata(sb);
 	if (UDF_SB_VAT(sb))
 		iput(UDF_SB_VAT(sb));
 	if (UDF_SB_NUMPARTS(sb))
@@ -1744,6 +1930,9 @@
 udf_put_super(struct super_block *sb)
 {
 	int i;
+	udf_debug("udf_put_super!!!!!\n");
+
+	udf_release_metadata(sb);
 
 	if (UDF_SB_VAT(sb))
 		iput(UDF_SB_VAT(sb));
--- linux/include/linux/udf_fs.h	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/include/linux/udf_fs.h	2007-03-01 18:46:20.000000000 +0200
@@ -32,8 +32,8 @@
 #define UDF_PREALLOCATE
 #define UDF_DEFAULT_PREALLOC_BLOCKS	8
 
-#define UDFFS_DATE			"2004/29/09"
-#define UDFFS_VERSION			"0.9.8.1"
+#define UDFFS_DATE			"2007/01/03"
+#define UDFFS_VERSION		"0.9.9.1"
 
 #undef UDFFS_DEBUG
 
--- linux/include/linux/udf_fs_sb.h	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/include/linux/udf_fs_sb.h	2007-02-27 21:05:43.000000000 +0200
@@ -23,6 +23,21 @@
 #define UDF_VIRTUAL_MAP15		0x1512U
 #define UDF_VIRTUAL_MAP20		0x2012U
 #define UDF_SPARABLE_MAP15		0x1522U
+#define UDF_METADATA_MAP25		0x2511U
+
+
+struct udf_meta_data
+{
+	__u32	s_meta_file_loc;
+	__u32	s_mirror_file_loc;
+	__u32	s_bitmap_file_loc;
+	__u32	s_alloc_unit_size;
+	__u16	s_align_unit_size;
+	__u8 	s_dup_md_flag;
+	struct inode *s_metadata_fe;
+	struct inode *s_mirror_fe;
+	struct inode *s_bitmap_fe;
+};
 
 struct udf_sparing_data
 {
@@ -64,6 +79,7 @@
 	{
 		struct udf_sparing_data s_sparing;
 		struct udf_virtual_data s_virtual;
+		struct udf_meta_data s_metadata;
 	} s_type_specific;
 	__u32	(*s_partition_func)(struct super_block *, __u32, __u16, __u32);
 	__u16	s_volumeseqnum;
--- linux/fs/udf/udf_sb.h	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/fs/udf/udf_sb.h	2007-02-06 19:13:52.000000000 +0200
@@ -4,7 +4,7 @@
 /* Since UDF 2.01 is ISO 13346 based... */
 #define UDF_SUPER_MAGIC			0x15013346
 
-#define UDF_MAX_READ_VERSION		0x0201
+#define UDF_MAX_READ_VERSION		0x0250
 #define UDF_MAX_WRITE_VERSION		0x0201
 
 #define UDF_FLAG_USE_EXTENDED_FE	0
@@ -43,6 +43,7 @@
 {\
 	if (UDF_SB(X))\
 	{\
+		if (UDF_SB_PARTMAPS(X))\
 		kfree(UDF_SB_PARTMAPS(X));\
 		UDF_SB_PARTMAPS(X) = NULL;\
 	}\
@@ -115,6 +116,7 @@
 #define UDF_SB_PARTNUM(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_partition_num )
 #define UDF_SB_TYPESPAR(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_sparing )
 #define UDF_SB_TYPEVIRT(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_virtual )
+#define UDF_SB_TYPEMETA(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_metadata )
 #define UDF_SB_PARTFUNC(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_partition_func )
 #define UDF_SB_PARTFLAGS(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_partition_flags )
 #define UDF_SB_BITMAP(X,Y,Z,I)			( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap[I] )
--- linux/fs/udf/udfdecl.h	2007-02-04 20:44:54.000000000 +0200
+++ linux-2.6.20.1/fs/udf/udfdecl.h	2007-02-06 19:13:52.000000000 +0200
@@ -126,6 +126,7 @@
 extern uint32_t udf_get_pblock_virt15(struct super_block *, uint32_t, uint16_t, uint32_t);
 extern uint32_t udf_get_pblock_virt20(struct super_block *, uint32_t, uint16_t, uint32_t);
 extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t, uint32_t);
+extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t, uint32_t);
 extern int udf_relocate_blocks(struct super_block *, long, long *);
 
 /* unicode.c */

 	  	 

