diff --git a/Makefile.am b/Makefile.am index da0fab24..dc9742bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,7 +71,7 @@ EXTRA_DIST = \ noautomake.sh \ README AUTHORS HISTORY INSTALL COPYING TODO TEST INSTALL.windows \ snapraid.d snapraid.1 snapraid.txt \ - test-raid5.conf test-raid6.conf test-raid6-hole.conf \ + test-raid5.conf test-raid6.conf test-raidTP.conf test-raidTP-hole.conf \ snapraid.conf.example \ configure.windows-x86 configure.windows-x64 snapraid.conf.example.windows \ acinclude.m4 @@ -92,9 +92,14 @@ maintainer-clean-local: # Automatic testing -CHECKFLAGS = --test-skip-device +CHECKFLAGS = --test-skip-device --test-skip-self CHECKCOUNT = 2000 CHECKSIZE = 4000 +CONF = $(srcdir)/test-raidTP.conf +HOLE = $(srcdir)/test-raidTP-hole.conf +RAID5 = $(srcdir)/test-raid5.conf +RAID6 = $(srcdir)/test-raid6.conf +RAIDTP = $(srcdir)/test-raidTP.conf check-local: rm -rf test @@ -103,35 +108,37 @@ check-local: mkdir test/disk1 mkdir test/disk2 mkdir test/disk3 + mkdir test/disk4 mkdir test/pool echo --- Help - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -h + $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -h + echo --- SelfTest + $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -c $(CONF) status echo --- As empty, sync and check forcing murmur3 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid6.conf diff - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid6.conf dup - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(srcdir)/test-raid6.conf --test-force-murmur3 sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(CONF) diff + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(CONF) dup + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-murmur3 sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status if HAVE_SYMLINK - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf pool + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) pool endif - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -a check - echo --- Create some files, sync raid6 and check - $(TESTENV) ./mktest$(EXEEXT) generate 1 3 $(CHECKCOUNT) $(CHECKSIZE) - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid6.conf diff > test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid6.conf dup - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-order-physical sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check + echo --- Create some files, sync and check in RAID5/6/TP + $(TESTENV) ./mktest$(EXEEXT) generate 1 4 $(CHECKCOUNT) $(CHECKSIZE) + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(CONF) diff > test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(CONF) dup + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-order-physical sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status if HAVE_SYMLINK - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf pool + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) pool endif - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf -a check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -a check - echo --- Create some more files, hardlinks and empty directories, sync raid5 and check - $(TESTENV) ./mktest$(EXEEXT) generate 2 3 $(CHECKCOUNT) $(CHECKSIZE) + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check + echo --- Create some more files, hardlinks and empty directories, sync RAID5 and check + $(TESTENV) ./mktest$(EXEEXT) generate 2 4 $(CHECKCOUNT) $(CHECKSIZE) mkdir test/disk1/empty1 mkdir test/disk2/empty2 mkdir test/disk3/empty3a @@ -146,262 +153,279 @@ endif echo 3 > test/disk3/file_hardlink1 ln test/disk3/file_hardlink1 test/disk3/file_hardlink2 ln test/disk3/file_hardlink1 test/disk3/file_hardlink3 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid5.conf diff > test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid5.conf dup - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-skip-fallocate -c $(srcdir)/test-raid5.conf --test-force-order-inode sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-skip-sequential -c $(srcdir)/test-raid5.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(RAID5) diff > test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(RAID5) dup + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-fallocate -c $(RAID5) --test-force-order-inode sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-sequential -c $(RAID5) check if HAVE_SYMLINK - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf pool + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) pool endif - echo --- Extend raid5 to raid6 with fix and check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check 2>> test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix 2>> test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + echo --- Extend RAID5 to RAIDTP with fix and check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(CONF) check 2>> test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix 2>> test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Dry - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf dry - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf dry + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) dry echo --- Scrub some times - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-scrub 100 scrub - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-scrub 1000 scrub - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-scrub 100000 scrub - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub 100 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub 1000 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub 100000 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status echo --- Corrupt one file, scrub and fix filtering for error rm -f test/disk1/content cp test/content test/disk1/content - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync $(TESTENV) ./mktest$(EXEEXT) damage 1 10 1 test/disk1/content - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-expect-recoverable --test-force-scrub 100000 scrub - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -e - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -p 0 scrub - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -o 0 scrub - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -p 100 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-recoverable --test-force-scrub 100000 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -e + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p 0 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -o 0 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p 100 scrub rm test/disk1/content - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync echo --- Make a hole in the disk array and sync with --force-empty mv test/disk2 test/disk2.old mkdir test/disk2 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --force-empty sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --force-empty sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Use with the hole - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6-hole.conf sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6-hole.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) check rm -r test/disk1/_a rm -r test/disk3/_a - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6-hole.conf fix 2>> test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6-hole.conf check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6-hole.conf dry + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) fix 2>> test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) dry echo --- Fill the hole with a new disk rm -r test/disk2 mv test/disk2.old test/disk2 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Delete some files, create some new, sync and check rm test/disk1/1* rm test/disk2/2* rm test/disk3/3* - $(TESTENV) ./mktest$(EXEEXT) generate 3 3 $(CHECKCOUNT) $(CHECKSIZE) - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + rm test/disk4/4* + $(TESTENV) ./mktest$(EXEEXT) generate 3 4 $(CHECKCOUNT) $(CHECKSIZE) + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Move some files, sync and check mv test/disk1/7* test/disk1/_a/ mv test/disk2/7* test/disk2/_a/ mv test/disk3/7* test/disk3/_a/ - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete one disk, fix and check with raid5 + mv test/disk4/7* test/disk4/_a/ + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete one disk, fix and check with RAID5 rm -r test/disk3 mkdir test/disk3 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf check 2>> test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf fix 2>> test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) check 2>> test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) fix 2>> test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Sync after all the fixes with an empty drive to test --force-empty - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --force-empty -c $(srcdir)/test-raid6.conf sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete two disks, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --force-empty -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete two disks, fix and check with RAID6 rm -r test/disk1 mkdir test/disk1 rm -r test/disk2 mkdir test/disk2 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid5.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + echo --- Delete theree disks, fix and check with RAIDTP + rm -r test/disk1 + mkdir test/disk1 + rm -r test/disk2 + mkdir test/disk2 + rm -r test/disk3 + mkdir test/disk3 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAIDTP) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAIDTP) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync echo --- Delete some files and create some new, sync and check in multiple steps rm test/disk1/4* rm test/disk2/5* rm test/disk3/6* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -t 10 sync --test-force-content-text + rm test/disk4/6* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -t 10 sync --test-force-content-text cp test/content test/content.txt - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf test-rewrite - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-content-text test-rewrite + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) test-rewrite + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-content-text test-rewrite cmp test/content test/content.txt - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./mktest$(EXEEXT) generate 4 3 $(CHECKCOUNT) $(CHECKSIZE) - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -t 100 sync --test-force-content-text + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log + $(TESTENV) ./mktest$(EXEEXT) generate 4 4 $(CHECKCOUNT) $(CHECKSIZE) + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -t 100 sync --test-force-content-text cp test/content test/content.txt - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf test-rewrite - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-content-text test-rewrite + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) test-rewrite + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-content-text test-rewrite cmp test/content test/content.txt - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -t 1000 sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -t 1000 sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Rehash to spooky2 and rehash even blocks - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-spooky2 rehash - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-force-scrub-even scrub - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf status - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-spooky2 rehash + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-even scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Delete files from three disks and fix with import in RAID6 rm -r test/disk1/_a rm -r test/disk1/_b rm -r test/disk2/_a rm -r test/disk2/_b mv test/disk3/_a test/_a - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -i test/_a -c $(srcdir)/test-raid6.conf fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -i test/_a -c $(RAID6) fix -l test.log rm -r test/_a - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync echo --- Abort sync late with additions, delete them and recover with RAID6 echo --- This triggers the recoving with q using p to check the validity cp -pR test/disk1/_a test/disk1/_c cp -pR test/disk1/_a test/disk1/_d - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-kill-after-sync -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) sync rm -r test/disk1/_c rm -r test/disk1/_d - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log rm -r test/disk1/_c rm -r test/disk1/_d - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync echo --- Abort sync early with additions, delete them and recover with RAID6 echo --- This triggers the recoving with q using p to check the validity, but failing for new block being filled with zero cp -pR test/disk1/_a test/disk1/_c cp -pR test/disk1/_a test/disk1/_d - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -t 1 --test-kill-after-sync -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -t 1 --test-kill-after-sync -c $(CONF) sync rm -r test/disk1/_c rm -r test/disk1/_d - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid6.conf fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID6) fix -l test.log rm -r test/disk1/_c rm -r test/disk1/_d - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync echo --- Abort sync late with additions and then delete the new additions and sync again cp -pR test/disk1/_a test/disk1/_c cp -pR test/disk2/_a test/disk2/_c cp -pR test/disk3/_a test/disk3/_c - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-kill-after-sync -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) sync rm -r test/disk1/_c rm -r test/disk2/_c rm -r test/disk3/_c - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync - echo --- Abort sync late with additions and then delete some unchanged stuff and fix with RAID5 and then with RAID6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + echo --- Abort sync late with additions and then delete some unchanged stuff and fix with RAID5 cp -pR test/disk1/_b test/disk1/_c - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf --test-kill-after-sync sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) --test-kill-after-sync sync rm -r test/disk2 mkdir test/disk2 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) fix -l test.log + echo --- Fixes again with RAIDTP to restore all the parity + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -l test.log rm -r test/disk1/_c - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync echo --- Abort sync late with more deletions than additions and then delete some unchanged stuff and fix with RAID5 cp -pR test/disk1/_a test/disk1/_c mv test/disk1/_a test/_a mv test/disk1/_b test/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf --test-kill-after-sync sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync rm -r test/disk2 mkdir test/disk2 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) fix -l test.log + echo --- Fixes again with RAIDTP to restore all the parity + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -l test.log -rm -r test/disk1/_a -rm -r test/disk1/_b rm -r test/disk1/_c mv test/_a test/disk1/_a mv test/_b test/disk1/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync echo --- Abort sync early with more deletions than additions and then delete some unchanged stuff and fix with RAID6 cp -pR test/disk1/_a test/disk1/_c mv test/disk1/_a test/_a mv test/disk1/_b test/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -t 1 --test-kill-after-sync sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -t 1 --test-kill-after-sync sync rm -r test/disk2 mkdir test/disk2 - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid5.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log -rm -r test/disk1/_a -rm -r test/disk1/_b rm -r test/disk1/_c mv test/_a test/disk1/_a mv test/_b test/disk1/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync - echo --- Delete some files, fix with -m and check with raid5 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + echo --- Delete some files, fix with -m and check with RAID5 rm test/disk1/8* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf -m fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete some dirs in a disk, fix with -m and check with raid5 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) -m fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete some dirs in a disk, fix with -m and check with RAID5 rm -r test/disk2/_a rm -r test/disk2/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf -m fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete some dirs in two disks, fix and check with raid6 using the -d option for each disk + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) -m fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete some dirs in two disks, fix and check with RAID6 using the -d option for each disk rm -r test/disk2/_a rm -r test/disk2/_b rm -r test/disk3/_a rm -r test/disk3/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid5.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -d disk2 fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -d disk3 fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete the parity, fix and check with raid5 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) -d disk2 fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) -d disk3 fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete the parity, fix and check with RAID5 rm test/parity - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete the parity and the q-parity, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete the parity and the q-parity, fix and check with RAID6 rm test/parity rm test/q-parity - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete the parity and a disk, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete the parity and a disk, fix and check with RAID6 rm test/parity rm -r test/disk2/_a rm -r test/disk2/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Delete the q-parity and a disk, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Delete the q-parity and a disk, fix and check with RAID6 rm test/q-parity rm -r test/disk3/_a rm -r test/disk3/_b - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Corrupt the parity, fix and check with raid5 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Corrupt the parity, fix and check with RAID5 $(TESTENV) ./mktest$(EXEEXT) damage 1 100 10000 test/parity - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf -a check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Corrupt the parity and the q-parity, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) -a check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Corrupt the parity and the q-parity, fix and check with RAID6 $(TESTENV) ./mktest$(EXEEXT) damage 2 100 10000 test/parity $(TESTENV) ./mktest$(EXEEXT) damage 2 100 10000 test/q-parity - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf -a check - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Corrupt some files, fix and check with raid5 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Corrupt some files, fix and check with RAID5 $(TESTENV) ./mktest$(EXEEXT) damage 3 1 500 test/disk2/b* $(TESTENV) ./mktest$(EXEEXT) append 3 500 test/disk2/c* $(TESTENV) ./mktest$(EXEEXT) truncate 3 500 test/disk2/d* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf -a check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Corrupt some files, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) -a check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Corrupt some files, fix and check with RAID6 $(TESTENV) ./mktest$(EXEEXT) damage 4 1 500 test/disk2/_a/_a/* $(TESTENV) ./mktest$(EXEEXT) damage 4 1 500 test/disk3/_a/_a/* $(TESTENV) ./mktest$(EXEEXT) damage 4 1 500 test/disk2/_a/_b/* @@ -410,12 +434,12 @@ endif $(TESTENV) ./mktest$(EXEEXT) append 4 500 test/disk3/_b/_a/* $(TESTENV) ./mktest$(EXEEXT) truncate 4 500 test/disk2/_b/_b/* $(TESTENV) ./mktest$(EXEEXT) truncate 4 500 test/disk3/_b/_b/* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf -a check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf -a check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) -a check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) -a check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Another time with different values $(TESTENV) ./mktest$(EXEEXT) damage 5 2 50 test/disk2/_a/_a/* $(TESTENV) ./mktest$(EXEEXT) damage 5 2 50 test/disk3/_a/_a/* @@ -427,38 +451,38 @@ endif $(TESTENV) ./mktest$(EXEEXT) append 5 1500 test/disk3/_b/_a/* $(TESTENV) ./mktest$(EXEEXT) truncate 5 1500 test/disk2/_b/_b/* $(TESTENV) ./mktest$(EXEEXT) truncate 5 1500 test/disk3/_b/_b/* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Corrupt the parity and some files, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Corrupt the parity and some files, fix and check with RAID6 $(TESTENV) ./mktest$(EXEEXT) damage 6 100 10000 test/parity $(TESTENV) ./mktest$(EXEEXT) damage 6 1 500 test/disk1/_a/_a/* $(TESTENV) ./mktest$(EXEEXT) damage 6 1 500 test/disk1/_a/_b/* $(TESTENV) ./mktest$(EXEEXT) append 6 500 test/disk1/_b/_a/* $(TESTENV) ./mktest$(EXEEXT) truncate 6 500 test/disk1/_b/_b/* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-unrecoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check - echo --- Corrupt the q-parity and some files, fix and check with raid6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + echo --- Corrupt the q-parity and some files, fix and check with RAID6 $(TESTENV) ./mktest$(EXEEXT) damage 7 100 10000 test/q-parity $(TESTENV) ./mktest$(EXEEXT) damage 7 1 500 test/disk1/_a/_a/* $(TESTENV) ./mktest$(EXEEXT) damage 7 1 500 test/disk1/_a/_b/* $(TESTENV) ./mktest$(EXEEXT) append 7 500 test/disk1/_b/_a/* $(TESTENV) ./mktest$(EXEEXT) truncate 7 500 test/disk1/_b/_b/* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid5.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-expect-recoverable -c $(srcdir)/test-raid6.conf check -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf fix -l test.log - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(RAID6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RAID6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo --- Sync after all the fixes - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf sync - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid6.conf check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check echo Success! # Manual testing -MANUAL = ./snapraid --test-skip-self --test-skip-device -c test-raid5.conf sync +MANUAL = ./snapraid --test-skip-device -c test-raid5.conf sync valgrind: valgrind \ diff --git a/check.c b/check.c index 1ec85967..bc1f4370 100644 --- a/check.c +++ b/check.c @@ -94,7 +94,7 @@ static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_bl * Returns <0 if failure for missing strategy, >0 if data is wrong and we cannot rebuild correctly, 0 on success. * If success, the parity and qarity are computed in the buffer variable. */ -static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, unsigned char** buffer, unsigned char* buffer_parity, unsigned char* buffer_qarity, unsigned char* buffer_zero) +static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, unsigned char** buffer, unsigned char* buffer_parity, unsigned char* buffer_qarity, unsigned char* buffer_rarity, unsigned char* buffer_zero) { unsigned j; int error = 0; @@ -127,7 +127,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u hash_checked = 0; /* keep track if we check at least one block */ /* check if the recovered blocks are OK */ - for(j=0;j<1;++j) { + for(j=0;jlevel, buffer, diskmax, state->block_size); return 0; @@ -157,7 +157,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u hash_checked = 0; /* keep track if we check at least one block */ /* check if the recovered blocks are OK */ - for(j=0;j<1;++j) { + for(j=0;jlevel, buffer, diskmax, state->block_size); return 0; @@ -210,7 +210,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u hash_checked = 0; /* keep track if we check at least one block */ /* check if the recovered blocks are OK */ - for(j=0;j<2;++j) { + for(j=0;jlevel, buffer, diskmax, state->block_size); return 0; @@ -229,6 +229,177 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u ++error; } + /* RAIDTP recovering from r, ignoring p,q */ + if (failed_count == 1 && buffer_rarity != 0 && has_hash) { + /* copy the redundancy to use */ + memcpy(buffer[diskmax+2], buffer_rarity, state->block_size); + + /* recover data */ + raidTP_recov_datapq(buffer, diskmax, state->block_size, failed[failed_map[0]].index, buffer_zero); + + hash_checked = 0; /* keep track if we check at least one block */ + + /* check if the recovered blocks are OK */ + for(j=0;jlevel, buffer, diskmax, state->block_size); + return 0; + } + + fprintf(stdlog, "error:%u:rarity: Data error\n", pos); + ++error; + } + + /* RAIDTP recovering from r, using p or q to check the result */ + if (failed_count == 1 && (buffer_parity != 0 || buffer_qarity != 0) && buffer_rarity != 0 && !has_hash) { + /* copy the redundancy to use */ + memcpy(buffer[diskmax+2], buffer_rarity, state->block_size); + + /* recover data */ + raidTP_recov_datapq(buffer, diskmax, state->block_size, failed[failed_map[0]].index, buffer_zero); + + /* recompute parity with RAID6 to get p and q from it */ + raid_gen(2, buffer, diskmax, state->block_size); + + /* if the recovered parity block matches */ + if ((buffer_parity != 0 && memcmp(buffer[diskmax], buffer_parity, state->block_size) == 0) + || (buffer_qarity != 0 && memcmp(buffer[diskmax+1], buffer_qarity, state->block_size) == 0) + ) { + /* recompute all the redundancy information */ + raid_gen(state->level, buffer, diskmax, state->block_size); + return 0; + } + + fprintf(stdlog, "error:%u:parity/qarity/rarity: Data error\n", pos); + ++error; + } + + /* RAIDTP recovering from p+r */ + if (failed_count == 2 && buffer_parity != 0 && buffer_rarity != 0 && has_hash) { + /* copy the redundancy to use */ + memcpy(buffer[diskmax], buffer_parity, state->block_size); + memcpy(buffer[diskmax+2], buffer_rarity, state->block_size); + + /* recover 2 data */ + raidTP_recov_2dataq(buffer, diskmax, state->block_size, failed[failed_map[0]].index, failed[failed_map[1]].index, buffer_zero); + + hash_checked = 0; /* keep track if we check at least one block */ + + /* check if the recovered blocks are OK */ + for(j=0;jlevel, buffer, diskmax, state->block_size); + return 0; + } + + fprintf(stdlog, "error:%u:parity/rarity: Data error\n", pos); + ++error; + } + + /* RAIDTP recovering from q+r */ + if (failed_count == 2 && buffer_qarity != 0 && buffer_rarity != 0 && has_hash) { + /* copy the redundancy to use */ + memcpy(buffer[diskmax+1], buffer_qarity, state->block_size); + memcpy(buffer[diskmax+2], buffer_rarity, state->block_size); + + /* recover 2 data */ + raidTP_recov_2datap(buffer, diskmax, state->block_size, failed[failed_map[0]].index, failed[failed_map[1]].index, buffer_zero); + + hash_checked = 0; /* keep track if we check at least one block */ + + /* check if the recovered blocks are OK */ + for(j=0;jlevel, buffer, diskmax, state->block_size); + return 0; + } + + fprintf(stdlog, "error:%u:qarity/rarity: Data error\n", pos); + ++error; + } + + /* RAIDTP recovering from q+r, using p to check the result */ + if (failed_count == 2 && buffer_parity != 0 && buffer_qarity != 0 && buffer_rarity != 0 && !has_hash) { + /* copy the redundancy to use */ + memcpy(buffer[diskmax+1], buffer_qarity, state->block_size); + memcpy(buffer[diskmax+2], buffer_rarity, state->block_size); + + /* recover data */ + raidTP_recov_2datap(buffer, diskmax, state->block_size, failed[failed_map[0]].index, failed[failed_map[1]].index, buffer_zero); + + /* recompute parity with RAID5 to get p from it */ + raid_gen(1, buffer, diskmax, state->block_size); + + /* if the recovered parity block matches */ + if (buffer_parity != 0 && memcmp(buffer[diskmax], buffer_parity, state->block_size) == 0) { + /* recompute all the redundancy information */ + raid_gen(state->level, buffer, diskmax, state->block_size); + return 0; + } + + fprintf(stdlog, "error:%u:parity/qarity/rarity: Data error\n", pos); + ++error; + } + + /* RAIDTP recovering from p+q+r */ + if (failed_count == 3 && buffer_parity != 0 && buffer_qarity != 0 && buffer_rarity != 0 && has_hash) { + /* copy the redundancy to use */ + memcpy(buffer[diskmax], buffer_parity, state->block_size); + memcpy(buffer[diskmax+1], buffer_qarity, state->block_size); + memcpy(buffer[diskmax+2], buffer_rarity, state->block_size); + + /* recover 3 data */ + raidTP_recov_3data(buffer, diskmax, state->block_size, failed[failed_map[0]].index, failed[failed_map[1]].index, failed[failed_map[2]].index, buffer_zero); + + hash_checked = 0; /* keep track if we check at least one block */ + + /* check if the recovered blocks are OK */ + for(j=0;jlevel, buffer, diskmax, state->block_size); + return 0; + } + + fprintf(stdlog, "error:%u:parity/qarity/rarity: Data error\n", pos); + ++error; + } + /* return the number of failed attempts, or -1 if no strategy */ if (error) return error; @@ -236,7 +407,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u return -1; } -static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, unsigned char** buffer, unsigned char* buffer_parity, unsigned char* buffer_qarity, unsigned char* buffer_zero) +static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, unsigned char** buffer, unsigned char* buffer_parity, unsigned char* buffer_qarity, unsigned char* buffer_rarity, unsigned char* buffer_zero) { int ret; int error; @@ -300,7 +471,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign return 0; } - ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_parity, buffer_qarity, buffer_zero); + ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_parity, buffer_qarity, buffer_rarity, buffer_zero); if (ret == 0) { /* reprocess the blocks for NEW and CHG ones, for which we don't have a hash to check */ /* if they were BAD we have to use some euristics to ensure that we have recovered */ @@ -417,7 +588,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign /* if nothing to fix, we just don't try */ if (something_to_recover) { - ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_parity, buffer_qarity, buffer_zero); + ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_parity, buffer_qarity, buffer_rarity, buffer_zero); if (ret == 0) { /* we alreay marked as outdated NEW and CHG blocks, we don't need to do it again */ return 0; @@ -433,7 +604,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign return -1; } -static int state_check_process(struct snapraid_state* state, int check, int fix, struct snapraid_parity* parity, struct snapraid_parity* qarity, block_off_t blockstart, block_off_t blockmax) +static int state_check_process(struct snapraid_state* state, int check, int fix, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; unsigned diskmax; @@ -737,15 +908,22 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, if (check) { unsigned char* buffer_parity; unsigned char* buffer_qarity; + unsigned char* buffer_rarity; unsigned char* buffer_zero; /* buffers for parity read and not computed */ if (state->level == 1) { buffer_parity = buffer[diskmax + 1]; buffer_qarity = 0; - } else { + buffer_rarity = 0; + } else if (state->level == 2) { buffer_parity = buffer[diskmax + 2]; buffer_qarity = buffer[diskmax + 3]; + buffer_rarity = 0; + } else { + buffer_parity = buffer[diskmax + 3]; + buffer_qarity = buffer[diskmax + 4]; + buffer_rarity = buffer[diskmax + 5]; } buffer_zero = buffer[buffermax-1]; @@ -777,8 +955,23 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, } } + /* read the rarity */ + if (state->level >= 3) { + if (rarity) { + ret = parity_read(rarity, i, buffer_rarity, state->block_size, stdlog); + if (ret == -1) { + buffer_rarity = 0; /* no rarity to use */ + + fprintf(stdlog, "error:%u:rarity: Read error\n", i); + ++error; + } + } else { + buffer_rarity = 0; + } + } + /* try all the recovering strategies */ - ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_parity, buffer_qarity, buffer_zero); + ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_parity, buffer_qarity, buffer_rarity, buffer_zero); if (ret != 0) { /* increment the number of errors */ if (ret > 0) @@ -835,6 +1028,16 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, ++error; } } + + /* check the rarity */ + if (state->level >= 3) { + if (buffer_rarity != 0 && memcmp(buffer_rarity, buffer[diskmax + 2], state->block_size) != 0) { + buffer_rarity = 0; + + fprintf(stdlog, "error:%u:rarity: Data error\n", i); + ++error; + } + } } /* now writes recovered files */ @@ -914,6 +1117,23 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, ++recovered_error; } } + + /* update the rarity */ + if (state->level >= 3) { + if (buffer_rarity == 0 && rarity) { + ret = parity_write(rarity, i, buffer[diskmax + 2], state->block_size); + if (ret == -1) { + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + fprintf(stderr, "WARNING! Without a working R-Parity disk, it isn't possible to fix errors on it.\n"); + printf("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + } + + fprintf(stdlog, "fixed:%u:rarity: Fixed data error\n", i); + ++recovered_error; + } + } } } else { /* if we are not fixing, we just set the FIXED flag */ @@ -1582,8 +1802,10 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl int ret; struct snapraid_parity parity; struct snapraid_parity qarity; + struct snapraid_parity rarity; struct snapraid_parity* parity_ptr; struct snapraid_parity* qarity_ptr; + struct snapraid_parity* rarity_ptr; unsigned error; printf("Initializing...\n"); @@ -1638,6 +1860,23 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl } else { qarity_ptr = 0; } + + if (state->level >= 3) { + rarity_ptr = &rarity; + ret = parity_create(rarity_ptr, state->rarity, &out_size, state->opt.skip_sequential); + if (ret == -1) { + fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to fix any error.\n"); + exit(EXIT_FAILURE); + } + + ret = parity_chsize(rarity_ptr, size, &out_size, state->opt.skip_fallocate); + if (ret == -1) { + fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to sync.\n"); + exit(EXIT_FAILURE); + } + } else { + rarity_ptr = 0; + } } else if (check) { /* if checking, open the file for reading */ /* it may fail if the file doesn't exist, in this case we continue to check the files */ @@ -1660,10 +1899,23 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl } else { qarity_ptr = 0; } + + if (state->level >= 3) { + rarity_ptr = &rarity; + ret = parity_open(rarity_ptr, state->rarity, state->opt.skip_sequential); + if (ret == -1) { + printf("No accessible R-Parity file, only files will be checked.\n"); + /* continue anyway */ + rarity_ptr = 0; + } + } else { + rarity_ptr = 0; + } } else { /* otherwise don't use any parity */ parity_ptr = 0; qarity_ptr = 0; + rarity_ptr = 0; } if (fix) @@ -1677,7 +1929,7 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { - ret = state_check_process(state, check, fix, parity_ptr, qarity_ptr, blockstart, blockmax); + ret = state_check_process(state, check, fix, parity_ptr, qarity_ptr, rarity_ptr, blockstart, blockmax); if (ret == -1) { ++error; /* continue, as we are already exiting */ @@ -1705,6 +1957,17 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl } } + if (state->level >= 3) { + if (rarity_ptr) { + ret = parity_close(rarity_ptr); + if (ret == -1) { + fprintf(stderr, "DANGER! Unexpected close error in R-Parity disk.\n"); + ++error; + /* continue, as we are already exiting */ + } + } + } + /* abort if error are present */ if (error != 0) return -1; diff --git a/dry.c b/dry.c index d00a52e1..9bca85ea 100644 --- a/dry.c +++ b/dry.c @@ -26,7 +26,7 @@ /****************************************************************************/ /* dry */ -static int state_dry_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, block_off_t blockstart, block_off_t blockmax) +static int state_dry_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; unsigned diskmax; @@ -117,6 +117,17 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit } } + /* read the rarity */ + if (state->level >= 3) { + if (rarity) { + ret = parity_read(rarity, i, buffer_aligned, state->block_size, stdlog); + if (ret == -1) { + fprintf(stdlog, "error:%u:rarity: Read error\n", i); + ++error; + } + } + } + /* count the number of processed block */ ++countpos; @@ -159,8 +170,10 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t int ret; struct snapraid_parity parity; struct snapraid_parity qarity; + struct snapraid_parity rarity; struct snapraid_parity* parity_ptr; struct snapraid_parity* qarity_ptr; + struct snapraid_parity* rarity_ptr; unsigned error; printf("Drying...\n"); @@ -199,11 +212,23 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t qarity_ptr = 0; } + if (state->level >= 3) { + rarity_ptr = &rarity; + ret = parity_open(rarity_ptr, state->rarity, state->opt.skip_sequential); + if (ret == -1) { + printf("No accessible R-Parity file.\n"); + /* continue anyway */ + rarity_ptr = 0; + } + } else { + rarity_ptr = 0; + } + error = 0; /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { - ret = state_dry_process(state, parity_ptr, qarity_ptr, blockstart, blockmax); + ret = state_dry_process(state, parity_ptr, qarity_ptr, rarity_ptr, blockstart, blockmax); if (ret == -1) { ++error; /* continue, as we are already exiting */ @@ -229,6 +254,16 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t } } + if (state->level >= 3) { + if (rarity_ptr) { + ret = parity_close(rarity_ptr); + if (ret == -1) { + ++error; + /* continue, as we are already exiting */ + } + } + } + /* abort if required */ if (error != 0) exit(EXIT_FAILURE); diff --git a/scrub.c b/scrub.c index b15cc4cc..bb405de9 100644 --- a/scrub.c +++ b/scrub.c @@ -35,7 +35,7 @@ struct snapraid_rehash { struct snapraid_block* block; }; -static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, block_off_t blockstart, block_off_t blockmax, time_t timelimit, block_off_t countlimit, time_t now) +static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax, time_t timelimit, block_off_t countlimit, time_t now) { struct snapraid_handle* handle; void* rehandle_alloc; @@ -283,14 +283,21 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par if (!error_on_this_block && !silent_error_on_this_block) { unsigned char* buffer_parity; unsigned char* buffer_qarity; + unsigned char* buffer_rarity; /* buffers for parity read and not computed */ if (state->level == 1) { buffer_parity = buffer[diskmax + 1]; buffer_qarity = 0; - } else { + buffer_rarity = 0; + } else if (state->level == 2) { buffer_parity = buffer[diskmax + 2]; buffer_qarity = buffer[diskmax + 3]; + buffer_rarity = 0; + } else { + buffer_parity = buffer[diskmax + 3]; + buffer_qarity = buffer[diskmax + 4]; + buffer_rarity = buffer[diskmax + 5]; } /* read the parity */ @@ -313,6 +320,17 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par } } + /* read the rarity */ + if (state->level >= 3) { + ret = parity_read(rarity, i, buffer_rarity, state->block_size, stdlog); + if (ret == -1) { + buffer_rarity = 0; + fprintf(stdlog, "error:%u:rarity: Read error\n", i); + ++error; + error_on_this_block = 1; + } + } + /* compute the parity */ raid_gen(state->level, buffer, diskmax, state->block_size); @@ -329,6 +347,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par silent_error_on_this_block = 1; } } + if (state->level >= 2) { if (buffer_qarity && memcmp(buffer[diskmax + 1], buffer_qarity, state->block_size) != 0) { fprintf(stdlog, "error:%u:qarity: Data error\n", i); @@ -343,6 +362,21 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par } } } + + if (state->level >= 3) { + if (buffer_rarity && memcmp(buffer[diskmax + 2], buffer_rarity, state->block_size) != 0) { + fprintf(stdlog, "error:%u:rarity: Data error\n", i); + ++error; + + /* it's a silent error only if we are dealing with synched blocks */ + if (block_is_unsynched) { + error_on_this_block = 1; + } else { + ++silent_error; + silent_error_on_this_block = 1; + } + } + } } if (silent_error_on_this_block) { @@ -440,8 +474,10 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan) int ret; struct snapraid_parity parity; struct snapraid_parity qarity; + struct snapraid_parity rarity; struct snapraid_parity* parity_ptr; struct snapraid_parity* qarity_ptr; + struct snapraid_parity* rarity_ptr; snapraid_info* infomap; unsigned error; time_t now; @@ -541,11 +577,22 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan) qarity_ptr = 0; } + if (state->level >= 3) { + rarity_ptr = &rarity; + ret = parity_open(rarity_ptr, state->rarity, state->opt.skip_sequential); + if (ret == -1) { + fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to scrub.\n"); + exit(EXIT_FAILURE); + } + } else { + rarity_ptr = 0; + } + printf("Scrubbing...\n"); error = 0; - ret = state_scrub_process(state, parity_ptr, qarity_ptr, 0, blockmax, timelimit, countlimit, now); + ret = state_scrub_process(state, parity_ptr, qarity_ptr, rarity_ptr, 0, blockmax, timelimit, countlimit, now); if (ret == -1) { ++error; /* continue, as we are already exiting */ @@ -567,6 +614,15 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan) } } + if (state->level >= 3) { + ret = parity_close(rarity_ptr); + if (ret == -1) { + fprintf(stderr, "DANGER! Unexpected close error in R-Parity disk.\n"); + ++error; + /* continue, as we are already exiting */ + } + } + /* abort if required */ if (error != 0) return -1; diff --git a/state.c b/state.c index 2b5f0408..b6df158e 100644 --- a/state.c +++ b/state.c @@ -34,6 +34,8 @@ void state_init(struct snapraid_state* state) state->parity_device = 0; state->qarity[0] = 0; state->qarity_device = 0; + state->rarity[0] = 0; + state->rarity_device = 0; state->pool[0] = 0; state->pool_device = 0; state->lockfile[0] = 0; @@ -69,11 +71,21 @@ static void state_config_check(struct snapraid_state* state, const char* path) { tommy_node* i; - if (state->parity[0] == 0) { + if (state->level >= 1 && state->parity[0] == 0) { fprintf(stderr, "No 'parity' specification in '%s'\n", path); exit(EXIT_FAILURE); } + if (state->level >= 2 && state->qarity[0] == 0) { + fprintf(stderr, "No 'q-parity' specification in '%s'\n", path); + exit(EXIT_FAILURE); + } + + if (state->level >= 3 && state->rarity[0] == 0) { + fprintf(stderr, "No 'r-parity' specification in '%s'\n", path); + exit(EXIT_FAILURE); + } + if (tommy_list_empty(&state->contentlist)) { fprintf(stderr, "No 'content' specification in '%s'\n", path); exit(EXIT_FAILURE); @@ -89,7 +101,12 @@ static void state_config_check(struct snapraid_state* state, const char* path) } if (state->qarity[0] != 0 && pathcmp(state->qarity, content->content) == 0) { - fprintf(stderr, "Same path used for 'qarity' and 'content' as '%s'\n", content->content); + fprintf(stderr, "Same path used for 'q-parity' and 'content' as '%s'\n", content->content); + exit(EXIT_FAILURE); + } + + if (state->rarity[0] != 0 && pathcmp(state->rarity, content->content) == 0) { + fprintf(stderr, "Same path used for 'r-parity' and 'content' as '%s'\n", content->content); exit(EXIT_FAILURE); } } @@ -138,7 +155,15 @@ static void state_config_check(struct snapraid_state* state, const char* path) } if (state->qarity[0] != 0 && disk->device == state->qarity_device) { - fprintf(stderr, "Disk '%s' and parity '%s' are on the same device.\n", disk->dir, state->qarity); + fprintf(stderr, "Disk '%s' and q-parity '%s' are on the same device.\n", disk->dir, state->qarity); +#ifdef _WIN32 + fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", disk->device); +#endif + exit(EXIT_FAILURE); + } + + if (state->rarity[0] != 0 && disk->device == state->rarity_device) { + fprintf(stderr, "Disk '%s' and r-parity '%s' are on the same device.\n", disk->dir, state->rarity); #ifdef _WIN32 fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", disk->device); #endif @@ -179,6 +204,14 @@ static void state_config_check(struct snapraid_state* state, const char* path) exit(EXIT_FAILURE); } + if (state->rarity[0] != 0 && state->rarity_device == 0) { + fprintf(stderr, "Disk '%s' has a zero serial number.\n", state->rarity); + fprintf(stderr, "This is not necessarely wrong, but for using SnapRAID\n"); + fprintf(stderr, "it's better to change the serial number of the disk.\n"); + fprintf(stderr, "Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + exit(EXIT_FAILURE); + } + if (state->pool[0] != 0 && state->pool_device == 0) { fprintf(stderr, "Disk '%s' has a zero serial number.\n", state->pool); fprintf(stderr, "This is not necessarely wrong, but for using SnapRAID\n"); @@ -196,6 +229,22 @@ static void state_config_check(struct snapraid_state* state, const char* path) exit(EXIT_FAILURE); } + if (state->rarity[0] != 0 && state->parity_device == state->rarity_device) { + fprintf(stderr, "Parity '%s' and '%s' are on the same device.\n", state->parity, state->rarity); +#ifdef _WIN32 + fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->parity_device); +#endif + exit(EXIT_FAILURE); + } + + if (state->qarity[0] != 0 && state->rarity[0] != 0 && state->qarity_device == state->rarity_device) { + fprintf(stderr, "Parity '%s' and '%s' are on the same device.\n", state->qarity, state->rarity); +#ifdef _WIN32 + fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->qarity_device); +#endif + exit(EXIT_FAILURE); + } + if (state->pool[0] != 0 && state->pool_device == state->parity_device) { fprintf(stderr, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity); #ifdef _WIN32 @@ -208,6 +257,14 @@ static void state_config_check(struct snapraid_state* state, const char* path) fprintf(stderr, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->qarity); #ifdef _WIN32 fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->pool_device); +#endif + exit(EXIT_FAILURE); + } + + if (state->pool[0] != 0 && state->rarity[0] != 0 && state->pool_device == state->rarity_device) { + fprintf(stderr, "Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->rarity); +#ifdef _WIN32 + fprintf(stderr, "Both have the serial number '%"PRIx64"'.\n", state->pool_device); #endif exit(EXIT_FAILURE); } @@ -357,6 +414,9 @@ void state_config(struct snapraid_state* state, const char* path, const char* co /* set lock file */ pathcpy(state->lockfile, sizeof(state->lockfile), state->parity); pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); + + if (state->level < 1) + state->level = 1; } else if (strcmp(tag, "q-parity") == 0) { char device[PATH_MAX]; char* slash; @@ -395,7 +455,48 @@ void state_config(struct snapraid_state* state, const char* path, const char* co state->qarity_device = st.st_dev; /* we have two level of parity */ - state->level = 2; + if (state->level < 2) + state->level = 2; + } else if (strcmp(tag, "r-parity") == 0) { + char device[PATH_MAX]; + char* slash; + struct stat st; + + if (*state->rarity) { + fprintf(stderr, "Multiple 'r-parity' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + } + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + fprintf(stderr, "Invalid 'r-parity' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + } + + if (!*buffer) { + fprintf(stderr, "Empty 'r-parity' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + } + + pathimport(state->rarity, sizeof(state->rarity), buffer); + + /* get the device of the directory containing the qparity file */ + pathimport(device, sizeof(device), buffer); + slash = strrchr(device, '/'); + if (slash) + *slash = 0; + else + pathcpy(device, sizeof(device), "."); + if (stat(device, &st) != 0) { + fprintf(stderr, "Error accessing 'rarity' dir '%s' specification in '%s' at line %u\n", device, path, line); + exit(EXIT_FAILURE); + } + + state->rarity_device = st.st_dev; + + /* we have three level of parity */ + if (state->level < 3) + state->level = 3; } else if (strcmp(tag, "pool") == 0) { struct stat st; @@ -651,13 +752,17 @@ void state_config(struct snapraid_state* state, const char* path, const char* co struct snapraid_disk* disk = i->data; fprintf(stdlog, "disk:%s:%s\n", disk->name, disk->dir); } - if (state->qarity[0] != 0) + if (state->rarity[0] != 0) + fprintf(stdlog, "mode:raidTP\n"); + else if (state->qarity[0] != 0) fprintf(stdlog, "mode:raid6\n"); else fprintf(stdlog, "mode:raid5\n"); fprintf(stdlog, "parity:%s\n", state->parity); if (state->qarity[0] != 0) fprintf(stdlog, "qarity:%s\n", state->qarity); + if (state->rarity[0] != 0) + fprintf(stdlog, "rarity:%s\n", state->rarity); if (state->pool[0] != 0) fprintf(stdlog, "pool:%s\n", state->pool); fflush(stdlog); diff --git a/state.h b/state.h index 802ee6cc..61bc5b85 100644 --- a/state.h +++ b/state.h @@ -70,6 +70,8 @@ struct snapraid_state { uint64_t parity_device; /**< Device identifier of the parity. */ char qarity[PATH_MAX]; /**< Path of the qarity file. */ uint64_t qarity_device; /**< Device identifier of the qarity. */ + char rarity[PATH_MAX]; /**< Path of the qarity file. */ + uint64_t rarity_device; /**< Device identifier of the rarity. */ char pool[PATH_MAX]; /**< Path of the pool tree. */ uint64_t pool_device; /**< Device identifier of the pool. */ unsigned char hashseed[HASH_SIZE]; /**< Hash seed. Just after a uint64 to provide a minimal alignment. */ diff --git a/sync.c b/sync.c index d47b08f2..1c59ef0a 100644 --- a/sync.c +++ b/sync.c @@ -35,7 +35,7 @@ struct snapraid_rehash { struct snapraid_block* block; }; -static int state_sync_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, block_off_t blockstart, block_off_t blockmax) +static int state_sync_process(struct snapraid_state* state, struct snapraid_parity* parity, struct snapraid_parity* qarity, struct snapraid_parity* rarity, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; void* rehandle_alloc; @@ -320,6 +320,17 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari } } + /* write the rarity */ + if (state->level >= 3) { + ret = parity_write(rarity, i, buffer[diskmax+2], state->block_size); + if (ret == -1) { + fprintf(stderr, "DANGER! Write error in the R-Parity disk, it isn't possible to sync.\n"); + printf("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + } + } + /* for each disk, mark the blocks as processed */ for(j=0;jlevel >= 3) { + rarity_ptr = &rarity; + ret = parity_create(rarity_ptr, state->rarity, &out_size, state->opt.skip_sequential); + if (ret == -1) { + fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to sync.\n"); + exit(EXIT_FAILURE); + } + + /* if the file is too small */ + if (out_size < loaded_size) { + fprintf(stderr, "DANGER! The R-Parity file %s is smaller than the expected %" PRId64 ".\n", state->rarity, loaded_size); + exit(EXIT_FAILURE); + } + + ret = parity_chsize(rarity_ptr, size, &out_size, state->opt.skip_fallocate); + if (ret == -1) { + parity_overflow(state, out_size); + fprintf(stderr, "WARNING! Without an accessible R-Parity file, it isn't possible to sync.\n"); + exit(EXIT_FAILURE); + } + } else { + rarity_ptr = 0; + } + printf("Syncing...\n"); unrecoverable_error = 0; /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { - ret = state_sync_process(state, parity_ptr, qarity_ptr, blockstart, blockmax); + ret = state_sync_process(state, parity_ptr, qarity_ptr, rarity_ptr, blockstart, blockmax); if (ret == -1) { ++unrecoverable_error; /* continue, as we are already exiting */ @@ -527,6 +564,22 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t } } + if (state->level >= 3) { + ret = parity_sync(rarity_ptr); + if (ret == -1) { + fprintf(stderr, "DANGER! Unexpected sync error in R-Parity disk.\n"); + ++unrecoverable_error; + /* continue, as we are already exiting */ + } + + ret = parity_close(rarity_ptr); + if (ret == -1) { + fprintf(stderr, "DANGER! Unexpected close error in R-Parity disk.\n"); + ++unrecoverable_error; + /* continue, as we are already exiting */ + } + } + /* abort if required */ if (unrecoverable_error != 0) return -1; diff --git a/test-raid5.conf b/test-raid5.conf index 66846405..23bc1f43 100644 --- a/test-raid5.conf +++ b/test-raid5.conf @@ -2,10 +2,12 @@ block_size 1 parity test/parity content test/content content test/p-content -disk disk1 test/disk1/ -disk disk2 test/disk2/ -disk disk3 test/disk3/ +disk disk1 test/disk1/ +disk disk2 test/disk2/ +disk disk3 test/disk3/ +disk disk4 test/disk4/ include *.hidden exclude *.unrecoverable pool test/pool -autosave 1 + + diff --git a/test-raid6.conf b/test-raid6.conf index ae1bc24d..83d18344 100644 --- a/test-raid6.conf +++ b/test-raid6.conf @@ -1,12 +1,13 @@ -block_size 1 -parity test/parity -q-parity test/q-parity -content test/content -content test/p-content -content test/q-content -disk disk1 test/disk1/ -disk disk2 test/disk2/ -disk disk3 test/disk3/ +block_size 1 +parity test/parity +q-parity test/q-parity +content test/content +content test/p-content +content test/q-content +disk disk1 test/disk1/ +disk disk2 test/disk2/ +disk disk3 test/disk3/ +disk disk4 test/disk4/ include *.hidden -exclude *.unrecoverable -autosave 1 +exclude *.unrecoverable + diff --git a/test-raid6-hole.conf b/test-raidTP-hole.conf similarity index 68% rename from test-raid6-hole.conf rename to test-raidTP-hole.conf index 03142c67..ffb0bab2 100644 --- a/test-raid6-hole.conf +++ b/test-raidTP-hole.conf @@ -1,9 +1,14 @@ block_size 1 parity test/parity q-parity test/q-parity +r-parity test/r-parity content test/content content test/p-content content test/q-content +content test/r-content disk disk1 test/disk1/ disk disk3 test/disk3/ +disk disk4 test/disk4/ +include *.hidden exclude *.unrecoverable + diff --git a/test-raidTP.conf b/test-raidTP.conf new file mode 100644 index 00000000..945d7134 --- /dev/null +++ b/test-raidTP.conf @@ -0,0 +1,15 @@ +block_size 1 +parity test/parity +q-parity test/q-parity +r-parity test/r-parity +content test/content +content test/p-content +content test/q-content +content test/r-content +disk disk1 test/disk1/ +disk disk2 test/disk2/ +disk disk3 test/disk3/ +disk disk4 test/disk4/ +include *.hidden +exclude *.unrecoverable +