Whamcloud - gitweb
Set pointer to NULL after ext2fs_free
[tools/e2fsprogs.git] / lib / ext2fs / openfs.c
index aac8894..a1a3517 100644 (file)
@@ -37,12 +37,19 @@ blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
                                     dgrp_t i)
 {
        int     bg;
-       int     has_super = 0;
+       int     has_super = 0, group_zero_adjust = 0;
        blk64_t ret_blk;
 
+       /*
+        * On a bigalloc FS with 1K blocks, block 0 is reserved for non-ext4
+        * stuff, so adjust for that if we're being asked for group 0.
+        */
+       if (i == 0 && fs->blocksize == 1024 && EXT2FS_CLUSTER_RATIO(fs) > 1)
+               group_zero_adjust = 1;
+
        if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
            (i < fs->super->s_first_meta_bg))
-               return (group_block + i + 1);
+               return group_block + i + 1 + group_zero_adjust;
 
        bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
        if (ext2fs_bg_has_super(fs, bg))
@@ -71,7 +78,7 @@ blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
                else
                        has_super = 0;
        }
-       return ret_blk + has_super;
+       return ret_blk + has_super + group_zero_adjust;
 }
 
 blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
@@ -113,6 +120,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        unsigned int    blocks_per_group, io_flags;
        blk64_t         group_block, blk;
        char            *dest, *cp;
+       int             group_zero_adjust = 0;
 #ifdef WORDS_BIGENDIAN
        unsigned int    groups_per_block;
        struct ext2_group_desc *gdp;
@@ -353,8 +361,19 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                goto cleanup;
        if (!group_block)
                group_block = fs->super->s_first_data_block;
+       /*
+        * On a FS with a 1K blocksize, block 0 is reserved for bootloaders
+        * so we must increment block numbers to any group 0 items.
+        *
+        * However, we cannot touch group_block directly because in the meta_bg
+        * case, the ext2fs_descriptor_block_loc2() function will interpret
+        * group_block != s_first_data_block to mean that we want to access the
+        * backup group descriptors.  This is not what we want if the caller
+        * set superblock == 0 (i.e. auto-detect the superblock), which is
+        * what's going on here.
+        */
        if (group_block == 0 && fs->blocksize == 1024)
-               group_block = 1; /* Deal with 1024 blocksize && bigalloc */
+               group_zero_adjust = 1;
        dest = (char *) fs->group_desc;
 #ifdef WORDS_BIGENDIAN
        groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
@@ -364,7 +383,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        else
                first_meta_bg = fs->desc_blocks;
        if (first_meta_bg) {
-               retval = io_channel_read_blk(fs->io, group_block+1,
+               retval = io_channel_read_blk(fs->io, group_block +
+                                            group_zero_adjust + 1,
                                             first_meta_bg, dest);
                if (retval)
                        goto cleanup;
@@ -430,10 +450,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 
        return 0;
 cleanup:
-       if (flags & EXT2_FLAG_NOFREE_ON_ERROR)
-               *ret_fs = fs;
-       else
+       if (!(flags & EXT2_FLAG_NOFREE_ON_ERROR)) {
                ext2fs_free(fs);
+               fs = NULL;
+       }
+       *ret_fs = fs;
        return retval;
 }