]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: fix uninit block calculation when inodes_per_block < first_ino
authorTheodore Ts'o <tytso@mit.edu>
Sun, 29 Jul 2012 17:34:01 +0000 (13:34 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 29 Jul 2012 17:34:01 +0000 (13:34 -0400)
The following commands:

dd if=/dev/zero of=/tmp/foo count=1 ibs=$(( 256 * 1024 * 1024 ))
mke2fs -N 256 -t ext4 /tmp/foo

... will cause mke2fs to write until it fills the device.  The cause
for this is that the explicit request for 256 inodes causes the number
of inodes per block group to be 8.  The ext2fs_initialize() function
assumed that all of the reserved inodes would be in the first block
group, which is not true in this case.  This caused the number of
uninitialized inodes in the first block group to be negative, which
then resulted in mke2fs trying to zero out a very large number of
blocks.  Oops.

Addresses-Sourceforge-Bug: #3528892

Reported-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
lib/ext2fs/initialize.c

index b06371cf4c17569cf8a5574974d989806cbdd170..5a6f8ea22c206f7be162ef3e135f5c885b0c9d64 100644 (file)
@@ -98,6 +98,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
        int             csum_flag;
        int             bigalloc_flag;
        int             io_flags;
+       unsigned        reserved_inos;
        char            *buf = 0;
        char            c;
 
@@ -439,6 +440,7 @@ ipg_retry:
        free_blocks = 0;
        csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
                                               EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+       reserved_inos = super->s_first_ino;
        for (i = 0; i < fs->group_desc_count; i++) {
                /*
                 * Don't set the BLOCK_UNINIT group for the last group
@@ -450,8 +452,15 @@ ipg_retry:
                                                    EXT2_BG_BLOCK_UNINIT);
                        ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
                        numblocks = super->s_inodes_per_group;
-                       if (i == 0)
-                               numblocks -= super->s_first_ino;
+                       if (reserved_inos) {
+                               if (numblocks > reserved_inos) {
+                                       numblocks -= reserved_inos;
+                                       reserved_inos = 0;
+                               } else {
+                                       reserved_inos -= numblocks;
+                                       numblocks = 0;
+                               }
+                       }
                        ext2fs_bg_itable_unused_set(fs, i, numblocks);
                }
                numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);