udf: Skip mirror metadata FE loading when metadata FE is ok
authorNamjae Jeon <linkinjeon@gmail.com>
Sun, 23 Oct 2011 10:28:32 +0000 (19:28 +0900)
committerJan Kara <jack@suse.cz>
Mon, 31 Oct 2011 22:49:30 +0000 (23:49 +0100)
It is not necessary to load mirror metadata FE when metadata FE is OK.  So try
to read it only the first time udf_get_pblock_meta25() fails to map the block
from metadata FE.

Signed-off-by: Ashish Sangwan <ashishsangwan2@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/udf/partition.c
fs/udf/super.c
fs/udf/udf_sb.h
fs/udf/udfdecl.h

index f3e472c..b526f25 100644 (file)
@@ -321,8 +321,14 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
        /* We shouldn't mount such media... */
        BUG_ON(!inode);
        retblk = udf_try_read_meta(inode, block, partition, offset);
-       if (retblk == 0xFFFFFFFF) {
+       if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) {
                udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n");
+               if (!mdata->s_mirror_loaded_flag) {
+                       mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
+                               mdata->s_mirror_file_loc, map->s_partition_num);
+                       mdata->s_mirror_loaded_flag = 1;
+               }
+
                inode = mdata->s_mirror_fe;
                if (!inode)
                        return 0xFFFFFFFF;
index e58123a..dfe043a 100644 (file)
@@ -826,59 +826,57 @@ out1:
        return ret;
 }
 
+struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
+                                       u32 meta_file_loc, u32 partition_num)
+{
+       struct kernel_lb_addr addr;
+       struct inode *metadata_fe;
+
+       addr.logicalBlockNum = meta_file_loc;
+       addr.partitionReferenceNum = partition_num;
+
+       metadata_fe = udf_iget(sb, &addr);
+
+       if (metadata_fe == NULL)
+               udf_warn(sb, "metadata inode efe not found\n");
+       else if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) {
+               udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n");
+               iput(metadata_fe);
+               metadata_fe = NULL;
+       }
+
+       return metadata_fe;
+}
+
 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;
        struct 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_meta_file_loc, map->s_partition_num);
 
-       mdata->s_metadata_fe = udf_iget(sb, &addr);
+       mdata->s_metadata_fe = udf_find_metadata_inode_efe(sb,
+               mdata->s_meta_file_loc, map->s_partition_num);
 
        if (mdata->s_metadata_fe == NULL) {
-               udf_warn(sb, "metadata inode efe not found, will try mirror inode\n");
-               fe_error = 1;
-       } else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type !=
-                ICBTAG_FLAG_AD_SHORT) {
-               udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n");
-               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;
+               /* mirror file entry */
+               udf_debug("Mirror metadata file location: block = %d part = %d\n",
+                         mdata->s_mirror_file_loc, map->s_partition_num);
 
-       udf_debug("Mirror metadata file location: block = %d part = %d\n",
-                 addr.logicalBlockNum, addr.partitionReferenceNum);
+               mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
+                       mdata->s_mirror_file_loc, map->s_partition_num);
 
-       mdata->s_mirror_fe = udf_iget(sb, &addr);
-
-       if (mdata->s_mirror_fe == NULL) {
-               if (fe_error) {
-                       udf_err(sb, "mirror inode efe not found and metadata inode is missing too, exiting...\n");
-                       goto error_exit;
-               } else
-                       udf_warn(sb, "mirror inode efe not found, but metadata inode is OK\n");
-       } else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type !=
-                ICBTAG_FLAG_AD_SHORT) {
-               udf_warn(sb, "mirror inode efe does not have short allocation descriptors!\n");
-               iput(mdata->s_mirror_fe);
-               mdata->s_mirror_fe = NULL;
-               if (fe_error)
+               if (mdata->s_mirror_fe == NULL) {
+                       udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
                        goto error_exit;
+               }
        }
 
        /*
index 4858c19..a3146b0 100644 (file)
@@ -61,6 +61,7 @@ struct udf_meta_data {
        __u32   s_alloc_unit_size;
        __u16   s_align_unit_size;
        __u8    s_dup_md_flag;
+       __u8    s_mirror_loaded_flag;
        struct inode *s_metadata_fe;
        struct inode *s_mirror_fe;
        struct inode *s_bitmap_fe;
index f3d4498..79aae3f 100644 (file)
@@ -135,6 +135,8 @@ static inline void udf_updated_lvid(struct super_block *sb)
        UDF_SB(sb)->s_lvid_dirty = 1;
 }
 extern u64 lvid_get_unique_id(struct super_block *sb);
+struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
+                                       u32 meta_file_loc, u32 partition_num);
 
 /* namei.c */
 extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,