Code:
--- linux/fs/udf/inode.c 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/inode.c 2006-03-20 12:51:12.000000000 +0200
@@ -1212,6 +1212,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",
--- linux/fs/udf/osta_udf.h 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/osta_udf.h 2006-03-20 12:51:12.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 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/partition.c 2006-03-20 12:51:12.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");
+ udf_release_data(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 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/super.c 2006-04-26 12:41:54.000000000 +0300
@@ -909,6 +909,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)
{
@@ -928,6 +1025,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;
@@ -938,6 +1036,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)
@@ -1006,19 +1106,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
@@ -1088,6 +1191,29 @@
}
UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_spar15;
}
+ else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA)))
+ {
+ udf_debug("Parsing Logical vol part %d type %d id=%s\n",i,type,UDF_ID_METADATA);
+ struct metadataPartitionMap *mdm = (struct metadataPartitionMap *)&(lvd->partitionMaps[offset]);
+
+ 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);
@@ -1298,7 +1424,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
@@ -1620,6 +1754,17 @@
goto error_out;
}
+ /* 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");
@@ -1661,6 +1806,7 @@
return 0;
error_out:
+ udf_release_metadata(sb);
if (UDF_SB_VAT(sb))
iput(UDF_SB_VAT(sb));
if (UDF_SB_NUMPARTS(sb))
@@ -1738,6 +1884,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 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/include/udf_fs.h 2006-04-26 12:32:42.000000000 +0300
@@ -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 "2005/21/07"
+#define UDFFS_VERSION "0.9.9"
#undef UDFFS_DEBUG
--- linux/include/linux/udf_fs_sb.h 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/include/udf_fs_sb.h 2006-03-20 12:51:12.000000000 +0200
@@ -23,6 +23,22 @@
#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 +80,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 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/udf_sb.h 2006-03-20 12:51:12.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 2006-03-20 07:53:29.000000000 +0200
+++ ../../root/work/udf-mod_2_6-rel/udfdecl.h 2006-03-20 12:51:12.000000000 +0200
@@ -127,6 +127,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 */ I hope this help you a bit.