Whamcloud - gitweb
libext2fs: precompute FS UUID checksum seed
[tools/e2fsprogs.git] / lib / ext2fs / openfs.c
index 0cefe3f..3675518 100644 (file)
@@ -87,6 +87,8 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock,
  *                             features aren't supported.
  *     EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
  *     EXT2_FLAG_SKIP_MMP - Open without multi-mount protection check.
+ *     EXT2_FLAG_64BITS - Allow 64-bit bitfields (needed for large
+ *                             filesystems)
  */
 errcode_t ext2fs_open2(const char *name, const char *io_options,
                       int flags, int superblock,
@@ -142,7 +144,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                goto cleanup;
        fs->image_io = fs->io;
        fs->io->app_data = fs;
-       retval = ext2fs_get_memalign(SUPERBLOCK_SIZE, 512, &fs->super);
+       retval = io_channel_alloc_buf(fs->io, -SUPERBLOCK_SIZE, &fs->super);
        if (retval)
                goto cleanup;
        if (flags & EXT2_FLAG_IMAGE_FILE) {
@@ -261,6 +263,21 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                retval = EXT2_ET_CORRUPT_SUPERBLOCK;
                goto cleanup;
        }
+
+       /* Enforce the block group descriptor size */
+       if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) {
+               if (fs->super->s_desc_size != EXT2_MIN_DESC_SIZE_64BIT) {
+                       retval = EXT2_ET_BAD_DESC_SIZE;
+                       goto cleanup;
+               }
+       } else {
+               if (fs->super->s_desc_size &&
+                   fs->super->s_desc_size != EXT2_MIN_DESC_SIZE) {
+                       retval = EXT2_ET_BAD_DESC_SIZE;
+                       goto cleanup;
+               }
+       }
+
        fs->cluster_ratio_bits = fs->super->s_log_cluster_size -
                fs->super->s_log_block_size;
        if (EXT2_BLOCKS_PER_GROUP(fs->super) !=
@@ -298,6 +315,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                retval = EXT2_ET_CORRUPT_SUPERBLOCK;
                goto cleanup;
        }
+       /* Precompute the FS UUID to seed other checksums */
+       ext2fs_init_csum_seed(fs);
 
        /*
         * Read group descriptors
@@ -356,8 +375,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                        goto cleanup;
 #ifdef WORDS_BIGENDIAN
                for (j=0; j < groups_per_block; j++) {
-                       /* The below happens to work... be careful. */
-                       gdp = ext2fs_group_desc(fs, fs->group_desc, j);
+                       gdp = ext2fs_group_desc(fs, fs->group_desc,
+                                               i * groups_per_block + j);
                        ext2fs_swap_group_desc2(fs, gdp);
                }
 #endif
@@ -378,8 +397,12 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                        ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
                        ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
                        ext2fs_bg_itable_unused_set(fs, group, 0);
+                       /* The checksum will be reset later, but fix it here
+                        * anyway to avoid printing a lot of spurious errors. */
+                       ext2fs_group_desc_csum_set(fs, group);
                }
-               ext2fs_mark_super_dirty(fs);
+               if (fs->flags & EXT2_FLAG_RW)
+                       ext2fs_mark_super_dirty(fs);
        }
 
        fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;