Whamcloud - gitweb
Fix gcc -Wall warnings in libuuid
[tools/e2fsprogs.git] / lib / ext2fs / openfs.c
index 5050117..fc54afe 100644 (file)
@@ -39,11 +39,10 @@ blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
            (i < fs->super->s_first_meta_bg))
                return (group_block + i + 1);
 
-       bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
+       bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
        if (ext2fs_bg_has_super(fs, bg))
                has_super = 1;
-       ret_blk = (fs->super->s_first_data_block + has_super + 
-                  (bg * fs->super->s_blocks_per_group));
+       ret_blk = ext2fs_group_first_block(fs, bg) + has_super;
        /*
         * If group_block is not the normal value, we're trying to use
         * the backup group descriptors and superblock --- so use the
@@ -87,10 +86,13 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        errcode_t       retval;
        unsigned long   i;
        __u32           features;
-       int             j, groups_per_block, blocks_per_group, io_flags;
+       int             groups_per_block, blocks_per_group, io_flags;
        blk_t           group_block, blk;
        char            *dest, *cp;
+#ifdef WORDS_BIGENDIAN
        struct ext2_group_desc *gdp;
+       int             j;
+#endif
        
        EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
 
@@ -101,6 +103,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        memset(fs, 0, sizeof(struct struct_ext2_filsys));
        fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
        fs->flags = flags;
+       /* don't overwrite sb backups unless flag is explicitly cleared */
+       fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
        fs->umask = 022;
        retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
        if (retval)
@@ -176,12 +180,13 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        if (fs->orig_super)
                memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
 
-#ifdef EXT2FS_ENABLE_SWAPFS
-       if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ||
-           (fs->flags & EXT2_FLAG_SWAP_BYTES)) {
-               fs->flags |= EXT2_FLAG_SWAP_BYTES;
-
-               ext2fs_swap_super(fs->super);
+#ifdef WORDS_BIGENDIAN
+       fs->flags |= EXT2_FLAG_SWAP_BYTES;
+       ext2fs_swap_super(fs->super);
+#else
+       if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+               retval = EXT2_ET_UNIMPLEMENTED;
+               goto cleanup;
        }
 #endif
        
@@ -232,6 +237,10 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                retval = EXT2_ET_CORRUPT_SUPERBLOCK;
                goto cleanup;
        }
+       if (EXT2_INODE_SIZE(fs->super) < EXT2_GOOD_OLD_INODE_SIZE) {
+               retval = EXT2_ET_CORRUPT_SUPERBLOCK;
+               goto cleanup;
+       }
        fs->fragsize = EXT2_FRAG_SIZE(fs->super);
        fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
                                       EXT2_INODE_SIZE(fs->super) +
@@ -274,33 +283,53 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                                               blocks_per_group);
        fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
                                          EXT2_DESC_PER_BLOCK(fs->super));
-       retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
+       retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
                                &fs->group_desc);
        if (retval)
                goto cleanup;
        if (!group_block)
                group_block = fs->super->s_first_data_block;
        dest = (char *) fs->group_desc;
-       groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
+       groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
        for (i=0 ; i < fs->desc_blocks; i++) {
                blk = ext2fs_descriptor_block_loc(fs, group_block, i);
                retval = io_channel_read_blk(fs->io, blk, 1, dest);
                if (retval)
                        goto cleanup;
-#ifdef EXT2FS_ENABLE_SWAPFS
-               if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
-                       gdp = (struct ext2_group_desc *) dest;
-                       for (j=0; j < groups_per_block; j++)
-                               ext2fs_swap_group_desc(gdp++);
-               }
+#ifdef WORDS_BIGENDIAN
+               gdp = (struct ext2_group_desc *) dest;
+               for (j=0; j < groups_per_block; j++)
+                       ext2fs_swap_group_desc(gdp++);
 #endif
                dest += fs->blocksize;
        }
 
+       fs->stride = fs->super->s_raid_stride;
+
+       /*
+        * If recovery is from backup superblock, Clear _UNININT flags &
+        * reset bg_itable_unused to zero
+        */
+       if (superblock > 1 && EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+                                       EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+               struct ext2_group_desc *gd;
+               for (i = 0, gd = fs->group_desc; i < fs->group_desc_count;
+                    i++, gd++) {
+                       gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+                       gd->bg_flags &= ~EXT2_BG_INODE_UNINIT;
+                       gd->bg_itable_unused = 0;
+               }
+               ext2fs_mark_super_dirty(fs);
+       }
+
+       fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
        *ret_fs = fs;
        return 0;
 cleanup:
-       ext2fs_free(fs);
+       if (flags & EXT2_FLAG_NOFREE_ON_ERROR)
+               *ret_fs = fs;
+       else
+               ext2fs_free(fs);
        return retval;
 }