fstests: log-writes: Add support to output human readable flags
PATCH 1/3 fstests: log-writes: Add support to output human readable flags
Also change the flag numeric output to hex.
--- src/log-writes/log-writes.c | 70 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-)
src/log-writes/log-writes.c +63 -7
@@ -120,6 +120,58 @@ int log_discard(struct log *log, struct log_write_entry *entry)return 0 ; } +#define DEFINE_LOG_FLAGS_STR_ENTRY (x) \ + {LOG_##x##_FLAG, #x} + +struct flags_to_str_entry { +u64 flags; +const char *str; +} log_flags_table[] = { +DEFINE_LOG_FLAGS_STR_ENTRY (FLUSH ), +DEFINE_LOG_FLAGS_STR_ENTRY (FUA ), +DEFINE_LOG_FLAGS_STR_ENTRY (DISCARD ), +DEFINE_LOG_FLAGS_STR_ENTRY (MARK ) +}; + +#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0])) +#define LOG_FLAGS_BUF_SIZE 128 +/* +* Convert numeric flags to human readable flags. +* @flags: numeric flags +* @buf: output buffer for human readable string. +* must have enough space (LOG_FLAGS_BUF_SIZE) to contain all +* the string +*/ +static void entry_flags_to_str (u64 flags,char *buf) +{ +int empty =1 ; +int left_len; +int i; + + buf[0 ] ='\0' ; +for (i =0 ; i <ARRAY_SIZE (log_flags_table); i++) { +if (flags & log_flags_table[i].flags) { +if (!empty) +strncat (buf,"|" ,LOG_FLAGS_BUF_SIZE ); + empty =0 ; +strncat (buf, log_flags_table[i].str,LOG_FLAGS_BUF_SIZE ); + flags &= ~log_flags_table[i].flags; + } + } +if (flags) { +if (!empty) +strncat (buf,"|" ,LOG_FLAGS_BUF_SIZE ); + empty =0 ; + left_len =LOG_FLAGS_BUF_SIZE -strnlen (buf, +LOG_FLAGS_BUF_SIZE ); +if (left_len >0 ) +snprintf (buf +strnlen (buf,LOG_FLAGS_BUF_SIZE ), + left_len,"UNKNOWN.0x%llx" , flags); + } +if (empty) +strncpy (buf,"NONE" ,LOG_FLAGS_BUF_SIZE ); +} +/* * @log: the log we are replaying. * @entry: entry to be replayed.
@@ -179,6 +231,7 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry,size_t read_size = read_data ? log->sectorsize :sizeof (struct log_write_entry );char *buf; +char flags_buf[LOG_FLAGS_BUF_SIZE ];ssize_t ret;off_t offset;int skip =0 ;
@@ -210,19 +263,20 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, log->cur_pos += read_size; } + flags =le64_to_cpu (entry->flags); +entry_flags_to_str (flags, flags_buf); skip =log_should_skip (log, entry);if (log_writes_verbose >1 || (log_writes_verbose && !skip)) { -printf ("%s %d@%llu: sector %llu, size %llu, flags %llu\n" , +printf ("%s %d@%llu: sector %llu, size %llu, flags 0x%llx(%s)\n" , skip ?"skipping" :"replaying" , (int )log->cur_entry -1 , log->cur_pos / log->sectorsize, (unsigned long long )le64_to_cpu (entry->sector), (unsigned long long )size, - (unsigned long long )le64_to_cpu (entry->flags)); + (unsigned long long )flags, flags_buf); }if (!size)return 0 ; - flags =le64_to_cpu (entry->flags);if (flags &LOG_DISCARD_FLAG )return log_discard (log, entry);
@@ -301,7 +355,7 @@ int log_seek_entry(struct log *log, u64 entry_num)return -1 ; }if (log_writes_verbose >1 ) - printf("seek entry %d@%llu: %llu, size %llu, flags %llu\n", + printf("seek entry %d@%llu: %llu, size %llu, flags 0x%llx\n", (int)i, log->cur_pos / log->sectorsize, (unsigned long long)le64_to_cpu(entry.sector), (unsigned long long)le64_to_cpu(entry.nr_sectors),
@@ -339,6 +393,7 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry,size_t read_size = read_data ? log->sectorsize :sizeof (struct log_write_entry );u64 flags; +char flags_buf[LOG_FLAGS_BUF_SIZE ];ssize_t ret;if (log->cur_entry >= log->nr_entries)
@@ -366,14 +421,15 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, }else { log->cur_pos += read_size; } + flags =le64_to_cpu (entry->flags); +entry_flags_to_str (flags, flags_buf);if (log_writes_verbose >1 ) -printf ("seek entry %d@%llu: %llu, size %llu, flags %llu\n" , +printf ("seek entry %d@%llu: %llu, size %llu, flags 0x%llx(%s)\n" , (int )log->cur_entry -1 , log->cur_pos / log->sectorsize, (unsigned long long )le64_to_cpu (entry->sector), (unsigned long long )le64_to_cpu (entry->nr_sectors), - (unsigned long long )le64_to_cpu (entry->flags)); + (unsigned long long )flags, flags_buf); - flags =le64_to_cpu (entry->flags); read_size =le64_to_cpu (entry->nr_sectors) * log->sectorsize;if (!read_size || (flags &LOG_DISCARD_FLAG ))return 0 ;
Signature · 1 line
2.15.1
PATCH 2/3 fstests: log-writes: Add support for METADATA flag
--- src/log-writes/log-writes.c | 3 ++- src/log-writes/log-writes.h | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-)
src/log-writes/log-writes.c +2 -1
@@ -130,7 +130,8 @@ struct flags_to_str_entry {DEFINE_LOG_FLAGS_STR_ENTRY (FLUSH ),DEFINE_LOG_FLAGS_STR_ENTRY (FUA ),DEFINE_LOG_FLAGS_STR_ENTRY (DISCARD ), - DEFINE_LOG_FLAGS_STR_ENTRY(MARK) +DEFINE_LOG_FLAGS_STR_ENTRY (MARK ), + DEFINE_LOG_FLAGS_STR_ENTRY(METADATA) };#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0]))
src/log-writes/log-writes.h +5 -4
@@ -20,10 +20,11 @@ typedef __u32 u32;/* * Constants copied from kernel file drivers/md/dm-log-writes.c */ -#define LOG_FLUSH_FLAG (1 << 0) -#define LOG_FUA_FLAG (1 << 1) -#define LOG_DISCARD_FLAG (1 << 2) -#define LOG_MARK_FLAG (1 << 3) +#define LOG_FLUSH_FLAG (1 << 0) +#define LOG_FUA_FLAG (1 << 1) +#define LOG_DISCARD_FLAG (1 << 2) +#define LOG_MARK_FLAG (1 << 3) +#define LOG_METADATA_FLAG (1 << 4)#define WRITE_LOG_VERSION 1#define WRITE_LOG_MAGIC 0x6a736677736872
Signature · 1 line
2.15.1
Re: [PATCH 2/3] fstests: log-writes: Add support for METADATA flag
Quoted 1 line · Qu Wenruo
Signed-off-by Qu Wenruo <[email protected]>
Quoted 42 lines
--- src/log-writes/log-writes.c | 3 ++- src/log-writes/log-writes.h | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-)src/log-writes/log-writes.c +2
-1@@ -130,7 +130,8 @@ struct flags_to_str_entry {DEFINE_LOG_FLAGS_STR_ENTRY (FLUSH ),DEFINE_LOG_FLAGS_STR_ENTRY (FUA ),DEFINE_LOG_FLAGS_STR_ENTRY (DISCARD ), - DEFINE_LOG_FLAGS_STR_ENTRY(MARK) +DEFINE_LOG_FLAGS_STR_ENTRY (MARK ), + DEFINE_LOG_FLAGS_STR_ENTRY(METADATA) };#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0]))src/log-writes/log-writes.h +5
-5@@ -20,10 +20,11 @@ typedef __u32 u32;/* * Constants copied from kernel file drivers/md/dm-log-writes.c */ -#define LOG_FLUSH_FLAG (1 << 0) -#define LOG_FUA_FLAG (1 << 1) -#define LOG_DISCARD_FLAG (1 << 2) -#define LOG_MARK_FLAG (1 << 3) +#define LOG_FLUSH_FLAG (1 << 0) +#define LOG_FUA_FLAG (1 << 1) +#define LOG_DISCARD_FLAG (1 << 2) +#define LOG_MARK_FLAG (1 << 3) +#define LOG_METADATA_FLAG (1 << 4)#define WRITE_LOG_VERSION 1#define WRITE_LOG_MAGIC 0x6a736677736872 --2.15.1
RFC PATCH 3/3 fstests: generic: Check the fs after each FUA writes
In reply to Qu WenruoBasic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.
---
In my test, xfs and btrfs survives while ext4 would report error during fsck.
My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
--- common/dmlogwrites | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481.out | 2 + tests/generic/group | 1 + 4 files changed, 246 insertions(+) create mode 100755 tests/generic/481 create mode 100644 tests/generic/481.out
common/dmlogwrites +119 -0
@@ -126,3 +126,122 @@ _log_writes_cleanup() $UDEV_SETTLE_PROG >/dev/null 2>&1 _log_writes_remove } + +# Convert log writes mark to entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_mark_to_entry_number() +{ + local _mark=$1 + local ret + + [ -z "$_mark" ] && _fatal \ + "mark must be given for _log_writes_mark_to_entry_number" + + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --end-mark $_mark 2> /dev/null) + [ -z "$ret" ] && return + ret=$(echo "$ret" | cut -f1 -d\@) + echo "mark $_mark has entry number $ret" >> $seqres.full + echo "$ret" +} + +# Find next fua write entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_find_next_fua() +{ + local _start_entry=$1 + local ret + + [ -z "$_start_entry" ] && _start_entry=0 + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --next-fua --start-entry $_start_entry 2> /dev/null) + [ -z "$ret" ] && return + + ret=$(echo "$ret" | cut -f1 -d\@) + echo "next fua is entry number $ret" >> $seqres.full + echo "$ret" +} + +# Replay log range to specified entry +# $1: End entry. The entry with this number *WILL* be replayed +# $2: Start entry. If not specified, start from the first entry. +# $3: Verbose. If set to 'y' do verbose output +_log_writes_replay_log_entry_range() +{ + local _end=$1 + local _start=$2 + local _verbose=$3 + + [ -z "$_end" ] && _fatal \ + "end entry must be specified for _log_writes_replay_log_entry_range" + + [ "x$verbose" == "xy" ] && _verbose="-v" + [ -z "$_start" ] && _start=0 + [ "$_start" -gt "$_end" ] && _fatal \ + "wrong parameter order for _log_writes_replay_log_entry_range:start=$_start end=$_end" + + # To ensure we replay the last entry, for _start == 0 case, + # we need to manually increase the end entry number to ensure + # it's played + echo "=== replay from $_start to $_end ===" >> $seqres.full + $here/src/log-writes/replay-log --log $LOGWRITES_DEV \ + --replay $SCRATCH_DEV --start-entry $_start \ + --limit $(($_end - $_start + 1)) $_verbose \ + >> $seqres.full 2>&1 + [ $? -ne 0 ] && _fatal "replay failed" +} + +_log_writes_cleanup_snapshot() +{ + $UDEV_SETTLE_PROG > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_SNAPSHOT_NAME" > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_ORIGIN_NAME" > /dev/null 2>&1 +} + +# Helper to create snapshot of a the replayed device +# Useful for journal based filesystem such as XFS and Ext4 to replay +# their journal without touching the replay device, so that we can +# continue replaying other than replay from the beginning. +# $1: Snapshot device +_log_writes_create_snapshot() +{ + _require_dm_target snapshot + + local snapshot_dev=$1 + local cow_base="" + + [ -z "$snapshot_dev" ] && _fatal \ + "@device must be specified for _log_writes_create_snapshot" + local size=$(blockdev --getsz $SCRATCH_DEV) + [ -z "$size" ] && _fatal \ + "failed to get device size for _log_writes_create_snapshot" + + _log_writes_cleanup_snapshot + + DMLOGWRITES_ORIGIN_NAME="log-writes-origin" + DMLOGWRITES_SNAPSHOT_NAME="log-writes-snapshot" + DMLOGWRITES_ORIGIN_TABLE="0 $size snapshot-origin $SCRATCH_DEV" + DMLOGWRITES_SNAPSHOT_TABLE="0 $size snapshot /dev/mapper/$DMLOGWRITES_ORIGIN_NAME $snapshot_dev N 512" + + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_ORIGIN_NAME --table "$DMLOGWRITES_ORIGIN_TABLE" ||\ + _fatal "failed to create snapshot-origin of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_SNAPSHOT_NAME --table "$DMLOGWRITES_SNAPSHOT_TABLE" ||\ + _fatal "failed to create snapshot of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 +} + +_log_writes_mount_snapshot() +{ + _scratch_options mount + $MOUNT_PROG -t $FSTYP `_common_dev_mount_options $*` $SCRATCH_OPTIONS \ + "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME" $SCRATCH_MNT +} + +_log_writes_unmount_snapshot() +{ + $UMOUNT_PROG $SCRATCH_MNT +} +
tests/generic/481 new file +124 -0
124 lines not on this page · raw message
tests/generic/481.out new file +2 -0
@@ -0,0 +1,2 @@ +QA output created by 481 +Silence is golden
tests/generic/group +1 -0
@@ -483,3 +483,4 @@ 478 auto quick 479 auto quick metadata 480 auto quick metadata +481 auto
Signature · 1 line
2.15.1
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
Quoted 10 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
Definitely not allowed.
I suppose you could either create an LVM volume on scratch for the tested fs and leave room for a snapshot target on scratch or do something similar with LOGWRITES_DEV, which may be more appropriate in the context of common/dmlogwrites helper.
I see you are posting this generic series independently from the btrsf specific series, but the two series have conflicting changes. How do intent for the final merged result to look like?
Quoted 57 lines
--- common/dmlogwrites | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481.out | 2 + tests/generic/group | 1 + 4 files changed, 246 insertions(+) create mode 100755 tests/generic/481 create mode 100644 tests/generic/481.outcommon/dmlogwrites +40
-0@@ -126,3 +126,122 @@ _log_writes_cleanup() $UDEV_SETTLE_PROG >/dev/null 2>&1 _log_writes_remove } + +# Convert log writes mark to entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_mark_to_entry_number() +{ + local _mark=$1 + local ret + + [ -z "$_mark" ] && _fatal \ + "mark must be given for _log_writes_mark_to_entry_number" + + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --end-mark $_mark 2> /dev/null) + [ -z "$ret" ] && return + ret=$(echo "$ret" | cut -f1 -d\@) + echo "mark $_mark has entry number $ret" >> $seqres.full + echo "$ret" +} + +# Find next fua write entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_find_next_fua() +{ + local _start_entry=$1 + local ret + + [ -z "$_start_entry" ] && _start_entry=0 + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --next-fua --start-entry $_start_entry 2> /dev/null) + [ -z "$ret" ] && return + + ret=$(echo "$ret" | cut -f1 -d\@) + echo "next fua is entry number $ret" >> $seqres.full + echo "$ret" +} + +# Replay log range to specified entry +# $1: End entry. The entry with this number *WILL* be replayed +# $2: Start entry. If not specified, start from the first entry. +# $3: Verbose. If set to 'y' do verbose output
common/dmlogwrites _log_writes_cleanup() · line 178
Quoted 10 lines
common/dmlogwrites +10
-0+_log_writes_replay_log_entry_range() +{ + local _end=$1 + local _start=$2 + local _verbose=$3 + + [ -z "$_end" ] && _fatal \ + "end entry must be specified for _log_writes_replay_log_entry_range" + + [ "x$verbose" == "xy" ] && _verbose="-v"
Those xy tricks are really not needed with bash.
"$verbose" == "y" is nicer and better.
Quoted 167 lines
common/dmlogwrites +69
-0+ [ -z "$_start" ] && _start=0 + [ "$_start" -gt "$_end" ] && _fatal \ + "wrong parameter order for _log_writes_replay_log_entry_range:start=$_start end=$_end" + + # To ensure we replay the last entry, for _start == 0 case, + # we need to manually increase the end entry number to ensure + # it's played + echo "=== replay from $_start to $_end ===" >> $seqres.full + $here/src/log-writes/replay-log --log $LOGWRITES_DEV \ + --replay $SCRATCH_DEV --start-entry $_start \ + --limit $(($_end - $_start + 1)) $_verbose \ + >> $seqres.full 2>&1 + [ $? -ne 0 ] && _fatal "replay failed" +} + +_log_writes_cleanup_snapshot() +{ + $UDEV_SETTLE_PROG > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_SNAPSHOT_NAME" > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_ORIGIN_NAME" > /dev/null 2>&1 +} + +# Helper to create snapshot of a the replayed device +# Useful for journal based filesystem such as XFS and Ext4 to replay +# their journal without touching the replay device, so that we can +# continue replaying other than replay from the beginning. +# $1: Snapshot device +_log_writes_create_snapshot() +{ + _require_dm_target snapshot + + local snapshot_dev=$1 + local cow_base="" + + [ -z "$snapshot_dev" ] && _fatal \ + "@device must be specified for _log_writes_create_snapshot" + local size=$(blockdev --getsz $SCRATCH_DEV) + [ -z "$size" ] && _fatal \ + "failed to get device size for _log_writes_create_snapshot" + + _log_writes_cleanup_snapshot + + DMLOGWRITES_ORIGIN_NAME="log-writes-origin" + DMLOGWRITES_SNAPSHOT_NAME="log-writes-snapshot" + DMLOGWRITES_ORIGIN_TABLE="0 $size snapshot-origin $SCRATCH_DEV" + DMLOGWRITES_SNAPSHOT_TABLE="0 $size snapshot /dev/mapper/$DMLOGWRITES_ORIGIN_NAME $snapshot_dev N 512" + + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_ORIGIN_NAME --table "$DMLOGWRITES_ORIGIN_TABLE" ||\ + _fatal "failed to create snapshot-origin of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_SNAPSHOT_NAME --table "$DMLOGWRITES_SNAPSHOT_TABLE" ||\ + _fatal "failed to create snapshot of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 +} + +_log_writes_mount_snapshot() +{ + _scratch_options mount + $MOUNT_PROG -t $FSTYP `_common_dev_mount_options $*` $SCRATCH_OPTIONS \ + "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME" $SCRATCH_MNT +} + +_log_writes_unmount_snapshot() +{ + $UMOUNT_PROG $SCRATCH_MNT +} +tests/generic/481 new file +92
-0@@ -0,0 +1,124 @@ +#! /bin/bash +# FS QA Test 481 +# +# Test filesystem consistency after each FUA operation +# +# Will do log replay and check the filesystem. +# +#----------------------------------------------------------------------- +# Copyright (c) 2018 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() +{ + cd / + $KILLALL_PROG -KILL -q $FSSTRESS_PROG &> /dev/null + _log_writes_cleanup_snapshot &> /dev/null + _log_writes_cleanup &> /dev/null + + # We use $TEST_DEV as snapshot COW device, which can't be + # mounted/recognized as normal fs, need to recreate it + # or fstest will complain about it + _mkfs_dev $TEST_DEV > /dev/null 2>&1 + rm -f $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/dmlogwrites + +# remove previous $seqres.full before test +rm -f $seqres.full + +# real QA test starts here + +# Modify as appropriate. +_supported_fs generic +_supported_os Linux + +_require_command "$KILLALL_PROG" killall +# Use $TEST_DEV as snapshot CoW device +_require_test +# Use $SCRATCH_DEV as replay device +_require_scratch +# and we need extra device as log device +_require_log_writes + + +workload=$(( 512 * $LOAD_FACTOR )) +nr_threads=$(($($here/src/feature -o) * $LOAD_FACTOR)) + +_test_unmount +_log_writes_init +_log_writes_mkfs >> $seqres.full 2>&1 +_log_writes_mark mkfs + +_log_writes_mount +run_check $FSSTRESS_PROG -w -n $workload -p $nr_threads -d $SCRATCH_MNT \ + $FSSTRESS_AVOID > /dev/null 2>&1 +_log_writes_unmount + +_log_writes_remove +prev=$(_log_writes_mark_to_entry_number mkfs) +[ -z "$prev" ] && _fail "failed to locate entry mark 'mkfs'" +cur=$(_log_writes_find_next_fua $prev) +[ -z "$cur" ] && _fail "failed to locate next FUA write" + +_log_writes_replay_log_entry_range $prev +while [ ! -z "$cur" ]; do
tests/generic/481 line 102
Quoted 10 lines
tests/generic/481 new file +10
-0+ _log_writes_replay_log_entry_range $cur $prev >> $seqres.full + + echo "=== Replay to entry number $cur ===" >> $seqres.full + # Here we need extra mount to replay the log, mainly for journal based + # fs, as their fsck will report dirty log as error. So do snapshot + # to replay, so we can still continue replaying + _log_writes_create_snapshot $TEST_DEV + _log_writes_mount_snapshot + _log_writes_unmount_snapshot + _check_generic_filesystem "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME"
Maybe _log_writes_check_snapshot helper?
Thanks,
Amir.
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
Quoted 12 lines · Amir Goldstein
Quoted 10 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
Quoted 6 lines
Definitely not allowed.
I suppose you could either create an LVM volume on scratch for the tested fs and leave room for a snapshot target on scratch or do something similar with
LOGWRITES_DEV, which may be more appropriate in the context of common/dmlogwrites helper.
This sounds much better.
Quoted 4 lines
I see you are posting this generic series independently from the btrsf specific series, but the two series have conflicting changes. How do intent for the final merged result to look like?
Btrfs specific one will be discard and merged into this. The found btrfs specific problem proves to be harmless now.
Thanks,
Qu
Quoted 261 lines
Quoted 59 lines
--- common/dmlogwrites | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481.out | 2 + tests/generic/group | 1 + 4 files changed, 246 insertions(+) create mode 100755 tests/generic/481 create mode 100644 tests/generic/481.outcommon/dmlogwrites +40
-0@@ -126,3 +126,122 @@ _log_writes_cleanup() $UDEV_SETTLE_PROG >/dev/null 2>&1 _log_writes_remove } + +# Convert log writes mark to entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_mark_to_entry_number() +{ + local _mark=$1 + local ret + + [ -z "$_mark" ] && _fatal \ + "mark must be given for _log_writes_mark_to_entry_number" + + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --end-mark $_mark 2> /dev/null) + [ -z "$ret" ] && return + ret=$(echo "$ret" | cut -f1 -d\@) + echo "mark $_mark has entry number $ret" >> $seqres.full + echo "$ret" +} + +# Find next fua write entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_find_next_fua() +{ + local _start_entry=$1 + local ret + + [ -z "$_start_entry" ] && _start_entry=0 + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --next-fua --start-entry $_start_entry 2> /dev/null) + [ -z "$ret" ] && return + + ret=$(echo "$ret" | cut -f1 -d\@) + echo "next fua is entry number $ret" >> $seqres.full + echo "$ret" +} + +# Replay log range to specified entry +# $1: End entry. The entry with this number *WILL* be replayed +# $2: Start entry. If not specified, start from the first entry. +# $3: Verbose. If set to 'y' do verbose outputcommon/dmlogwrites _log_writes_cleanup() · line 178
Quoted 10 lines
common/dmlogwrites +10
-0+_log_writes_replay_log_entry_range() +{ + local _end=$1 + local _start=$2 + local _verbose=$3 + + [ -z "$_end" ] && _fatal \ + "end entry must be specified for _log_writes_replay_log_entry_range" + + [ "x$verbose" == "xy" ] && _verbose="-v"Those xy tricks are really not needed with bash.
"$verbose" == "y" is nicer and better.Quoted 167 lines
common/dmlogwrites +69
-0+ [ -z "$_start" ] && _start=0 + [ "$_start" -gt "$_end" ] && _fatal \ + "wrong parameter order for _log_writes_replay_log_entry_range:start=$_start end=$_end" + + # To ensure we replay the last entry, for _start == 0 case, + # we need to manually increase the end entry number to ensure + # it's played + echo "=== replay from $_start to $_end ===" >> $seqres.full + $here/src/log-writes/replay-log --log $LOGWRITES_DEV \ + --replay $SCRATCH_DEV --start-entry $_start \ + --limit $(($_end - $_start + 1)) $_verbose \ + >> $seqres.full 2>&1 + [ $? -ne 0 ] && _fatal "replay failed" +} + +_log_writes_cleanup_snapshot() +{ + $UDEV_SETTLE_PROG > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_SNAPSHOT_NAME" > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_ORIGIN_NAME" > /dev/null 2>&1 +} + +# Helper to create snapshot of a the replayed device +# Useful for journal based filesystem such as XFS and Ext4 to replay +# their journal without touching the replay device, so that we can +# continue replaying other than replay from the beginning. +# $1: Snapshot device +_log_writes_create_snapshot() +{ + _require_dm_target snapshot + + local snapshot_dev=$1 + local cow_base="" + + [ -z "$snapshot_dev" ] && _fatal \ + "@device must be specified for _log_writes_create_snapshot" + local size=$(blockdev --getsz $SCRATCH_DEV) + [ -z "$size" ] && _fatal \ + "failed to get device size for _log_writes_create_snapshot" + + _log_writes_cleanup_snapshot + + DMLOGWRITES_ORIGIN_NAME="log-writes-origin" + DMLOGWRITES_SNAPSHOT_NAME="log-writes-snapshot" + DMLOGWRITES_ORIGIN_TABLE="0 $size snapshot-origin $SCRATCH_DEV" + DMLOGWRITES_SNAPSHOT_TABLE="0 $size snapshot /dev/mapper/$DMLOGWRITES_ORIGIN_NAME $snapshot_dev N 512" + + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_ORIGIN_NAME --table "$DMLOGWRITES_ORIGIN_TABLE" ||\ + _fatal "failed to create snapshot-origin of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_SNAPSHOT_NAME --table "$DMLOGWRITES_SNAPSHOT_TABLE" ||\ + _fatal "failed to create snapshot of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 +} + +_log_writes_mount_snapshot() +{ + _scratch_options mount + $MOUNT_PROG -t $FSTYP `_common_dev_mount_options $*` $SCRATCH_OPTIONS \ + "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME" $SCRATCH_MNT +} + +_log_writes_unmount_snapshot() +{ + $UMOUNT_PROG $SCRATCH_MNT +} +tests/generic/481 new file +92
-0@@ -0,0 +1,124 @@ +#! /bin/bash +# FS QA Test 481 +# +# Test filesystem consistency after each FUA operation +# +# Will do log replay and check the filesystem. +# +#----------------------------------------------------------------------- +# Copyright (c) 2018 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() +{ + cd / + $KILLALL_PROG -KILL -q $FSSTRESS_PROG &> /dev/null + _log_writes_cleanup_snapshot &> /dev/null + _log_writes_cleanup &> /dev/null + + # We use $TEST_DEV as snapshot COW device, which can't be + # mounted/recognized as normal fs, need to recreate it + # or fstest will complain about it + _mkfs_dev $TEST_DEV > /dev/null 2>&1 + rm -f $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/dmlogwrites + +# remove previous $seqres.full before test +rm -f $seqres.full + +# real QA test starts here + +# Modify as appropriate. +_supported_fs generic +_supported_os Linux + +_require_command "$KILLALL_PROG" killall +# Use $TEST_DEV as snapshot CoW device +_require_test +# Use $SCRATCH_DEV as replay device +_require_scratch +# and we need extra device as log device +_require_log_writes + + +workload=$(( 512 * $LOAD_FACTOR )) +nr_threads=$(($($here/src/feature -o) * $LOAD_FACTOR)) + +_test_unmount +_log_writes_init +_log_writes_mkfs >> $seqres.full 2>&1 +_log_writes_mark mkfs + +_log_writes_mount +run_check $FSSTRESS_PROG -w -n $workload -p $nr_threads -d $SCRATCH_MNT \ + $FSSTRESS_AVOID > /dev/null 2>&1 +_log_writes_unmount + +_log_writes_remove +prev=$(_log_writes_mark_to_entry_number mkfs) +[ -z "$prev" ] && _fail "failed to locate entry mark 'mkfs'" +cur=$(_log_writes_find_next_fua $prev) +[ -z "$cur" ] && _fail "failed to locate next FUA write" + +_log_writes_replay_log_entry_range $prev +while [ ! -z "$cur" ]; dotests/generic/481 line 102
Quoted 10 lines
tests/generic/481 new file +10
-0+ _log_writes_replay_log_entry_range $cur $prev >> $seqres.full + + echo "=== Replay to entry number $cur ===" >> $seqres.full + # Here we need extra mount to replay the log, mainly for journal based + # fs, as their fsck will report dirty log as error. So do snapshot + # to replay, so we can still continue replaying + _log_writes_create_snapshot $TEST_DEV + _log_writes_mount_snapshot + _log_writes_unmount_snapshot + _check_generic_filesystem "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME"Maybe
_log_writes_check_snapshothelper?Thanks,
Amir.
--
To unsubscribe from this list: send the line "unsubscribe fstests" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
In reply to Qu WenruoQuoted 3 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.
It's not clear to me why the existing infrastructure is not sufficient for the test. It'd be great if you could provide more information and/or background in commit log.
Quoted 7 lines
Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
As Amir already replied, that's not allowed, any destructive operations should be done on $SCRATCH_DEV.
Quoted 14 lines
--- common/dmlogwrites | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481.out | 2 + tests/generic/group | 1 + 4 files changed, 246 insertions(+) create mode 100755 tests/generic/481 create mode 100644 tests/generic/481.outcommon/dmlogwrites +0
-0
common/dmlogwrites _log_writes_cleanup() · line 134
Quoted 9 lines
common/dmlogwrites +6
-0@@ -126,3 +126,122 @@ _log_writes_cleanup() $UDEV_SETTLE_PROG >/dev/null 2>&1 _log_writes_remove } + +# Convert log writes mark to entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_mark_to_entry_number() +{ + local _mark=$1
No need to name a local variable with leading underscore.
common/dmlogwrites _log_writes_cleanup() · line 138
Quoted 4 lines
common/dmlogwrites +4
-0+ local ret + + [ -z "$_mark" ] && _fatal \ + "mark must be given for _log_writes_mark_to_entry_number"
Please use _fail instead of _fatal (and all the other places in this patch). I think _fatal is only used at the initializing phase of the test harness (e.g. check required tools, env etc.) and abort the test run in early stage. _fail is used to indicate a failure in test phase, it also logs the error messages in $seqres.full.
common/dmlogwrites _log_writes_cleanup() · line 141
Quoted 3 lines
common/dmlogwrites +3
-0+ + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --end-mark $_mark 2> /dev/null)
Is this output long or short? If it's a short one, e.g. a number or a simple string, I think it's OK to save it in a variable. But if it's long/complex enough and/or has multiple lines, I think we'd better to save it with a tmp file, e.g. $tmp.<suffix>.
common/dmlogwrites _log_writes_cleanup() · line 143
Quoted 2 lines
common/dmlogwrites +2
-0+ [ -z "$ret" ] && return + ret=$(echo "$ret" | cut -f1 -d\@)
Because I want to avoid echoing such a variable to a pipe (even it's quoted), it used to cause subtle problems if not quoted properly.
Also, it'd be better to give a sample output of the replay-log command in comment if it's short enough, so people could have an idea what it looks like and know what you're looking for in the subsequent steps (cut -f1 -d\@, in this example), and it's easier to review.
Above comments apply to other helper functions too.
Thanks for all the work!
Eryu
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
Quoted 8 lines · Eryu Guan
Quoted 3 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.It's not clear to me why the existing infrastructure is not sufficient for the test. It'd be great if you could provide more information and/or background in commit log.
The main problem of current infrastructure is we don't have the following things:
1) Way to take full advantage of dm-log-writes
The main thing is, we don't have test cases to check each FUA (this patch) and flush (later patch after clearing all the RFC comments).
We have some dm-flakey test cases to emulate power loss, but they are mostly for fsync.
Here we are not only testing fsync, but also every superblock update. Which should be a super set of dm-flakey tests.
2) Workaround for journal replay
In fact, if we only test btrfs, we don't even need such complicated work, just 'replay-log --fsck "btrfs check" --check fua' will be enough. As btrfs check doesn't report dirty journal (log tree) as problem.
But for journal based fses, their fsck all report dirty journal as error, which needs current snapshot works to replay them before running fsck.
I would add them in next version if there is no extra comment on this.
Quoted 11 lines
Quoted 8 lines
Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
As Amir already replied, that's not allowed, any destructive operations should be done on $SCRATCH_DEV.
Yep, I'm looking for similar case who uses $SCRATCH_DEV as LVM pv do get extra device.
Or can we reuse the scratch_dev_pool even for ext4/xfs?
Quoted 27 lines
Quoted 15 lines
--- common/dmlogwrites | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481.out | 2 + tests/generic/group | 1 + 4 files changed, 246 insertions(+) create mode 100755 tests/generic/481 create mode 100644 tests/generic/481.outcommon/dmlogwrites +0
-0common/dmlogwrites _log_writes_cleanup() · line 134
Quoted 9 lines
common/dmlogwrites +6
-0@@ -126,3 +126,122 @@ _log_writes_cleanup() $UDEV_SETTLE_PROG >/dev/null 2>&1 _log_writes_remove } + +# Convert log writes mark to entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_mark_to_entry_number() +{ + local _mark=$1No need to name a local variable with leading underscore.
Quoted 10 lines
common/dmlogwrites _log_writes_cleanup() · line 138
Quoted 4 lines
common/dmlogwrites +4
-0+ local ret + + [ -z "$_mark" ] && _fatal \ + "mark must be given for _log_writes_mark_to_entry_number"Please use
_failinstead of_fatal(and all the other places in this patch). I think_fatalis only used at the initializing phase of the test harness (e.g. check required tools, env etc.) and abort the test run in early stage._failis used to indicate a failure in test phase, it also logs the error messages in $seqres.full.
Glad to know the difference.
Quoted 9 lines
common/dmlogwrites _log_writes_cleanup() · line 141
Quoted 4 lines
common/dmlogwrites +3
-0+ + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --end-mark $_mark 2> /dev/null)Is this output long or short? If it's a short one, e.g. a number or a simple string, I think it's OK to save it in a variable. But if it's long/complex enough and/or has multiple lines, I think we'd better to save it with a tmp file, e.g. $tmp.<suffix>.
Very very short, just one line like '1024@2048'.
Quoted 7 lines
common/dmlogwrites _log_writes_cleanup() · line 143
Quoted 3 lines
common/dmlogwrites +2
-0+ [ -z "$ret" ] && return + ret=$(echo "$ret" | cut -f1 -d\@)Because I want to avoid echoing such a variable to a pipe (even it's quoted), it used to cause subtle problems if not quoted properly.
Quoted 8 lines
Also, it'd be better to give a sample output of the replay-log command in comment if it's short enough, so people could have an idea what it looks like and know what you're looking for in the subsequent steps (cut -f1 -d\@, in this example), and it's easier to review.
Above comments apply to other helper functions too.
Thanks for all the work!
Thanks for your review too,
Qu
Quoted 7 lines
Eryu
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
Quoted 24 lines · Qu Wenruo
Quoted 8 lines · Eryu Guan
Quoted 3 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.It's not clear to me why the existing infrastructure is not sufficient for the test. It'd be great if you could provide more information and/or background in commit log.
The main problem of current infrastructure is we don't have the following things:
1) Way to take full advantage of dm-log-writes
The main thing is, we don't have test cases to check each FUA (this patch) and flush (later patch after clearing all the RFC comments).We have some dm-flakey test cases to emulate power loss, but they are mostly for fsync.
Here we are not only testing fsync, but also every superblock update. Which should be a super set of dm-flakey tests.
Quoted 8 lines
2) Workaround for journal replay
In fact, if we only test btrfs, we don't even need such complicated work, just 'replay-log --fsck "btrfs check" --check fua' will be enough. As btrfs check doesn't report dirty journal (log tree) as problem.
But for journal based fses, their fsck all report dirty journal as error, which needs current snapshot works to replay them before running fsck.
And replay-to-fua doesn't guarantee a consistent filesystem state, that's why we need to mount/umount the target device to replay the filesystem journal, and to avoid replaying already-replayed-log over and over again, we create a snapshot of the target device and mount cycle & fsck the snapshot, right?
I'm wondering if the overhead of repeatly create & destroy snapshots is larger than replaying log from start. Maybe snapshots take more time?
Quoted 12 lines
I would add them in next version if there is no extra comment on this.
Quoted 9 lines
Quoted 8 lines
Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
Quoted 7 lines
Quoted 2 lines
As Amir already replied, that's not allowed, any destructive operations should be done on $SCRATCH_DEV.
Yep, I'm looking for similar case who uses $SCRATCH_DEV as LVM pv do get extra device.
Or can we reuse the
scratch_dev_pooleven for ext4/xfs?
I think so, IMO pool devices are not limited to btrfs. But I think we could use a loop device reside on $TEST_DIR? Or if snapshots take longer time, then we don't need this extra device at all :)
I have some other comments, will reply to the RFC patch in another email.
Thanks,
Eryu
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
Quoted 34 lines · Eryu Guan
Quoted 24 lines · Qu Wenruo
Quoted 8 lines · Eryu Guan
Quoted 3 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.It's not clear to me why the existing infrastructure is not sufficient for the test. It'd be great if you could provide more information and/or background in commit log.
The main problem of current infrastructure is we don't have the following things:
1) Way to take full advantage of dm-log-writes
The main thing is, we don't have test cases to check each FUA (this patch) and flush (later patch after clearing all the RFC comments).We have some dm-flakey test cases to emulate power loss, but they are mostly for fsync.
Here we are not only testing fsync, but also every superblock update. Which should be a super set of dm-flakey tests.Quoted 8 lines
2) Workaround for journal replay
In fact, if we only test btrfs, we don't even need such complicated work, just 'replay-log --fsck "btrfs check" --check fua' will be enough. As btrfs check doesn't report dirty journal (log tree) as problem.
But for journal based fses, their fsck all report dirty journal as error, which needs current snapshot works to replay them before running fsck.
Quoted 9 lines
And replay-to-fua doesn't guarantee a consistent filesystem state, that's why we need to mount/umount the target device to replay the filesystem journal, and to avoid replaying already-replayed-log over and over again, we create a snapshot of the target device and mount cycle & fsck the snapshot, right?
I'm wondering if the overhead of repeatly create & destroy snapshots is larger than replaying log from start. Maybe snapshots take more time?
FYI, the snapshots flavor comes from Josef's scripts and it is called fast*** I suppose this means the non-snapshot flavor is the original implementation and it is slower. Josef?
Quoted 29 lines
Quoted 12 lines
I would add them in next version if there is no extra comment on this.
Quoted 9 lines
Quoted 8 lines
Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
Quoted 7 lines
Quoted 2 lines
As Amir already replied, that's not allowed, any destructive operations should be done on $SCRATCH_DEV.
Yep, I'm looking for similar case who uses $SCRATCH_DEV as LVM pv do get extra device.
Or can we reuse the
scratch_dev_pooleven for ext4/xfs?I think so, IMO pool devices are not limited to btrfs. But I think we could use a loop device reside on $TEST_DIR? Or if snapshots take longer time, then we don't need this extra device at all :)
I have some other comments, will reply to the RFC patch in another email.
Thanks,
Eryu
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
In reply to Eryu GuanQuoted 34 lines · Eryu Guan
Quoted 24 lines · Qu Wenruo
Quoted 8 lines · Eryu Guan
Quoted 3 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.It's not clear to me why the existing infrastructure is not sufficient for the test. It'd be great if you could provide more information and/or background in commit log.
The main problem of current infrastructure is we don't have the following things:
1) Way to take full advantage of dm-log-writes
The main thing is, we don't have test cases to check each FUA (this patch) and flush (later patch after clearing all the RFC comments).We have some dm-flakey test cases to emulate power loss, but they are mostly for fsync.
Here we are not only testing fsync, but also every superblock update. Which should be a super set of dm-flakey tests.Quoted 8 lines
2) Workaround for journal replay
In fact, if we only test btrfs, we don't even need such complicated work, just 'replay-log --fsck "btrfs check" --check fua' will be enough. As btrfs check doesn't report dirty journal (log tree) as problem.
But for journal based fses, their fsck all report dirty journal as error, which needs current snapshot works to replay them before running fsck.
Quoted 8 lines
And replay-to-fua doesn't guarantee a consistent filesystem state, that's why we need to mount/umount the target device to replay the filesystem journal, and to avoid replaying already-replayed-log over and over again, we create a snapshot of the target device and mount cycle & fsck the snapshot, right?
I'm wondering if the overhead of repeatly create & destroy snapshots is larger than replaying log from start. Maybe snapshots take more time?
This is the interesting part.
Repeatedly creating snapshot will become slower and slower, and in fact for ext4/xfs it's pretty slow, so I use the small nops for fsstress (512), as for later snapshot creation it's taking quite a long time.
But if we switch back to no snapshot, but pure replay-log method, replay-log itself will become slow too.
But at least it can go much further (nops=2048) and still get a somewhat acceptable speed.
Either way, we will get slower and slower when the number of operation grow.
However personally speaking, the pure replay-log one looks a little better, as I don't need to use LVM to create snapshot. :)
Quoted 16 lines
Quoted 16 lines
I would add them in next version if there is no extra comment on this.
Quoted 11 lines
Quoted 8 lines
Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
As Amir already replied, that's not allowed, any destructive operations should be done on $SCRATCH_DEV.
Quoted 8 lines
Quoted 4 lines
Yep, I'm looking for similar case who uses $SCRATCH_DEV as LVM pv do get extra device.
Or can we reuse the
scratch_dev_pooleven for ext4/xfs?I think so, IMO pool devices are not limited to btrfs. But I think we could use a loop device reside on $TEST_DIR? Or if snapshots take longer time, then we don't need this extra device at all :)
That would be much better!
Both common/dmlogwrites and the test case will be much simpler.
Thanks,
Qu
Quoted 11 lines
I have some other comments, will reply to the RFC patch in another email.
Thanks,
Eryu
--
To unsubscribe from this list: send the line "unsubscribe fstests" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
In reply to Qu WenruoQuoted 58 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
--- common/dmlogwrites | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481.out | 2 + tests/generic/group | 1 + 4 files changed, 246 insertions(+) create mode 100755 tests/generic/481 create mode 100644 tests/generic/481.outcommon/dmlogwrites +31
-0@@ -126,3 +126,122 @@ _log_writes_cleanup() $UDEV_SETTLE_PROG >/dev/null 2>&1 _log_writes_remove } + +# Convert log writes mark to entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_mark_to_entry_number() +{ + local _mark=$1 + local ret + + [ -z "$_mark" ] && _fatal \ + "mark must be given for _log_writes_mark_to_entry_number" + + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --end-mark $_mark 2> /dev/null) + [ -z "$ret" ] && return + ret=$(echo "$ret" | cut -f1 -d\@) + echo "mark $_mark has entry number $ret" >> $seqres.full + echo "$ret" +} + +# Find next fua write entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_find_next_fua() +{ + local _start_entry=$1 + local ret + + [ -z "$_start_entry" ] && _start_entry=0 + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --next-fua --start-entry $_start_entry 2> /dev/null) + [ -z "$ret" ] && return +
common/dmlogwrites _log_writes_cleanup() · line 169
Quoted 10 lines
common/dmlogwrites +10
-0+ ret=$(echo "$ret" | cut -f1 -d\@) + echo "next fua is entry number $ret" >> $seqres.full + echo "$ret" +} + +# Replay log range to specified entry +# $1: End entry. The entry with this number *WILL* be replayed +# $2: Start entry. If not specified, start from the first entry. +# $3: Verbose. If set to 'y' do verbose output +_log_writes_replay_log_entry_range()
_log_writes_replay_log_range() would be fine.
common/dmlogwrites _log_writes_cleanup() · line 172
Quoted 3 lines
common/dmlogwrites +3
-0+{ + local _end=$1 + local _start=$2
This arguments order ($end comes first) makes me confused when I first read the test code. Reverse the order?
Quoted 26 lines
common/dmlogwrites +26
-0+ local _verbose=$3 + + [ -z "$_end" ] && _fatal \ + "end entry must be specified for _log_writes_replay_log_entry_range" + + [ "x$verbose" == "xy" ] && _verbose="-v" + [ -z "$_start" ] && _start=0 + [ "$_start" -gt "$_end" ] && _fatal \ + "wrong parameter order for _log_writes_replay_log_entry_range:start=$_start end=$_end" + + # To ensure we replay the last entry, for _start == 0 case, + # we need to manually increase the end entry number to ensure + # it's played + echo "=== replay from $_start to $_end ===" >> $seqres.full + $here/src/log-writes/replay-log --log $LOGWRITES_DEV \ + --replay $SCRATCH_DEV --start-entry $_start \ + --limit $(($_end - $_start + 1)) $_verbose \ + >> $seqres.full 2>&1 + [ $? -ne 0 ] && _fatal "replay failed" +} + +_log_writes_cleanup_snapshot() +{ + $UDEV_SETTLE_PROG > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_SNAPSHOT_NAME" > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_ORIGIN_NAME" > /dev/null 2>&1
common/dmlogwrites _log_writes_cleanup() · line 208
Quoted 10 lines
common/dmlogwrites +10
-0+} + +# Helper to create snapshot of a the replayed device +# Useful for journal based filesystem such as XFS and Ext4 to replay +# their journal without touching the replay device, so that we can +# continue replaying other than replay from the beginning. +# $1: Snapshot device +_log_writes_create_snapshot() +{ + _require_dm_target snapshot
This doesn't belong here, call it in the test.
common/dmlogwrites _log_writes_cleanup() · line 211
Quoted 3 lines
common/dmlogwrites +3
-0+ + local snapshot_dev=$1 + local cow_base=""
Unused variable.
Quoted 114 lines
common/dmlogwrites +36
-0+ + [ -z "$snapshot_dev" ] && _fatal \ + "@device must be specified for _log_writes_create_snapshot" + local size=$(blockdev --getsz $SCRATCH_DEV) + [ -z "$size" ] && _fatal \ + "failed to get device size for _log_writes_create_snapshot" + + _log_writes_cleanup_snapshot + + DMLOGWRITES_ORIGIN_NAME="log-writes-origin" + DMLOGWRITES_SNAPSHOT_NAME="log-writes-snapshot" + DMLOGWRITES_ORIGIN_TABLE="0 $size snapshot-origin $SCRATCH_DEV" + DMLOGWRITES_SNAPSHOT_TABLE="0 $size snapshot /dev/mapper/$DMLOGWRITES_ORIGIN_NAME $snapshot_dev N 512" + + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_ORIGIN_NAME --table "$DMLOGWRITES_ORIGIN_TABLE" ||\ + _fatal "failed to create snapshot-origin of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_SNAPSHOT_NAME --table "$DMLOGWRITES_SNAPSHOT_TABLE" ||\ + _fatal "failed to create snapshot of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 +} + +_log_writes_mount_snapshot() +{ + _scratch_options mount + $MOUNT_PROG -t $FSTYP `_common_dev_mount_options $*` $SCRATCH_OPTIONS \ + "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME" $SCRATCH_MNT +} + +_log_writes_unmount_snapshot() +{ + $UMOUNT_PROG $SCRATCH_MNT +} +tests/generic/481 new file +72
-0@@ -0,0 +1,124 @@ +#! /bin/bash +# FS QA Test 481 +# +# Test filesystem consistency after each FUA operation +# +# Will do log replay and check the filesystem. +# +#----------------------------------------------------------------------- +# Copyright (c) 2018 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() +{ + cd / + $KILLALL_PROG -KILL -q $FSSTRESS_PROG &> /dev/null + _log_writes_cleanup_snapshot &> /dev/null + _log_writes_cleanup &> /dev/null + + # We use $TEST_DEV as snapshot COW device, which can't be + # mounted/recognized as normal fs, need to recreate it + # or fstest will complain about it + _mkfs_dev $TEST_DEV > /dev/null 2>&1 + rm -f $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/dmlogwrites + +# remove previous $seqres.full before test +rm -f $seqres.full + +# real QA test starts here + +# Modify as appropriate. +_supported_fs generic +_supported_os Linux + +_require_command "$KILLALL_PROG" killall +# Use $TEST_DEV as snapshot CoW device +_require_test +# Use $SCRATCH_DEV as replay device +_require_scratch +# and we need extra device as log device +_require_log_writes + + +workload=$(( 512 * $LOAD_FACTOR ))
tests/generic/481 line 82
Quoted 10 lines
tests/generic/481 new file +10
-0+nr_threads=$(($($here/src/feature -o) * $LOAD_FACTOR)) + +_test_unmount +_log_writes_init +_log_writes_mkfs >> $seqres.full 2>&1 +_log_writes_mark mkfs + +_log_writes_mount +run_check $FSSTRESS_PROG -w -n $workload -p $nr_threads -d $SCRATCH_MNT \ + $FSSTRESS_AVOID > /dev/null 2>&1
Use _scale_fsstress_args to scale the load.
And I don't think checking the result of fsstress is necessary, it's used as a load generator and we check fs consistency anyway.
Quoted 10 lines
tests/generic/481 new file +10
-0+_log_writes_unmount + +_log_writes_remove +prev=$(_log_writes_mark_to_entry_number mkfs) +[ -z "$prev" ] && _fail "failed to locate entry mark 'mkfs'" +cur=$(_log_writes_find_next_fua $prev) +[ -z "$cur" ] && _fail "failed to locate next FUA write" + +_log_writes_replay_log_entry_range $prev +while [ ! -z "$cur" ]; do
tests/generic/481 line 102
Quoted 10 lines
tests/generic/481 new file +10
-0+ _log_writes_replay_log_entry_range $cur $prev >> $seqres.full + + echo "=== Replay to entry number $cur ===" >> $seqres.full + # Here we need extra mount to replay the log, mainly for journal based + # fs, as their fsck will report dirty log as error. So do snapshot + # to replay, so we can still continue replaying + _log_writes_create_snapshot $TEST_DEV + _log_writes_mount_snapshot + _log_writes_unmount_snapshot + _check_generic_filesystem "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME"
Use _check_scratch_fs $some_dev, _check_generic_filesystem doesn't work for xfs/btrfs/udf/overlay.
tests/generic/481 line 106
Quoted 4 lines
tests/generic/481 new file +4
-0+ if [ $? -ne 0 ]; then + _log_writes_replay_log_entry_range $cur $prev y >> $seqres.full + _fail "error found in fsck after log replay" + fi
And _check_scratch_fs/_check_generic_filesystem exits directly on fsck failure, you can't do the return status check.
Quoted 31 lines
tests/generic/481 new file +18
-0+ _log_writes_cleanup_snapshot + + prev=$cur + cur=$(_log_writes_find_next_fua $(($cur + 1))) + [ -z "$cur" ] && break +done +_log_writes_cleanup_snapshot +_log_writes_cleanup + +# mkfs before ending the test case, or $TEST_DEV doesn't contain any +# valid fs +_mkfs_dev $TEST_DEV + +echo "Silence is golden" + +# success, all done +status=0 +exittests/generic/481.out new file +2
-0@@ -0,0 +1,2 @@ +QA output created by 481 +Silence is goldentests/generic/group +0
-0
tests/generic/group line 486
Quoted 4 lines
tests/generic/group +1
-0@@ -483,3 +483,4 @@ 478 auto quick 479 auto quick metadata 480 auto quick metadata +481 auto
Add 'replay' group, as all other tests using dm-log-writes.
Thanks,
Eryu
Re: [PATCH RFC 3/3] fstests: generic: Check the fs after each FUA writes
Quoted 72 lines · Eryu Guan
Quoted 58 lines · Qu Wenruo
Basic test case which triggers fsstress with dm-log-writes, and then check the fs after each FUA writes.
With needed infrastructure and special handlers for journal based fs.Signed-off-by Qu Wenruo <[email protected]>---
In my test, xfs and btrfs survives while ext4 would report error during fsck.My current biggest concern is, we abuse $TEST_DEV and mkfs on it all by ourselves. Not sure if it's allowed.
--- common/dmlogwrites | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481 | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/481.out | 2 + tests/generic/group | 1 + 4 files changed, 246 insertions(+) create mode 100755 tests/generic/481 create mode 100644 tests/generic/481.outcommon/dmlogwrites +31
-0@@ -126,3 +126,122 @@ _log_writes_cleanup() $UDEV_SETTLE_PROG >/dev/null 2>&1 _log_writes_remove } + +# Convert log writes mark to entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_mark_to_entry_number() +{ + local _mark=$1 + local ret + + [ -z "$_mark" ] && _fatal \ + "mark must be given for _log_writes_mark_to_entry_number" + + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --end-mark $_mark 2> /dev/null) + [ -z "$ret" ] && return + ret=$(echo "$ret" | cut -f1 -d\@) + echo "mark $_mark has entry number $ret" >> $seqres.full + echo "$ret" +} + +# Find next fua write entry number +# Result entry number is output to stdout, could be empty if not found +_log_writes_find_next_fua() +{ + local _start_entry=$1 + local ret + + [ -z "$_start_entry" ] && _start_entry=0 + ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \ + --next-fua --start-entry $_start_entry 2> /dev/null) + [ -z "$ret" ] && return +common/dmlogwrites _log_writes_cleanup() · line 169
Quoted 10 lines
common/dmlogwrites +10
-0+ ret=$(echo "$ret" | cut -f1 -d\@) + echo "next fua is entry number $ret" >> $seqres.full + echo "$ret" +} + +# Replay log range to specified entry +# $1: End entry. The entry with this number *WILL* be replayed +# $2: Start entry. If not specified, start from the first entry. +# $3: Verbose. If set to 'y' do verbose output +_log_writes_replay_log_entry_range()
_log_writes_replay_log_range()would be fine.
Quoted 6 lines
common/dmlogwrites _log_writes_cleanup() · line 172
Quoted 3 lines
common/dmlogwrites +3
-0+{ + local _end=$1 + local _start=$2This arguments order ($end comes first) makes me confused when I first read the test code. Reverse the order?
Yep, the order is confusing.
However the confusing parameter order is here because some parameter is optional.
As we can call _log_writes_replay_log_range() like:
_log_writes_replay_log_range 1024 # Replay to number 1024_log_writes_replay_log_range 1024 2048 # Replay from 1024 to 2048_log_writes_replay_log_range 128 512 y # verbose replay
So this makes order pretty hard to reverse.
(Or, we discard the ability to replay from $start to $end, and only
support replay to $end?)
Anyway, I would use the pure replay-log method to avoid extra device, and see if it would make test case easier.
Thanks,
Qu
Quoted 253 lines
Quoted 27 lines
common/dmlogwrites +26
-0+ local _verbose=$3 + + [ -z "$_end" ] && _fatal \ + "end entry must be specified for _log_writes_replay_log_entry_range" + + [ "x$verbose" == "xy" ] && _verbose="-v" + [ -z "$_start" ] && _start=0 + [ "$_start" -gt "$_end" ] && _fatal \ + "wrong parameter order for _log_writes_replay_log_entry_range:start=$_start end=$_end" + + # To ensure we replay the last entry, for _start == 0 case, + # we need to manually increase the end entry number to ensure + # it's played + echo "=== replay from $_start to $_end ===" >> $seqres.full + $here/src/log-writes/replay-log --log $LOGWRITES_DEV \ + --replay $SCRATCH_DEV --start-entry $_start \ + --limit $(($_end - $_start + 1)) $_verbose \ + >> $seqres.full 2>&1 + [ $? -ne 0 ] && _fatal "replay failed" +} + +_log_writes_cleanup_snapshot() +{ + $UDEV_SETTLE_PROG > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_SNAPSHOT_NAME" > /dev/null 2>&1 + $DMSETUP_PROG remove "$DMLOGWRITES_ORIGIN_NAME" > /dev/null 2>&1common/dmlogwrites _log_writes_cleanup() · line 208
Quoted 10 lines
common/dmlogwrites +10
-0+} + +# Helper to create snapshot of a the replayed device +# Useful for journal based filesystem such as XFS and Ext4 to replay +# their journal without touching the replay device, so that we can +# continue replaying other than replay from the beginning. +# $1: Snapshot device +_log_writes_create_snapshot() +{ + _require_dm_target snapshotThis doesn't belong here, call it in the test.
common/dmlogwrites _log_writes_cleanup() · line 211
Quoted 3 lines
common/dmlogwrites +3
-0+ + local snapshot_dev=$1 + local cow_base=""Unused variable.
Quoted 114 lines
common/dmlogwrites +36
-0+ + [ -z "$snapshot_dev" ] && _fatal \ + "@device must be specified for _log_writes_create_snapshot" + local size=$(blockdev --getsz $SCRATCH_DEV) + [ -z "$size" ] && _fatal \ + "failed to get device size for _log_writes_create_snapshot" + + _log_writes_cleanup_snapshot + + DMLOGWRITES_ORIGIN_NAME="log-writes-origin" + DMLOGWRITES_SNAPSHOT_NAME="log-writes-snapshot" + DMLOGWRITES_ORIGIN_TABLE="0 $size snapshot-origin $SCRATCH_DEV" + DMLOGWRITES_SNAPSHOT_TABLE="0 $size snapshot /dev/mapper/$DMLOGWRITES_ORIGIN_NAME $snapshot_dev N 512" + + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_ORIGIN_NAME --table "$DMLOGWRITES_ORIGIN_TABLE" ||\ + _fatal "failed to create snapshot-origin of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG create $DMLOGWRITES_SNAPSHOT_NAME --table "$DMLOGWRITES_SNAPSHOT_TABLE" ||\ + _fatal "failed to create snapshot of log writes target" + $DMSETUP_PROG mknodes > /dev/null 2>&1 +} + +_log_writes_mount_snapshot() +{ + _scratch_options mount + $MOUNT_PROG -t $FSTYP `_common_dev_mount_options $*` $SCRATCH_OPTIONS \ + "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME" $SCRATCH_MNT +} + +_log_writes_unmount_snapshot() +{ + $UMOUNT_PROG $SCRATCH_MNT +} +tests/generic/481 new file +72
-0@@ -0,0 +1,124 @@ +#! /bin/bash +# FS QA Test 481 +# +# Test filesystem consistency after each FUA operation +# +# Will do log replay and check the filesystem. +# +#----------------------------------------------------------------------- +# Copyright (c) 2018 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() +{ + cd / + $KILLALL_PROG -KILL -q $FSSTRESS_PROG &> /dev/null + _log_writes_cleanup_snapshot &> /dev/null + _log_writes_cleanup &> /dev/null + + # We use $TEST_DEV as snapshot COW device, which can't be + # mounted/recognized as normal fs, need to recreate it + # or fstest will complain about it + _mkfs_dev $TEST_DEV > /dev/null 2>&1 + rm -f $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/dmlogwrites + +# remove previous $seqres.full before test +rm -f $seqres.full + +# real QA test starts here + +# Modify as appropriate. +_supported_fs generic +_supported_os Linux + +_require_command "$KILLALL_PROG" killall +# Use $TEST_DEV as snapshot CoW device +_require_test +# Use $SCRATCH_DEV as replay device +_require_scratch +# and we need extra device as log device +_require_log_writes + + +workload=$(( 512 * $LOAD_FACTOR ))tests/generic/481 line 82
Quoted 10 lines
tests/generic/481 new file +10
-0+nr_threads=$(($($here/src/feature -o) * $LOAD_FACTOR)) + +_test_unmount +_log_writes_init +_log_writes_mkfs >> $seqres.full 2>&1 +_log_writes_mark mkfs + +_log_writes_mount +run_check $FSSTRESS_PROG -w -n $workload -p $nr_threads -d $SCRATCH_MNT \ + $FSSTRESS_AVOID > /dev/null 2>&1Use
_scale_fsstress_argsto scale the load.And I don't think checking the result of fsstress is necessary, it's used as a load generator and we check fs consistency anyway.
Quoted 10 lines
tests/generic/481 new file +10
-0+_log_writes_unmount + +_log_writes_remove +prev=$(_log_writes_mark_to_entry_number mkfs) +[ -z "$prev" ] && _fail "failed to locate entry mark 'mkfs'" +cur=$(_log_writes_find_next_fua $prev) +[ -z "$cur" ] && _fail "failed to locate next FUA write" + +_log_writes_replay_log_entry_range $prev +while [ ! -z "$cur" ]; dotests/generic/481 line 102
Quoted 10 lines
tests/generic/481 new file +10
-0+ _log_writes_replay_log_entry_range $cur $prev >> $seqres.full + + echo "=== Replay to entry number $cur ===" >> $seqres.full + # Here we need extra mount to replay the log, mainly for journal based + # fs, as their fsck will report dirty log as error. So do snapshot + # to replay, so we can still continue replaying + _log_writes_create_snapshot $TEST_DEV + _log_writes_mount_snapshot + _log_writes_unmount_snapshot + _check_generic_filesystem "/dev/mapper/$DMLOGWRITES_SNAPSHOT_NAME"Use
_check_scratch_fs$some_dev,_check_generic_filesystemdoesn't work for xfs/btrfs/udf/overlay.tests/generic/481 line 106
Quoted 4 lines
tests/generic/481 new file +4
-0+ if [ $? -ne 0 ]; then + _log_writes_replay_log_entry_range $cur $prev y >> $seqres.full + _fail "error found in fsck after log replay" + fiAnd _check_scratch_fs/_check_generic_filesystem exits directly on fsck failure, you can't do the return status check.
Quoted 31 lines
tests/generic/481 new file +18
-0+ _log_writes_cleanup_snapshot + + prev=$cur + cur=$(_log_writes_find_next_fua $(($cur + 1))) + [ -z "$cur" ] && break +done +_log_writes_cleanup_snapshot +_log_writes_cleanup + +# mkfs before ending the test case, or $TEST_DEV doesn't contain any +# valid fs +_mkfs_dev $TEST_DEV + +echo "Silence is golden" + +# success, all done +status=0 +exittests/generic/481.out new file +2
-0@@ -0,0 +1,2 @@ +QA output created by 481 +Silence is goldentests/generic/group +0
-0tests/generic/group line 486
Quoted 4 lines
tests/generic/group +1
-0@@ -483,3 +483,4 @@ 478 auto quick 479 auto quick metadata 480 auto quick metadata +481 autoAdd 'replay' group, as all other tests using dm-log-writes.
Thanks,
Eryu
--
To unsubscribe from this list: send the line "unsubscribe fstests" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 3 lines · Qu Wenruo
Also change the flag numeric output to hex.
Signed-off-by Qu Wenruo <[email protected]>
Quoted 138 lines
--- src/log-writes/log-writes.c | 70 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-)src/log-writes/log-writes.c +63
-8@@ -120,6 +120,58 @@ int log_discard(struct log *log, struct log_write_entry *entry)return 0 ; } +#define DEFINE_LOG_FLAGS_STR_ENTRY (x) \ + {LOG_##x##_FLAG, #x} + +struct flags_to_str_entry { +u64 flags; +const char *str; +} log_flags_table[] = { +DEFINE_LOG_FLAGS_STR_ENTRY (FLUSH ), +DEFINE_LOG_FLAGS_STR_ENTRY (FUA ), +DEFINE_LOG_FLAGS_STR_ENTRY (DISCARD ), +DEFINE_LOG_FLAGS_STR_ENTRY (MARK ) +}; + +#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0])) +#define LOG_FLAGS_BUF_SIZE 128 +/* +* Convert numeric flags to human readable flags. +* @flags: numeric flags +* @buf: output buffer for human readable string. +* must have enough space (LOG_FLAGS_BUF_SIZE) to contain all +* the string +*/ +static void entry_flags_to_str (u64 flags,char *buf) +{ +int empty =1 ; +int left_len; +int i; + + buf[0 ] ='\0' ; +for (i =0 ; i <ARRAY_SIZE (log_flags_table); i++) { +if (flags & log_flags_table[i].flags) { +if (!empty) +strncat (buf,"|" ,LOG_FLAGS_BUF_SIZE ); + empty =0 ; +strncat (buf, log_flags_table[i].str,LOG_FLAGS_BUF_SIZE ); + flags &= ~log_flags_table[i].flags; + } + } +if (flags) { +if (!empty) +strncat (buf,"|" ,LOG_FLAGS_BUF_SIZE ); + empty =0 ; + left_len =LOG_FLAGS_BUF_SIZE -strnlen (buf, +LOG_FLAGS_BUF_SIZE ); +if (left_len >0 ) +snprintf (buf +strnlen (buf,LOG_FLAGS_BUF_SIZE ), + left_len,"UNKNOWN.0x%llx" , flags); + } +if (empty) +strncpy (buf,"NONE" ,LOG_FLAGS_BUF_SIZE ); +} +/* * @log: the log we are replaying. * @entry: entry to be replayed. @@ -179,6 +231,7 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry,size_t read_size = read_data ? log->sectorsize :sizeof (struct log_write_entry );char *buf; +char flags_buf[LOG_FLAGS_BUF_SIZE ];ssize_t ret;off_t offset;int skip =0 ;@@ -210,19 +263,20 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, log->cur_pos += read_size; } + flags =le64_to_cpu (entry->flags); +entry_flags_to_str (flags, flags_buf); skip =log_should_skip (log, entry);if (log_writes_verbose >1 || (log_writes_verbose && !skip)) { -printf ("%s %d@%llu: sector %llu, size %llu, flags %llu\n" , +printf ("%s %d@%llu: sector %llu, size %llu, flags 0x%llx(%s)\n" , skip ?"skipping" :"replaying" , (int )log->cur_entry -1 , log->cur_pos / log->sectorsize, (unsigned long long )le64_to_cpu (entry->sector), (unsigned long long )size, - (unsigned long long )le64_to_cpu (entry->flags)); + (unsigned long long )flags, flags_buf); }if (!size)return 0 ; - flags =le64_to_cpu (entry->flags);if (flags &LOG_DISCARD_FLAG )return log_discard (log, entry);@@ -301,7 +355,7 @@ int log_seek_entry(struct log *log, u64 entry_num)return -1 ; }if (log_writes_verbose >1 ) - printf("seek entry %d@%llu: %llu, size %llu, flags %llu\n", + printf("seek entry %d@%llu: %llu, size %llu, flags 0x%llx\n", (int)i, log->cur_pos / log->sectorsize, (unsigned long long)le64_to_cpu(entry.sector), (unsigned long long)le64_to_cpu(entry.nr_sectors),@@ -339,6 +393,7 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry,size_t read_size = read_data ? log->sectorsize :sizeof (struct log_write_entry );u64 flags; +char flags_buf[LOG_FLAGS_BUF_SIZE ];ssize_t ret;if (log->cur_entry >= log->nr_entries)@@ -366,14 +421,15 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, }else { log->cur_pos += read_size; } + flags =le64_to_cpu (entry->flags); +entry_flags_to_str (flags, flags_buf);if (log_writes_verbose >1 ) -printf ("seek entry %d@%llu: %llu, size %llu, flags %llu\n" , +printf ("seek entry %d@%llu: %llu, size %llu, flags 0x%llx(%s)\n" , (int )log->cur_entry -1 , log->cur_pos / log->sectorsize, (unsigned long long )le64_to_cpu (entry->sector), (unsigned long long )le64_to_cpu (entry->nr_sectors), - (unsigned long long )le64_to_cpu (entry->flags)); + (unsigned long long )flags, flags_buf); - flags =le64_to_cpu (entry->flags); read_size =le64_to_cpu (entry->nr_sectors) * log->sectorsize;if (!read_size || (flags &LOG_DISCARD_FLAG ))return 0 ; --2.15.1