diff --git a/Makefile.am b/Makefile.am index b6247d45..1398f90b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -310,6 +310,8 @@ endif $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check --test-expect-recoverable $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub + echo --- Full sync forced + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -F sync echo --- Abort sync with additions. Delete some of them, and add others and sync again. echo --- This triggers files reallocation inside parity mkdir bench/disk1/c diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index b5273a81..fdb54606 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -65,6 +65,7 @@ void usage(void) printf(" " SWITCH_GETOPT_LONG("-U, --force-uuid ", "-U") " Force commands on disks with uuid changed\n"); printf(" " SWITCH_GETOPT_LONG("-D, --force-device ", "-D") " Force commands on disks with same device id\n"); printf(" " SWITCH_GETOPT_LONG("-N, --force-nocopy ", "-N") " Force commands disabling the copy detection\n"); + printf(" " SWITCH_GETOPT_LONG("-F, --force-full ", "-F") " Force commands requiring a full sync\n"); printf(" " SWITCH_GETOPT_LONG("-s, --start BLKSTART ", "-s") " Start from the specified block number\n"); printf(" " SWITCH_GETOPT_LONG("-t, --count BLKCOUNT ", "-t") " Count of block to process\n"); printf(" " SWITCH_GETOPT_LONG("-v, --verbose ", "-v") " Verbose\n"); @@ -251,6 +252,7 @@ struct option long_options[] = { { "force-uuid", 0, 0, 'U' }, { "force-device", 0, 0, 'D' }, { "force-nocopy", 0, 0, 'N' }, + { "force-full", 0, 0, 'F' }, { "audit-only", 0, 0, 'a' }, { "pre-hash", 0, 0, 'h' }, { "speed-test", 0, 0, 'T' }, @@ -330,7 +332,7 @@ struct option long_options[] = { }; #endif -#define OPTIONS "c:f:d:mep:o:s:t:i:l:ZEUDNahTC:vqHVG" +#define OPTIONS "c:f:d:mep:o:s:t:i:l:ZEUDNFahTC:vqHVG" volatile int global_interrupt = 0; @@ -516,6 +518,9 @@ int main(int argc, char* argv[]) case 'N' : opt.force_nocopy = 1; break; + case 'F' : + opt.force_full = 1; + break; case 'a' : opt.auditonly = 1; break; @@ -693,6 +698,34 @@ int main(int argc, char* argv[]) exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } + + if (opt.force_nocopy) { + /* LCOV_EXCL_START */ + fprintf(stderr, "You cannot use -N, --force-nocopy with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (opt.force_full) { + /* LCOV_EXCL_START */ + fprintf(stderr, "You cannot use -G, --force-full with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + if (opt.force_full && opt.force_nocopy) { + /* LCOV_EXCL_START */ + fprintf(stderr, "You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (opt.prehash && opt.force_nocopy) { + /* LCOV_EXCL_START */ + fprintf(stderr, "You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ } switch (operation) { diff --git a/cmdline/state.c b/cmdline/state.c index e2dbff26..23447626 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -1363,6 +1363,15 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE block_state_set(block, BLOCK_STATE_CHG); } + /* if we want a full sync, marks block as invalid parity */ + /* note that we do this after the force_nocopy option */ + /* to avoid to mixup the two things */ + if (state->opt.force_full + && block_state_get(block) == BLOCK_STATE_BLK) { + /* convert from BLK to REP */ + block_state_set(block, BLOCK_STATE_REP); + } + /* we must not overwrite existing blocks */ if (disk_block_get(disk, v_pos) != BLOCK_EMPTY) { /* LCOV_EXCL_START */ @@ -2861,6 +2870,15 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST block_state_set(block, BLOCK_STATE_CHG); } + /* if we want a full sync, marks block as invalid parity */ + /* note that we do this after the force_nocopy option */ + /* to avoid to mixup the two things */ + if (state->opt.force_full + && block_state_get(block) == BLOCK_STATE_BLK) { + /* convert from BLK to REP */ + block_state_set(block, BLOCK_STATE_REP); + } + /* we must not overwrite existing blocks */ if (disk_block_get(disk, v_pos) != BLOCK_EMPTY) { /* LCOV_EXCL_START */ diff --git a/cmdline/state.h b/cmdline/state.h index 2ad6bb91..6ef557ab 100644 --- a/cmdline/state.h +++ b/cmdline/state.h @@ -66,6 +66,7 @@ struct snapraid_option { int force_uuid; /**< Forced dangerous operations of synching disks with uuid changed. */ int force_device; /**< Forced dangerous operations of using disks with save device id. */ int force_nocopy; /**< Force dangerous operations of synching files without using copy detection. */ + int force_full; /**< Force a full sync when using an old content file. */ int expect_unrecoverable; /**< Expect presence of unrecoverable error in checking or fixing. */ int expect_recoverable; /**< Expect presence of recoverable error in checking. */ int skip_device; /**< Skip devices matching checks. */ diff --git a/cmdline/sync.c b/cmdline/sync.c index bfea61b0..b4545c40 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -1017,12 +1017,18 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t /* LCOV_EXCL_STOP */ } - /* if the file is too small */ - if (out_size < loaded_size) { - /* LCOV_EXCL_START */ - fprintf(stderr, "DANGER! The %s file %s is smaller than the expected %" PRId64 ".\n", lev_name(l), state->parity_path[l], loaded_size); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ + /* if we do a full sync, having a wrong parity size is expected */ + if (!state->opt.force_full) { + /* if the file is too small */ + if (out_size < loaded_size) { + /* LCOV_EXCL_START */ + fprintf(stderr, "DANGER! The %s file %s is smaller than the expected %" PRId64 ".\n", lev_name(l), state->parity_path[l], loaded_size); + fprintf(stderr, "If this happens because you are using an old content file,\n"); + fprintf(stderr, "you can 'sync' anyway using 'snapraid --force-full sync'\n"); + fprintf(stderr, "to force a full rebuild of the parity.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } } /* change the size of the parity file, truncating or extending it */ diff --git a/snapraid.1 b/snapraid.1 index 94459f15..ce8fd7af 100644 --- a/snapraid.1 +++ b/snapraid.1 @@ -30,7 +30,7 @@ snapraid [\-c, \-\-conf CONFIG] .PD 0 .PP .PD - [\-N, \-\-force\-nocopy] + [\-N, \-\-force\-nocopy] [\-F, \-\-force\-full] .PD 0 .PP .PD @@ -819,6 +819,7 @@ it stops proceeding, because it\'s not a supported configuration. But it could happen that you want to temporarily restore a lost disk in the free space left in an already used disk. and this option allows you to continue anyway. +This option can be used only with the \[dq]fix\[dq] command. .TP .B \-N, \-\-force\-nocopy In the \[dq]sync\[dq] command, disables the copy detection heuristic. @@ -830,6 +831,18 @@ and to reuse the already computed hash information to detect silent errors in the copy. This behavior, in some rare cases, may result in false positives, and this option allow to resolve them. +This option can be used only with the \[dq]sync\[dq] command. +.TP +.B \-F, \-\-force\-full +In the \[dq]sync\[dq] command, forces a full rebuild of the parity. +This option can be used when you reverted back to an old content +file, because you have lost the most recent one, and you still have +the parity data. +Instead of recomputing the parity from scratch, this allows +to reuse the hashes present in the content file to validate data, +and to maintain data protection using the old content file and the +parity data you have. +This option can be used only with the \[dq]sync\[dq] command. .TP .B \-l, \-\-log FILE Write a detailed log of errors found in check and fix. diff --git a/snapraid.d b/snapraid.d index a6edfa5e..77ac2904 100644 --- a/snapraid.d +++ b/snapraid.d @@ -9,7 +9,7 @@ Synopsis : [-p, --percentage PERC] [-o, --older-than DAYS] : [-Z, --force-zero] [-E, --force-empty] : [-U, --force-uuid] [-D, --force-device] - : [-N, --force-nocopy] + : [-N, --force-nocopy] [-F, --force-full] : [-v, --verbose] [-l, --log FILE] : [-s, --start BLKSTART] [-t, --count BLKCOUNT] : status|sync|scrub|fix|check|list|diff|dup|pool|rehash @@ -582,6 +582,7 @@ Options But it could happen that you want to temporarily restore a lost disk in the free space left in an already used disk. and this option allows you to continue anyway. + This option can be used only with the "fix" command. -N, --force-nocopy In the "sync" command, disables the copy detection heuristic. @@ -593,6 +594,18 @@ Options silent errors in the copy. This behavior, in some rare cases, may result in false positives, and this option allow to resolve them. + This option can be used only with the "sync" command. + + -F, --force-full + In the "sync" command, forces a full rebuild of the parity. + This option can be used when you reverted back to an old content + file, because you have lost the most recent one, and you still have + the parity data. + Instead of recomputing the parity from scratch, this allows + to reuse the hashes present in the content file to validate data, + and to maintain data protection using the old content file and the + parity data you have. + This option can be used only with the "sync" command. -l, --log FILE Write a detailed log of errors found in check and fix. diff --git a/snapraid.txt b/snapraid.txt index 69264b8e..4f846050 100644 --- a/snapraid.txt +++ b/snapraid.txt @@ -13,7 +13,7 @@ snapraid [-c, --conf CONFIG] [-p, --percentage PERC] [-o, --older-than DAYS] [-Z, --force-zero] [-E, --force-empty] [-U, --force-uuid] [-D, --force-device] - [-N, --force-nocopy] + [-N, --force-nocopy] [-F, --force-full] [-v, --verbose] [-l, --log FILE] [-s, --start BLKSTART] [-t, --count BLKCOUNT] status|sync|scrub|fix|check|list|diff|dup|pool|rehash @@ -627,6 +627,7 @@ SnapRAID provides the following options: But it could happen that you want to temporarily restore a lost disk in the free space left in an already used disk. and this option allows you to continue anyway. + This option can be used only with the "fix" command. -N, --force-nocopy In the "sync" command, disables the copy detection heuristic. @@ -638,6 +639,18 @@ SnapRAID provides the following options: silent errors in the copy. This behavior, in some rare cases, may result in false positives, and this option allow to resolve them. + This option can be used only with the "sync" command. + + -F, --force-full + In the "sync" command, forces a full rebuild of the parity. + This option can be used when you reverted back to an old content + file, because you have lost the most recent one, and you still have + the parity data. + Instead of recomputing the parity from scratch, this allows + to reuse the hashes present in the content file to validate data, + and to maintain data protection using the old content file and the + parity data you have. + This option can be used only with the "sync" command. -l, --log FILE Write a detailed log of errors found in check and fix.