| #! /bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # Copyright (c) 2018 Jan Kara, SUSE. All Rights Reserved. |
| # |
| # FS QA Test 033 |
| # |
| # Test s_inodes_count overflow for huge filesystems. This bug was fixed |
| # by commit 4f2f76f75143 ("ext4: Forbid overflowing inode count when |
| # resizing".) |
| # |
| . ./common/preamble |
| _begin_fstest auto ioctl resize |
| |
| # Override the default cleanup function. |
| _cleanup() |
| { |
| umount $SCRATCH_MNT >/dev/null 2>&1 |
| _dmhugedisk_cleanup |
| cd / |
| rm -f $tmp.* |
| } |
| |
| # Import common functions. |
| . ./common/filter |
| . ./common/dmhugedisk |
| |
| _exclude_fs ext2 |
| _exclude_fs ext3 |
| |
| _require_scratch_nocheck |
| _require_dmhugedisk |
| _require_dumpe2fs |
| _require_test_program ext4_resize |
| |
| EXT4_RESIZE=$here/src/ext4_resize |
| |
| # Figure out whether device is large enough |
| devsize=$(blockdev --getsize64 $SCRATCH_DEV) |
| if [ $devsize -lt 4294967296 ]; then |
| _notrun "Too small scratch device, need at least 4G" |
| fi |
| |
| # Figure out block size |
| echo "Figure out block size" |
| _scratch_mkfs >/dev/null 2>&1 |
| _scratch_mount >> $seqres.full |
| blksz="$(_get_block_size $SCRATCH_MNT)" |
| _scratch_unmount |
| |
| inodes_per_group=$((blksz*8)) |
| group_blocks=$((blksz*8)) |
| |
| # Number of groups to overflow s_inodes_count |
| limit_groups=$(((1<<32)/inodes_per_group)) |
| |
| # Create device huge enough so that overflowing inode count is possible. |
| # Set chunk size to 16 sectors. Group descriptors with META_BG feature |
| # are rather sparse and that leads to huge overallocation especially with |
| # 1k blocksize. |
| echo "Format huge device" |
| _dmhugedisk_init $(((limit_groups + 16)*group_blocks*(blksz/512))) 16 |
| |
| # Start with small fs |
| group_count=$((limit_groups - 16)) |
| _mkfs_dev -N $((group_count*inodes_per_group)) -b $blksz \ |
| $DMHUGEDISK_DEV $((group_count*group_blocks)) |
| |
| _mount $DMHUGEDISK_DEV $SCRATCH_MNT |
| |
| echo "Initial fs dump" >> $seqres.full |
| $DUMPE2FS_PROG -h $DMHUGEDISK_DEV >> $seqres.full 2>&1 |
| |
| # This should fail, s_inodes_count would just overflow! |
| echo "Resizing to inode limit + 1..." |
| echo $EXT4_RESIZE $SCRATCH_MNT $((limit_groups*group_blocks)) >> $seqres.full 2>&1 |
| $EXT4_RESIZE $SCRATCH_MNT $((limit_groups*group_blocks)) >> $seqres.full 2>&1 |
| if [ $? -eq 0 ]; then |
| echo "Resizing succeeded but it should fail!" |
| exit |
| fi |
| |
| # This should succeed, we are maxing out inodes |
| echo "Resizing to max group count..." |
| echo $EXT4_RESIZE $SCRATCH_MNT $(((limit_groups-1)*group_blocks)) >> $seqres.full 2>&1 |
| $EXT4_RESIZE $SCRATCH_MNT $(((limit_groups-1)*group_blocks)) >> $seqres.full 2>&1 |
| if [ $? -ne 0 ]; then |
| echo "Resizing failed!" |
| exit |
| fi |
| |
| echo "Fs dump after resize" >> $seqres.full |
| $DUMPE2FS_PROG -h $DMHUGEDISK_DEV >> $seqres.full 2>&1 |
| |
| # This should fail, s_inodes_count would overflow by quite a bit! |
| echo "Resizing to device size..." |
| echo $EXT4_RESIZE $SCRATCH_MNT $(((limit_groups + 16)*group_blocks)) >> $seqres.full 2>&1 |
| $EXT4_RESIZE $SCRATCH_MNT $(((limit_groups + 16)*group_blocks)) >> $seqres.full 2>&1 |
| if [ $? -eq 0 ]; then |
| echo "Resizing succeeded but it should fail!" |
| exit |
| fi |
| |
| # success, all done |
| status=0 |
| exit |