mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Add regression check for Btrfs
It requires root privileges as it has to create Btrfs filesystems.
This commit is contained in:
parent
20cdfa7535
commit
c79b0c0cc3
7 changed files with 142 additions and 59 deletions
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
|
|
@ -23,7 +23,8 @@ jobs:
|
|||
- uses: actions/checkout@v5
|
||||
- run: autoreconf -i
|
||||
- run: ./configure --enable-warning-as-error
|
||||
- run: make all dist check
|
||||
- run: make all btrfscheck
|
||||
- run: make distcheck
|
||||
build-win:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
|
|
|
|||
137
Makefile.am
137
Makefile.am
|
|
@ -154,6 +154,7 @@ EXTRA_DIST = \
|
|||
$(LIST_D) \
|
||||
$(LIST_MAN) \
|
||||
$(LIST_TXT) \
|
||||
test/test-btrfs.conf \
|
||||
test/test-par1.conf \
|
||||
test/test-par2.conf \
|
||||
test/test-par3.conf \
|
||||
|
|
@ -267,6 +268,9 @@ CHECKFLAGS_VERBOSE = $(CHECKFLAGS_ALPHA) -v --gui
|
|||
# Quiet options
|
||||
CHECKFLAGS = $(CHECKFLAGS_ALPHA) -q -q -q
|
||||
|
||||
# Btrfs with no parity limit
|
||||
CHECKFLAGS_BTRFS = --test-skip-device --test-skip-self --test-io-advise-none --test-force-order-alpha -q -q -q
|
||||
|
||||
# Number of files to create
|
||||
if !HAVE_MEMORY_CHECKER
|
||||
if HAVE_POSIX
|
||||
|
|
@ -297,48 +301,101 @@ PARZ = $(srcdir)/test/test-parz.conf
|
|||
PAR4 = $(srcdir)/test/test-par4.conf
|
||||
PAR5 = $(srcdir)/test/test-par5.conf
|
||||
PAR6 = $(srcdir)/test/test-par6.conf
|
||||
BTRFS = $(srcdir)/test/test-btrfs.conf
|
||||
MSG = @echo =====
|
||||
SNAPRAID = ./checker$(EXEEXT)
|
||||
|
||||
fastcheck: mktest
|
||||
setupcheck:
|
||||
rm -rf bench
|
||||
rm -f test.log
|
||||
mkdir bench
|
||||
mkdir bench/disk1
|
||||
mkdir bench/disk2
|
||||
mkdir bench/disk3
|
||||
mkdir bench/disk4
|
||||
mkdir bench/disk5
|
||||
mkdir bench/disk6
|
||||
mkdir bench/pool
|
||||
$(MSG) Stream
|
||||
$(TESTENV) $(SNAPRAID) --test-skip-device -H
|
||||
$(TESTENV) $(SNAPRAID) --test-skip-device -V
|
||||
$(TESTENV) $(SNAPRAID) test
|
||||
$(MSG) Create some files
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 1 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
echo DUP > bench/disk1/DUP1
|
||||
echo DUP > bench/disk1/DUP2
|
||||
echo -n > bench/disk1/ZERO
|
||||
$(MSG) Some commands with a not empty array
|
||||
$(FAILENV) $(SNAPRAID) $(CHECKFLAGS_COMMON) -c $(CONF) --test-expect-need-sync diff > output.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_COMMON) -c $(CONF) sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_VERBOSE) -c $(CONF) dup -l test.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_VERBOSE) -c $(CONF) list -l test.log > output.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_VERBOSE) -c $(CONF) test-rewrite
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_VERBOSE) -c $(CONF) read
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) status -l test.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) check
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) -a check
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) test-dry
|
||||
$(MSG) Regression test completed with SUCCESS!
|
||||
$(MSG) Please ignore any error message printed above, they are expected!
|
||||
$(MSG) Everything OK
|
||||
|
||||
check-local:
|
||||
rm -rf bench
|
||||
rm -f test.log
|
||||
mkdir bench
|
||||
# Not included in main check because it requires root permissions
|
||||
btrfscheck: mktest checker setupcheck
|
||||
sudo $(MAKE) btrfscheck_run; \
|
||||
status=$$?; \
|
||||
sudo $(MAKE) btrfscheck_cleanup; \
|
||||
exit $$status
|
||||
|
||||
btrfscheck_run:
|
||||
mkdir bench/btrfs1
|
||||
mkdir bench/btrfs2
|
||||
mkdir bench/btrfs3
|
||||
$(MSG) Create storages
|
||||
dd bs=1048576 count=32 if=/dev/zero of=bench/btrfs1.img
|
||||
dd bs=1048576 count=32 if=/dev/zero of=bench/btrfs2.img
|
||||
dd bs=1048576 count=32 if=/dev/zero of=bench/btrfs3.img
|
||||
/sbin/mkfs.btrfs --mixed bench/btrfs1.img
|
||||
/sbin/mkfs.btrfs --mixed bench/btrfs2.img
|
||||
/sbin/mkfs.btrfs --mixed bench/btrfs3.img
|
||||
mount -o loop bench/btrfs1.img bench/btrfs1
|
||||
mount -o loop bench/btrfs2.img bench/btrfs2
|
||||
mount -o loop bench/btrfs3.img bench/btrfs3
|
||||
$(MSG) Create some files
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 1 btrfs 3 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(MSG) Basic
|
||||
# Setup
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) scrub -p full
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) check -d btrfs1
|
||||
# Recover test
|
||||
$(MSG) Recover with file deletions from two disk with ONLY one parity OUTSIDE SYNC
|
||||
rm -rf bench/btrfs1/a
|
||||
rm -rf bench/btrfs2/a
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) fix -d btrfs1 -l test.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) fix -d btrfs2 -l test.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) check
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync --force-full
|
||||
# Recover test
|
||||
$(MSG) Recover with file deletions from two disk with ONLY one parity aborted BEFORE SYNC
|
||||
# Changes (including deletion) on disk1
|
||||
$(TESTENV) ./mktest$(EXEEXT) change 1 500 bench/btrfs1/a/* bench/btrfs1/b/*
|
||||
# Sync aborted BEFORE
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync --test-kill-before-sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) status
|
||||
# Destroy disk2
|
||||
rm -rf bench/btrfs2/a bench/btrfs2/b
|
||||
# Recover disk2 (disk1 is intentionally deleted, so nothing to recover)
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) fix -d btrfs2 -l test.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) check
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync --force-full
|
||||
# Recover test
|
||||
$(MSG) Recover with file deletions from two disk with ONLY one parity aborted AFTER SYNC
|
||||
# Changes (including deletion) on disk1
|
||||
$(TESTENV) ./mktest$(EXEEXT) change 2 500 bench/btrfs1/a/* bench/btrfs1/b/*
|
||||
# Sync aborted AFTER
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync --test-kill-after-sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) status
|
||||
# Destroy disk2
|
||||
rm -rf bench/btrfs2/a bench/btrfs2/b
|
||||
# Recover disk2 (disk1 is intentionally deleted, so nothing to recover)
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) fix -d btrfs2 -l test.log
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) check
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync --force-full
|
||||
# Sync recover
|
||||
$(MSG) Sync recover aborted AFTER
|
||||
# Change files in disk3
|
||||
$(TESTENV) ./mktest$(EXEEXT) change 1 500 bench/btrfs3/a/*
|
||||
# Sync abort and sync retry
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync --test-kill-after-sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) check
|
||||
# Sync recover
|
||||
$(MSG) Sync recover aborted BEFORE
|
||||
# Change files in disk3
|
||||
$(TESTENV) ./mktest$(EXEEXT) change 1 500 bench/btrfs3/a/*
|
||||
# Sync abort and sync retry
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync --test-kill-before-sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS_BTRFS) -c $(BTRFS) check
|
||||
|
||||
btrfscheck_cleanup:
|
||||
$(MSG) Unmount storages
|
||||
umount bench/btrfs1
|
||||
umount bench/btrfs2
|
||||
umount bench/btrfs3
|
||||
|
||||
check-local: setupcheck
|
||||
mkdir bench/disk1
|
||||
mkdir bench/disk2
|
||||
mkdir bench/disk3
|
||||
|
|
@ -351,7 +408,7 @@ check-local:
|
|||
if HAVE_THREAD_CHECKER
|
||||
#### THREAD TEST ####
|
||||
$(MSG) Create some files
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 1 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 1 disk 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(MSG) Some commands that use threads
|
||||
# First sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) sync
|
||||
|
|
@ -493,7 +550,7 @@ endif
|
|||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) sync
|
||||
#### NOT EMPTY ####
|
||||
$(MSG) Create some files
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 1 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 1 disk 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
echo DUP > bench/disk1/DUP1
|
||||
echo DUP > bench/disk1/DUP2
|
||||
echo -n > bench/disk1/ZERO
|
||||
|
|
@ -568,7 +625,7 @@ endif
|
|||
rm bench/disk4/a/8*
|
||||
rm bench/disk5/a/8*
|
||||
rm bench/disk6/a/8*
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 2 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 2 disk 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
mkdir bench/disk1/empty1
|
||||
mkdir bench/disk2/empty2
|
||||
mkdir bench/disk3/empty3a
|
||||
|
|
@ -793,7 +850,7 @@ endif
|
|||
rm bench/disk2/a/2*
|
||||
rm bench/disk3/a/3*
|
||||
rm bench/disk4/a/4*
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 3 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 3 disk 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) check
|
||||
$(MSG) Move some files, sync and check
|
||||
|
|
@ -916,7 +973,7 @@ endif
|
|||
rm bench/disk4/a/6*
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) -B 10 sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) check -l test.log
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 4 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(TESTENV) ./mktest$(EXEEXT) generate 4 disk 6 $(CHECKCOUNT) $(CHECKSIZE)
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) -B 100 sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) -B 1000 sync
|
||||
$(TESTENV) $(SNAPRAID) $(CHECKFLAGS) -c $(CONF) check -l test.log
|
||||
|
|
|
|||
|
|
@ -210,12 +210,12 @@ void cmd_generate_symlink(const char* path, const char* linkto)
|
|||
/**
|
||||
* Create a file or a symlink with a random name.
|
||||
*/
|
||||
void cmd_generate(int disk, int size)
|
||||
void cmd_generate(const char* tag, int disk, int size)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char* file;
|
||||
|
||||
snprintf(path, sizeof(path), "bench/disk%d/", disk);
|
||||
snprintf(path, sizeof(path), "bench/%s%d/", tag, disk);
|
||||
file = path + strlen(path);
|
||||
|
||||
/* add a directory */
|
||||
|
|
@ -627,9 +627,9 @@ void help(void)
|
|||
{
|
||||
printf("Test for " PACKAGE " v" VERSION " by Andrea Mazzoleni, " PACKAGE_URL "\n");
|
||||
printf("Usage:\n");
|
||||
printf("\tmktest generate SEED DISK_NUM FILE_NUM FILE_SIZE\n");
|
||||
printf("\tmktest damage SEED NUM SIZE FILE\n");
|
||||
printf("\tmktest write SEED NUM SIZE FILE\n");
|
||||
printf("\tmktest generate SEED DISK_TAG DISK_NUM FILE_NUM FILE_SIZE\n");
|
||||
printf("\tmktest damage SEED COUNT SIZE FILE\n");
|
||||
printf("\tmktest write SEED COUNT SIZE FILE\n");
|
||||
printf("\tmktest change SEED SIZE FILE\n");
|
||||
printf("\tmktest append SEED SIZE FILE\n");
|
||||
printf("\tmktest truncate SEED SIZE FILE\n");
|
||||
|
|
@ -648,8 +648,9 @@ int main(int argc, char* argv[])
|
|||
|
||||
if (strcmp(argv[1], "generate") == 0) {
|
||||
int disk, file, size;
|
||||
const char* tag;
|
||||
|
||||
if (argc != 6) {
|
||||
if (argc != 7) {
|
||||
/* LCOV_EXCL_START */
|
||||
help();
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -657,20 +658,21 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
seed = atoi(argv[2]);
|
||||
disk = atoi(argv[3]);
|
||||
file = atoi(argv[4]);
|
||||
size = atoi(argv[5]);
|
||||
tag = argv[3];
|
||||
disk = atoi(argv[4]);
|
||||
file = atoi(argv[5]);
|
||||
size = atoi(argv[6]);
|
||||
|
||||
for (i = 0; i < disk; ++i) {
|
||||
for (j = 0; j < file; ++j) {
|
||||
if (j == 0)
|
||||
/* create at least a big one */
|
||||
cmd_generate(i + 1, size);
|
||||
cmd_generate(tag, i + 1, size);
|
||||
else if (j == 1)
|
||||
/* create at least an empty one */
|
||||
cmd_generate(i + 1, 0);
|
||||
cmd_generate(tag, i + 1, 0);
|
||||
else
|
||||
cmd_generate(i + 1, rnd(size));
|
||||
cmd_generate(tag, i + 1, rnd(size));
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[1], "write") == 0) {
|
||||
|
|
|
|||
|
|
@ -659,6 +659,7 @@ void log_close(const char* file)
|
|||
#define OPT_TEST_SPEED_PERIOD 307
|
||||
#define OPT_TEST_SPEED_DISKS_NUMBER 308
|
||||
#define OPT_TEST_SPEED_BLOCKS_SIZE 309
|
||||
#define OPT_TEST_KILL_BEFORE_SYNC 310
|
||||
|
||||
|
||||
#if HAVE_GETOPT_LONG
|
||||
|
|
@ -714,6 +715,9 @@ static struct option long_options[] = {
|
|||
/* After syncing, do not write the new content file */
|
||||
{ "test-kill-after-sync", 0, 0, OPT_TEST_KILL_AFTER_SYNC },
|
||||
|
||||
/* Do not execure syncing after writing the new initial content file */
|
||||
{ "test-kill-before-sync", 0, 0, OPT_TEST_KILL_BEFORE_SYNC },
|
||||
|
||||
/* Exit with failure if after check/fix there ARE NOT unrecoverable errors. */
|
||||
{ "test-expect-unrecoverable", 0, 0, OPT_TEST_EXPECT_UNRECOVERABLE },
|
||||
|
||||
|
|
@ -1267,6 +1271,9 @@ int snapraid_main(int argc, char* argv[])
|
|||
case OPT_TEST_KILL_AFTER_SYNC :
|
||||
opt.kill_after_sync = 1;
|
||||
break;
|
||||
case OPT_TEST_KILL_BEFORE_SYNC :
|
||||
opt.kill_before_sync = 1;
|
||||
break;
|
||||
case OPT_TEST_EXPECT_UNRECOVERABLE :
|
||||
opt.expect_unrecoverable = 1;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ struct snapraid_option {
|
|||
int skip_disk_access; /**< Skip the data disk access for commands that don't need it. */
|
||||
int skip_content_access; /**< Skip the content access for commands that don't need it. */
|
||||
int kill_after_sync; /**< Kill the process after sync without saving the final state. */
|
||||
int kill_before_sync; /**< Kill the process before sync after saving the initial state. */
|
||||
int force_murmur3; /**< Force Murmur3 choice. */
|
||||
int force_spooky2; /**< Force Spooky2 choice. */
|
||||
int force_order; /**< Force sorting order. One of the SORT_* defines. */
|
||||
|
|
|
|||
|
|
@ -1431,14 +1431,15 @@ end:
|
|||
/* now the parity is fully written, no need to keep deallocated files */
|
||||
state_commit(state);
|
||||
|
||||
/* save the new state if required */
|
||||
if (!state->opt.kill_after_sync) {
|
||||
if ((state->need_write || state->opt.force_content_write))
|
||||
state_write(state);
|
||||
} else {
|
||||
log_fatal(EUSER, "WARNING! Skipped writing state due to --test-kill-after-sync option.\n");
|
||||
if (state->opt.kill_after_sync) {
|
||||
log_fatal(EUSER, "WARNING! Killing due --test-kill-after-sync option.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* save the new state if required */
|
||||
if ((state->need_write || state->opt.force_content_write))
|
||||
state_write(state);
|
||||
|
||||
state_usage_print(state);
|
||||
|
||||
if (soft_error || silent_error || io_error) {
|
||||
|
|
@ -1677,6 +1678,11 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
|
|||
log_fatal(EUSER, "WARNING! Skipped state write for --test-skip-content-write option.\n");
|
||||
}
|
||||
|
||||
if (state->opt.kill_before_sync) {
|
||||
log_fatal(EUSER, "WARNING! Killing due --test-kill-before-sync option.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* skip degenerated cases of empty parity, or skipping all */
|
||||
if (blockstart < blockmax) {
|
||||
ret = state_sync_process(state, parity_handle, blockstart, blockmax);
|
||||
|
|
|
|||
9
test/test-btrfs.conf
Normal file
9
test/test-btrfs.conf
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
blocksize 64
|
||||
parity bench/btrfs-parity
|
||||
content bench/btrfs-content
|
||||
content bench/btrfs-1-content
|
||||
disk btrfs1 bench/btrfs1/
|
||||
disk btrfs2 bench/btrfs2/
|
||||
disk btrfs3 bench/btrfs3/
|
||||
snapshot
|
||||
exclude .snapraid/
|
||||
Loading…
Add table
Add a link
Reference in a new issue