diff --git a/Makefile.am b/Makefile.am index d8aaafd2..e5610344 100644 --- a/Makefile.am +++ b/Makefile.am @@ -142,6 +142,7 @@ EXTRA_DIST = \ test/test-par1.conf \ test/test-par2.conf \ test/test-par3.conf \ + test/test-parz.conf \ test/test-par4.conf \ test/test-par5.conf \ test/test-par6.conf \ @@ -271,6 +272,7 @@ RENAME = $(srcdir)/test/test-par6-rename.conf PAR1 = $(srcdir)/test/test-par1.conf PAR2 = $(srcdir)/test/test-par2.conf PAR3 = $(srcdir)/test/test-par3.conf +PARZ = $(srcdir)/test/test-parz.conf PAR4 = $(srcdir)/test/test-par4.conf PAR5 = $(srcdir)/test/test-par5.conf PAR6 = $(srcdir)/test/test-par6.conf @@ -563,8 +565,10 @@ endif $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-none -c $(PAR1) sync -F --test-io-cache 1 $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-sequential -c $(PAR1) sync -F --test-io-stats + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-flush -c $(PAR1) sync -F --test-io-cache 1 $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-flush-window -c $(PAR1) sync -F $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-discard-window -c $(PAR1) sync -F + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-direct -c $(PAR1) sync -F #### CHANGE LINKS #### # Use a different size ("22" instead of "1") to ensure to recognize the file different # even if it gets the same timestamp in case subsecond timestamp is no available @@ -776,6 +780,12 @@ endif mv bench/disk4/a/7* bench/disk4/b/ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### SNAPRAIDIGNORE + echo "a*" > bench/disk1/a/.snapraidignore + echo "b*" > bench/disk1/.snapraidignore + echo "c/" > bench/disk1/.snapraidignore + echo "/d/" > bench/disk1/.snapraidignore + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync if !HAVE_MEMORY_CHECKER #### RECOVER 1 #### $(MSG) Delete one disk, fix and check with PAR1 @@ -809,6 +819,20 @@ if !HAVE_MEMORY_CHECKER $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR3) fix -l test.log $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER Z #### + $(MSG) Compute PARZ - keeping PAR1 and PAR2 as they are + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PARZ) fix -d 3-parity -l test.log + $(MSG) Delete three disks, fix and check with PARZ + rm -r bench/disk3 + mkdir bench/disk3 + rm -r bench/disk4 + mkdir bench/disk4 + rm -r bench/disk5 + mkdir bench/disk5 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PARZ) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PARZ) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync #### RECOVER 4 #### $(MSG) Delete four disks, fix and check with PAR4 rm -r bench/disk3 diff --git a/TODO b/TODO index 970b2e2b..b2bc6023 100644 --- a/TODO +++ b/TODO @@ -7,6 +7,8 @@ This is the list of TODO items for SnapRAID. * Integration with MergeFS ? +* Evaluate use of syscall getdents64() instead of readdir(): https://linux.die.net/man/2/getdents64 + * Check Reliability Test https://github.com/linuxhw/SMART https://github.com/linuxhw/EnterpriseDrive diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index b9c8ae4e..b7a5255a 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -101,10 +101,12 @@ void test(int argc, char* argv[]) int i; char buffer[ESC_MAX]; - /* special testing code for quoting */ + /* special testing code */ if (argc < 2 || strcmp(argv[1], "test") != 0) return; + lock_init(); + assert(strcmp(strpolish(strcpy(buffer, "\r \n\xFF")), " ") == 0); assert(strcmp(strtrim(strcpy(buffer, " trim trim \n\r")), "trim trim") == 0); assert(strcmp(strlwr(strcpy(buffer, " LoWer\n\r")), " lower\n\r") == 0); @@ -486,8 +488,14 @@ void test(int argc, char* argv[]) assert(strcmp(esc_shell("test_2024-01-01.log", buffer), "test_2024-01-01.log") == 0); #endif + random_seed(0); + assert(random_u8() == 0xAF); + assert(random_u64() == 0x6E789E6AA1B965F4ULL); + printf("Everything OK\n"); + lock_done(); + exit(EXIT_SUCCESS); } diff --git a/cmdline/state.c b/cmdline/state.c index 9a3557a9..79e612e7 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -1655,7 +1655,7 @@ static void state_map(struct snapraid_state* state) /* recommend number of parities */ if (!state->opt.no_warnings) { - /* intentionally use log_fatal() instead of log_error() to give more visibility at the warning */ + /* LCOV_EXCL_START */ if (diskcount >= 36 && state->level < 6) { log_error(EUSER, "WARNING! For %u disks, it's recommended to use six parity levels.\n", diskcount); } else if (diskcount >= 29 && state->level < 5) { @@ -1667,6 +1667,7 @@ static void state_map(struct snapraid_state* state) } else if (diskcount >= 5 && state->level < 2) { log_error(EUSER, "WARNING! For %u disks, it's recommended to use two parity levels.\n", diskcount); } + /* LCOV_EXCL_STOP */ } } diff --git a/cmdline/support.c b/cmdline/support.c index 205d358e..f61e39ee 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -98,6 +98,11 @@ void lock_done(void) static uint64_t random_state = 1; +void random_seed(uint64_t seed) +{ + random_state = seed; +} + void random_reseed(void) { random_state = tick(); @@ -138,6 +143,7 @@ uint64_t random_u64(void) int is_hw(int err) { + /* LCOV_EXCL_START */ if (err == EIO) return 1; #ifdef EFSCORRUPTED @@ -164,11 +170,13 @@ int is_hw(int err) if (err == EHWPOISON) /* hardware memory error */ return 1; #endif + /* LCOV_EXCL_STOP */ return 0; } void log_fatal_errno(int err, const char* name) { + /* LCOV_EXCL_START */ if (err == EIO) { log_fatal(err, "DANGER! Unexpected input/output error in disk %s. It isn't possible to continue.\n", name); #ifdef EFSCORRUPTED @@ -202,10 +210,12 @@ void log_fatal_errno(int err, const char* name) } else { log_fatal(err, "WARNING! Without a working %s disk, it isn't possible to continue.\n", name); } + /* LCOV_EXCL_STOP */ } void log_error_errno(int err, const char* name) { + /* LCOV_EXCL_START */ if (err == EIO) { log_fatal(err, "DANGER! Unexpected input/output error in disk %s.\n", name); #ifdef EFSCORRUPTED @@ -232,6 +242,7 @@ void log_error_errno(int err, const char* name) } else if (err == EHWPOISON) { log_fatal(err, "DANGER! Unexpected memory error in disk %s.\n", name); #endif + /* LCOV_EXCL_STOP */ } else if (err == EACCES) { log_error(err, "WARNING! Grant permission in the disk %s.\n", name); } else if (err == ENOSPC) { diff --git a/cmdline/support.h b/cmdline/support.h index 624ae789..69fb90bd 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -56,7 +56,12 @@ void unlock_memory(void); /* random */ /** - * Reseed the random pseudo random number generator + * Seed the random pseudo random number generator + */ +void random_seed(uint64_t seed); + +/** + * Reseed the random pseudo random number generator with the tick count */ void random_reseed(void); diff --git a/cmdline/util.c b/cmdline/util.c index 2395390c..860b3368 100644 --- a/cmdline/util.c +++ b/cmdline/util.c @@ -764,6 +764,7 @@ const char* hash_config_name(unsigned kind) case HASH_MURMUR3 : return "murmur3"; case HASH_SPOOKY2 : return "spooky2"; case HASH_METRO : return "metro"; + case HASH_MUSEAIR : return "museair"; default : /* LCOV_EXCL_START */ return "unknown"; diff --git a/makecov.sh b/makecov.sh index 4a0bbd99..eded9147 100755 --- a/makecov.sh +++ b/makecov.sh @@ -9,8 +9,22 @@ if ! ./configure --enable-coverage --enable-sde; then exit 1 fi -if ! make lcov_reset check lcov_capture lcov_html; then +if ! make lcov_reset; then exit 1 fi +if ! make check; then + exit 1 +fi +# Run commands on a real array to test smartctl +sudo ./snapraid probe +sudo ./snapraid up +sudo ./snapraid smart +sudo ./snapraid probe +sudo ./snapraid devices +sudo ./snapraid down + +if ! make lcov_capture lcov_html; then + exit 1 +fi diff --git a/test/test-par1.conf b/test/test-par1.conf index 3b9bf8eb..a13c8d61 100644 --- a/test/test-par1.conf +++ b/test/test-par1.conf @@ -1,4 +1,5 @@ # Test configuration file +hashsize 16 blocksize 1 parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 content bench/content diff --git a/test/test-parz.conf b/test/test-parz.conf new file mode 100644 index 00000000..0f8db9cf --- /dev/null +++ b/test/test-parz.conf @@ -0,0 +1,17 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +z-parity bench/z-parity.0,bench/z-parity.1,bench/z-parity.2,bench/z-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable +