• Theodore Ts'o's avatar
    ext4: fix online resize with very large inode tables · b93c9535
    Theodore Ts'o authored
    If a file system has a large number of inodes per block group, all of
    the metadata blocks in a flex_bg may be larger than what can fit in a
    single block group.  Unfortunately, ext4_alloc_group_tables() in
    resize.c was never tested to see if it would handle this case
    correctly, and there were a large number of bugs which caused the
    following sequence to result in a BUG_ON:
    
    kernel bug at fs/ext4/resize.c:409!
       ...
    call trace:
     [<ffffffff81256768>] ext4_flex_group_add+0x1448/0x1830
     [<ffffffff81257de2>] ext4_resize_fs+0x7b2/0xe80
     [<ffffffff8123ac50>] ext4_ioctl+0xbf0/0xf00
     [<ffffffff811c111d>] do_vfs_ioctl+0x2dd/0x4b0
     [<ffffffff811b9df2>] ? final_putname+0x22/0x50
     [<ffffffff811c1371>] sys_ioctl+0x81/0xa0
     [<ffffffff81676aa9>] system_call_fastpath+0x16/0x1b
    code: c8 4c 89 df e8 41 96 f8 ff 44 89 e8 49 01 c4 44 29 6d d4 0
    rip  [<ffffffff81254fa1>] set_flexbg_block_bitmap+0x171/0x180
    
    
    This can be reproduced with the following command sequence:
    
       mke2fs -t ext4 -i 4096 /dev/vdd 1G
       mount -t ext4 /dev/vdd /vdd
       resize2fs /dev/vdd 8G
    
    To fix this, we need to make sure the right thing happens when a block
    group's inode table straddles two block groups, which means the
    following bugs had to be fixed:
    
    1) Not clearing the BLOCK_UNINIT flag in the second block group in
       ext4_alloc_group_tables --- the was proximate cause of the BUG_ON.
    
    2) Incorrectly determining how many block groups contained contiguous
       free blocks in ext4_alloc_group_tables().
    
    3) Incorrectly setting the start of the next block range to be marked
       in use after a discontinuity in setup_new_flex_group_blocks().
    Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
    Cc: stable@vger.kernel.org
    b93c9535
resize.c 57.3 KB