Merge tag '3.6-pci-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[cascardo/linux.git] / fs / udf / super.c
index 8d86a87..18fc038 100644 (file)
@@ -252,6 +252,63 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
        return 0;
 }
 
+static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
+{
+       int i;
+       int nr_groups = bitmap->s_nr_groups;
+       int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) *
+                                               nr_groups);
+
+       for (i = 0; i < nr_groups; i++)
+               if (bitmap->s_block_bitmap[i])
+                       brelse(bitmap->s_block_bitmap[i]);
+
+       if (size <= PAGE_SIZE)
+               kfree(bitmap);
+       else
+               vfree(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);
+       if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
+               iput(map->s_fspace.s_table);
+       if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
+               udf_sb_free_bitmap(map->s_uspace.s_bitmap);
+       if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
+               udf_sb_free_bitmap(map->s_fspace.s_bitmap);
+       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 void udf_sb_free_partitions(struct super_block *sb)
+{
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       int i;
+
+       for (i = 0; i < sbi->s_partitions; i++)
+               udf_free_partition(&sbi->s_partmaps[i]);
+       kfree(sbi->s_partmaps);
+       sbi->s_partmaps = NULL;
+}
+
 static int udf_show_options(struct seq_file *seq, struct dentry *root)
 {
        struct super_block *sb = root->d_sb;
@@ -1283,10 +1340,11 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
        BUG_ON(ident != TAG_IDENT_LVD);
        lvd = (struct logicalVolDesc *)bh->b_data;
        table_len = le32_to_cpu(lvd->mapTableLength);
-       if (sizeof(*lvd) + table_len > sb->s_blocksize) {
+       if (table_len > sb->s_blocksize - sizeof(*lvd)) {
                udf_err(sb, "error loading logical volume descriptor: "
                        "Partition table too long (%u > %lu)\n", table_len,
                        sb->s_blocksize - sizeof(*lvd));
+               ret = 1;
                goto out_bh;
        }
 
@@ -1331,8 +1389,10 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
                                                UDF_ID_SPARABLE,
                                                strlen(UDF_ID_SPARABLE))) {
                                if (udf_load_sparable_map(sb, map,
-                                   (struct sparablePartitionMap *)gpm) < 0)
+                                   (struct sparablePartitionMap *)gpm) < 0) {
+                                       ret = 1;
                                        goto out_bh;
+                               }
                        } else if (!strncmp(upm2->partIdent.ident,
                                                UDF_ID_METADATA,
                                                strlen(UDF_ID_METADATA))) {
@@ -1596,7 +1656,11 @@ static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
        /* responsible for finding the PartitionDesc(s) */
        if (!udf_process_sequence(sb, main_s, main_e, fileset))
                return 1;
-       return !udf_process_sequence(sb, reserve_s, reserve_e, fileset);
+       udf_sb_free_partitions(sb);
+       if (!udf_process_sequence(sb, reserve_s, reserve_e, fileset))
+               return 1;
+       udf_sb_free_partitions(sb);
+       return 0;
 }
 
 /*
@@ -1861,55 +1925,8 @@ u64 lvid_get_unique_id(struct super_block *sb)
        return ret;
 }
 
-static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
-{
-       int i;
-       int nr_groups = bitmap->s_nr_groups;
-       int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) *
-                                               nr_groups);
-
-       for (i = 0; i < nr_groups; i++)
-               if (bitmap->s_block_bitmap[i])
-                       brelse(bitmap->s_block_bitmap[i]);
-
-       if (size <= PAGE_SIZE)
-               kfree(bitmap);
-       else
-               vfree(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);
-       if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
-               iput(map->s_fspace.s_table);
-       if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
-               udf_sb_free_bitmap(map->s_uspace.s_bitmap);
-       if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
-               udf_sb_free_bitmap(map->s_fspace.s_bitmap);
-       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)
 {
-       int i;
        int ret;
        struct inode *inode = NULL;
        struct udf_options uopt;
@@ -1974,7 +1991,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sb->s_op = &udf_sb_ops;
        sb->s_export_op = &udf_export_ops;
 
-       sb->s_dirt = 0;
        sb->s_magic = UDF_SUPER_MAGIC;
        sb->s_time_gran = 1000;
 
@@ -1987,6 +2003,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                        if (!silent)
                                pr_notice("Rescanning with blocksize %d\n",
                                          UDF_DEFAULT_BLOCKSIZE);
+                       brelse(sbi->s_lvid_bh);
+                       sbi->s_lvid_bh = NULL;
                        uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
                        ret = udf_load_vrs(sb, &uopt, silent, &fileset);
                }
@@ -2072,9 +2090,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 error_out:
        if (sbi->s_vat_inode)
                iput(sbi->s_vat_inode);
-       if (sbi->s_partitions)
-               for (i = 0; i < sbi->s_partitions; i++)
-                       udf_free_partition(&sbi->s_partmaps[i]);
 #ifdef CONFIG_UDF_NLS
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
                unload_nls(sbi->s_nls_map);
@@ -2082,8 +2097,7 @@ error_out:
        if (!(sb->s_flags & MS_RDONLY))
                udf_close_lvid(sb);
        brelse(sbi->s_lvid_bh);
-
-       kfree(sbi->s_partmaps);
+       udf_sb_free_partitions(sb);
        kfree(sbi);
        sb->s_fs_info = NULL;
 
@@ -2096,10 +2110,6 @@ void _udf_err(struct super_block *sb, const char *function,
        struct va_format vaf;
        va_list args;
 
-       /* mark sb error */
-       if (!(sb->s_flags & MS_RDONLY))
-               sb->s_dirt = 1;
-
        va_start(args, fmt);
 
        vaf.fmt = fmt;
@@ -2128,16 +2138,12 @@ void _udf_warn(struct super_block *sb, const char *function,
 
 static void udf_put_super(struct super_block *sb)
 {
-       int i;
        struct udf_sb_info *sbi;
 
        sbi = UDF_SB(sb);
 
        if (sbi->s_vat_inode)
                iput(sbi->s_vat_inode);
-       if (sbi->s_partitions)
-               for (i = 0; i < sbi->s_partitions; i++)
-                       udf_free_partition(&sbi->s_partmaps[i]);
 #ifdef CONFIG_UDF_NLS
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
                unload_nls(sbi->s_nls_map);
@@ -2145,7 +2151,7 @@ static void udf_put_super(struct super_block *sb)
        if (!(sb->s_flags & MS_RDONLY))
                udf_close_lvid(sb);
        brelse(sbi->s_lvid_bh);
-       kfree(sbi->s_partmaps);
+       udf_sb_free_partitions(sb);
        kfree(sb->s_fs_info);
        sb->s_fs_info = NULL;
 }
@@ -2161,7 +2167,6 @@ static int udf_sync_fs(struct super_block *sb, int wait)
                 * the buffer for IO
                 */
                mark_buffer_dirty(sbi->s_lvid_bh);
-               sb->s_dirt = 0;
                sbi->s_lvid_dirty = 0;
        }
        mutex_unlock(&sbi->s_alloc_mutex);