mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
ext4: test journal checkpoint ioctl
Test for commit "ext4: add ioctl EXT4_IOC_CHECKPOINT". Tests journal checkpointing and journal erasing via EXT4_IOC_CHECKPOINT with flag EXT4_IOC_CHECKPOINT_FLAG_ZEROOUT set. Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com> Reviewed-by: Eryu Guan <guaneryu@gmail.com> Signed-off-by: Eryu Guan <guaneryu@gmail.com>
This commit is contained in:
@@ -61,6 +61,7 @@ tags
|
||||
/src/bulkstat_null_ocount
|
||||
/src/bulkstat_unlink_test
|
||||
/src/bulkstat_unlink_test_modified
|
||||
/src/checkpoint_journal
|
||||
/src/chprojid_fail
|
||||
/src/cloner
|
||||
/src/dbtest
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
|
||||
t_ext4_dax_journal_corruption t_ext4_dax_inline_corruption \
|
||||
t_ofd_locks t_mmap_collision mmap-write-concurrent \
|
||||
t_get_file_time t_create_short_dirs t_create_long_dirs t_enospc \
|
||||
t_mmap_writev_overlap
|
||||
t_mmap_writev_overlap checkpoint_journal
|
||||
|
||||
LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
|
||||
preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2021 Google
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* checkpoint_journal.c
|
||||
*
|
||||
* Flush journal log and checkpoint journal for ext4 file system and
|
||||
* optionally, issue discard or zeroout for the journal log blocks.
|
||||
*
|
||||
* Arguments:
|
||||
* 1) mount point for device
|
||||
* 2) flags (optional)
|
||||
* set --erase=discard to enable discarding journal blocks
|
||||
* set --erase=zeroout to enable zero-filling journal blocks
|
||||
* set --dry-run flag to only perform input checking
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <linux/fs.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#if !defined(EXT4_IOC_CHECKPOINT)
|
||||
#define EXT4_IOC_CHECKPOINT _IOW('f', 43, __u32)
|
||||
#endif
|
||||
|
||||
#if !defined(EXT4_IOC_CHECKPOINT_FLAG_DISCARD)
|
||||
#define EXT4_IOC_CHECKPOINT_FLAG_DISCARD 1
|
||||
#define EXT4_IOC_CHECKPOINT_FLAG_ZEROOUT 2
|
||||
#define EXT4_IOC_CHECKPOINT_FLAG_DRY_RUN 4
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int fd, c, ret = 0, option_index = 0;
|
||||
char* rpath;
|
||||
unsigned int flags = 0;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"dry-run", no_argument, 0, 'd'},
|
||||
{"erase", required_argument, 0, 'e'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* get optional flags */
|
||||
while ((c = getopt_long(argc, argv, "de:", long_options,
|
||||
&option_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
flags |= EXT4_IOC_CHECKPOINT_FLAG_DRY_RUN;
|
||||
break;
|
||||
case 'e':
|
||||
if (strcmp(optarg, "discard") == 0) {
|
||||
flags |= EXT4_IOC_CHECKPOINT_FLAG_DISCARD;
|
||||
} else if (strcmp(optarg, "zeroout") == 0) {
|
||||
flags |= EXT4_IOC_CHECKPOINT_FLAG_ZEROOUT;
|
||||
} else {
|
||||
fprintf(stderr, "Error: invalid erase option\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc - 1) {
|
||||
fprintf(stderr, "Error: invalid number of arguments\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get fd to file system */
|
||||
rpath = realpath(argv[optind], NULL);
|
||||
fd = open(rpath, O_RDONLY);
|
||||
free(rpath);
|
||||
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Error: unable to open device %s: %s\n",
|
||||
argv[optind], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, EXT4_IOC_CHECKPOINT, &flags);
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "checkpoint ioctl returned error: %s\n", strerror(errno));
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2021 Google, Inc. All Rights Reserved.
|
||||
#
|
||||
# FS QA Test No. 050
|
||||
#
|
||||
# Test checkpoint and zeroout of journal via ioctl EXT4_IOC_CHECKPOINT
|
||||
#
|
||||
|
||||
seq=`basename $0`
|
||||
seqres=$RESULT_DIR/$seq
|
||||
echo "QA output created by $seq"
|
||||
|
||||
status=1 # failure is the default!
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common/rc
|
||||
. ./common/filter
|
||||
|
||||
# remove previous $seqres.full before test
|
||||
rm -f $seqres.full
|
||||
|
||||
# real QA test starts here
|
||||
_supported_fs ext4
|
||||
|
||||
_require_scratch
|
||||
_require_command "$DEBUGFS_PROG" debugfs
|
||||
|
||||
checkpoint_journal=$here/src/checkpoint_journal
|
||||
_require_test_program "checkpoint_journal"
|
||||
|
||||
# convert output from stat<journal_inode> to list of block numbers
|
||||
get_journal_extents() {
|
||||
inode_info=$($DEBUGFS_PROG $SCRATCH_DEV -R "stat <8>" 2>> $seqres.full)
|
||||
echo -e "\nJournal info:" >> $seqres.full
|
||||
echo "$inode_info" >> $seqres.full
|
||||
|
||||
extents_line=$(echo "$inode_info" | awk '/EXTENTS:/{ print NR; exit }')
|
||||
get_extents=$(echo "$inode_info" | sed -n "$(($extents_line + 1))"p)
|
||||
|
||||
# get just the physical block numbers
|
||||
get_extents=$(echo "$get_extents" | perl -pe 's|\(.*?\):||g' | sed -e 's/, /\n/g' | perl -pe 's|(\d+)-(\d+)|\1 \2|g')
|
||||
|
||||
echo "$get_extents"
|
||||
}
|
||||
|
||||
|
||||
# checks all extents are zero'd out except for the superblock
|
||||
# arg 1: extents (output of get_journal_extents())
|
||||
check_extents() {
|
||||
echo -e "\nChecking extents:" >> $seqres.full
|
||||
echo "$1" >> $seqres.full
|
||||
|
||||
super_block="true"
|
||||
echo "$1" | while IFS= read line; do
|
||||
start_block=$(echo $line | cut -f1 -d' ')
|
||||
end_block=$(echo $line | cut -f2 -d' ' -s)
|
||||
|
||||
# if first block of journal, shouldn't be wiped
|
||||
if [ "$super_block" == "true" ]; then
|
||||
super_block="false"
|
||||
|
||||
#if super block only block in this extent, skip extent
|
||||
if [ -z "$end_block" ]; then
|
||||
continue;
|
||||
fi
|
||||
start_block=$(($start_block + 1))
|
||||
fi
|
||||
|
||||
if [ ! -z "$end_block" ]; then
|
||||
blocks=$(($end_block - $start_block + 1))
|
||||
else
|
||||
blocks=1
|
||||
fi
|
||||
|
||||
check=$(od $SCRATCH_DEV --skip-bytes=$(($start_block * $blocksize)) --read-bytes=$(($blocks * $blocksize)) -An -v | sed -e 's/[0 \t\n\r]//g')
|
||||
|
||||
[ ! -z "$check" ] && echo "error" && break
|
||||
done
|
||||
}
|
||||
|
||||
testdir="${SCRATCH_MNT}/testdir"
|
||||
|
||||
_scratch_mkfs_sized $((64 * 1024 * 1024)) >> $seqres.full 2>&1
|
||||
_require_metadata_journaling $SCRATCH_DEV
|
||||
_scratch_mount >> $seqres.full 2>&1
|
||||
blocksize=$(_get_block_size $SCRATCH_MNT)
|
||||
mkdir $testdir
|
||||
|
||||
# check if ioctl present, skip test if not present
|
||||
$checkpoint_journal $SCRATCH_MNT --dry-run || _notrun "journal checkpoint ioctl not present on device"
|
||||
|
||||
# create some files to add some entries to journal
|
||||
for i in {1..100}; do
|
||||
echo > $testdir/$i
|
||||
done
|
||||
|
||||
# make sure these files get to the journal
|
||||
sync --file-system $testdir/1
|
||||
|
||||
# call ioctl to checkpoint and zero-fill journal blocks
|
||||
$checkpoint_journal $SCRATCH_MNT --erase=zeroout || _fail "ioctl returned error"
|
||||
|
||||
extents=$(get_journal_extents)
|
||||
|
||||
# check journal blocks zeroed out
|
||||
ret=$(check_extents "$extents")
|
||||
[ "$ret" = "error" ] && _fail "Journal was not zero-filled"
|
||||
|
||||
_scratch_unmount >> $seqres.full 2>&1
|
||||
|
||||
echo "Silence is golden"
|
||||
|
||||
status=0
|
||||
exit
|
||||
@@ -0,0 +1,2 @@
|
||||
QA output created by 050
|
||||
Silence is golden
|
||||
@@ -52,6 +52,7 @@
|
||||
047 auto quick dax
|
||||
048 auto quick dir
|
||||
049 auto quick
|
||||
050 auto ioctl quick
|
||||
271 auto rw quick
|
||||
301 aio auto ioctl rw stress defrag
|
||||
302 aio auto ioctl rw stress defrag
|
||||
|
||||
Reference in New Issue
Block a user