Skip to content

Commit

Permalink
ext4: Test for s_inodes_count overflow during fs resize
Browse files Browse the repository at this point in the history
Test for overflow of s_inodes_count during filesystem resizing.

Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
  • Loading branch information
jankara authored and guaneryu committed Jun 3, 2018
1 parent 828f12b commit 678c3f4
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 0 deletions.
1 change: 1 addition & 0 deletions common/config
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export INDENT_PROG="$(type -P indent)"
export XFS_COPY_PROG="$(type -P xfs_copy)"
export FSTRIM_PROG="$(type -P fstrim)"
export DUMPE2FS_PROG="$(type -P dumpe2fs)"
export RESIZE2FS_PROG="$(type -P resize2fs)"
export FIO_PROG="$(type -P fio)"
export FILEFRAG_PROG="$(type -P filefrag)"
export E4DEFRAG_PROG="$(type -P e4defrag)"
Expand Down
123 changes: 123 additions & 0 deletions tests/ext4/033
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#! /bin/bash
# FS QA Test 033
#
# Test s_inodes_count overflow for huge filesystems. This bug was fixed
# by commit "ext4: Forbid overflowing inode count when resizing".
#
#-----------------------------------------------------------------------
# Copyright (c) 2018 Jan Kara, SUSE. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#-----------------------------------------------------------------------
#

seq=`basename $0`
seqres=$RESULT_DIR/$seq
echo "QA output created by $seq"

here=`pwd`
tmp=/tmp/$$
status=1 # failure is the default!
trap "_cleanup; exit \$status" 0 1 2 3 15

_cleanup()
{
umount $SCRATCH_MNT >/dev/null 2>&1
_dmhugedisk_cleanup
cd /
rm -f $tmp.*
}

# get standard environment, filters and checks
. ./common/rc
. ./common/filter
. ./common/dmhugedisk

# remove previous $seqres.full before test
rm -f $seqres.full

# real QA test starts here
_supported_fs ext4
_supported_os Linux
_require_scratch_nocheck
_require_dmhugedisk
_require_dumpe2fs
_require_command "$RESIZE2FS_PROG" resize2fs

# 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..."
$RESIZE2FS_PROG $DMHUGEDISK_DEV $((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..."
$RESIZE2FS_PROG $DMHUGEDISK_DEV $(((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..."
$RESIZE2FS_PROG $DMHUGEDISK_DEV >> $seqres.full 2>&1
if [ $? -eq 0 ]; then
echo "Resizing succeeded but it should fail!"
exit
fi

# success, all done
status=0
exit
6 changes: 6 additions & 0 deletions tests/ext4/033.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
QA output created by 033
Figure out block size
Format huge device
Resizing to inode limit + 1...
Resizing to max group count...
Resizing to device size...
1 change: 1 addition & 0 deletions tests/ext4/group
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
030 auto quick dax
031 auto quick dax
032 auto quick ioctl resize
033 auto ioctl resize
271 auto rw quick
301 aio auto ioctl rw stress defrag
302 aio auto ioctl rw stress defrag
Expand Down

0 comments on commit 678c3f4

Please sign in to comment.