All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leah Rumancik <leah.rumancik@gmail.com>
To: fstests@vger.kernel.org, linux-ext4@vger.kernel.org
Cc: Leah Rumancik <leah.rumancik@gmail.com>
Subject: [v2] ext4/310: test journal checkpoint ioctl
Date: Wed,  2 Jun 2021 22:17:04 +0000	[thread overview]
Message-ID: <20210602221704.2312894-1-leah.rumancik@gmail.com> (raw)

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>
---
 .gitignore               |   1 +
 src/Makefile             |   3 +-
 src/checkpoint_journal.c |  95 ++++++++++++++++++++++++++++++++
 tests/ext4/310           | 115 +++++++++++++++++++++++++++++++++++++++
 tests/ext4/310.out       |   2 +
 tests/ext4/group         |   1 +
 6 files changed, 216 insertions(+), 1 deletion(-)
 create mode 100644 src/checkpoint_journal.c
 create mode 100755 tests/ext4/310
 create mode 100644 tests/ext4/310.out

diff --git a/.gitignore b/.gitignore
index 4cc9c807..cb7e17bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -182,6 +182,7 @@
 /src/idmapped-mounts/mount-idmapped
 /src/log-writes/replay-log
 /src/perf/*.pyc
+/src/checkpoint_journal
 
 # Symlinked files
 /tests/generic/035.out
diff --git a/src/Makefile b/src/Makefile
index cc0b9579..e0e7006b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -17,7 +17,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
 	t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
 	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_get_file_time t_create_short_dirs t_create_long_dirs t_enospc \
+	checkpoint_journal
 
 LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
diff --git a/src/checkpoint_journal.c b/src/checkpoint_journal.c
new file mode 100644
index 00000000..0347e0c0
--- /dev/null
+++ b/src/checkpoint_journal.c
@@ -0,0 +1,95 @@
+#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>
+
+/*
+ * 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
+ */
+
+#if defined(__linux__) && !defined(EXT4_IOC_CHECKPOINT)
+#define EXT4_IOC_CHECKPOINT	_IOW('f', 43, __u32)
+#endif
+
+
+#if defined(__linux__) && !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;
+}
+
diff --git a/tests/ext4/310 b/tests/ext4/310
new file mode 100755
index 00000000..dd30c782
--- /dev/null
+++ b/tests/ext4/310
@@ -0,0 +1,115 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2021 Google, Inc. All Rights Reserved.
+#
+# FS QA Test No. 310
+#
+# 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
diff --git a/tests/ext4/310.out b/tests/ext4/310.out
new file mode 100644
index 00000000..7b9eaf78
--- /dev/null
+++ b/tests/ext4/310.out
@@ -0,0 +1,2 @@
+QA output created by 310
+Silence is golden
diff --git a/tests/ext4/group b/tests/ext4/group
index e7ad3c24..622590a9 100644
--- a/tests/ext4/group
+++ b/tests/ext4/group
@@ -60,3 +60,4 @@
 307 auto ioctl rw defrag
 308 auto ioctl rw prealloc quick defrag
 309 auto quick dir
+310 auto ioctl quick
-- 
2.32.0.rc1.229.g3e70b5a671-goog


             reply	other threads:[~2021-06-02 22:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-02 22:17 Leah Rumancik [this message]
2021-06-03  1:34 ` [v2] ext4/310: test journal checkpoint ioctl Darrick J. Wong
2021-06-04 20:12   ` Leah Rumancik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210602221704.2312894-1-leah.rumancik@gmail.com \
    --to=leah.rumancik@gmail.com \
    --cc=fstests@vger.kernel.org \
    --cc=linux-ext4@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.