Preserve recovery state until a full clean sync completes

This commit is contained in:
Andrea Mazzoleni 2026-08-14 01:18:03 +02:00
parent 349c18a0a8
commit f453a72369
6 changed files with 53 additions and 31 deletions

View file

@ -2091,11 +2091,7 @@ bail:
/* without checking, we don't know if they are really recoverable or not */
if (!state->opt.auditonly)
msg_status("%8u unrecoverable errors\n", unrecoverable_error);
if (fix)
msg_status("Everything OK\n");
}
} else {
msg_status("Everything OK\n");
}
if ((soft_error || io_error || silent_error) && !fix) {
@ -2329,6 +2325,9 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
if (process_error != 0)
return -1;
msg_status("Everything OK\n");
return 0;
}

View file

@ -388,8 +388,6 @@ bail:
msg_status("\n");
msg_status("%8u soft errors\n", soft_error);
msg_status("%8u io errors\n", io_error);
} else {
msg_status("Everything OK\n");
}
if (soft_error)
@ -486,6 +484,9 @@ int state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (process_error != 0)
return -1;
msg_status("Everything OK\n");
return 0;
}

View file

@ -682,8 +682,6 @@ end:
msg_status("%8u soft errors\n", soft_error);
msg_status("%8u io errors\n", io_error);
msg_status("%8u data errors\n", silent_error);
} else {
msg_status("Everything OK\n");
}
if (soft_error)
@ -944,6 +942,9 @@ int state_scrub(struct snapraid_state* state, int plan100, int olderthan)
if (process_error != 0)
return -1;
msg_status("Everything OK\n");
return 0;
}

View file

@ -1492,6 +1492,10 @@ int snapraid_main(int argc, char* argv[])
/* check options compatibility */
switch (operation) {
#if HAVE_CHECKER
/*
* Ranged sync is retained only for checker regression scenarios.
* The checker never enables filesystem snapshots.
*/
case OPERATION_SYNC :
#endif
case OPERATION_DRY :
@ -1886,8 +1890,12 @@ int snapraid_main(int argc, char* argv[])
ret = state_sync(&state, blockstart, blockcount);
/* commit the snapshot as stable */
/*
* On an operation error, intentionally leave snapshot mounts available
* so that the user can inspect the filesystem state.
*/
if (ret == 0) {
/* commit the snapshot as stable */
ret = state_snapshot_commit(&state);
state_snapshot_cleanup(&state);
}
@ -1940,6 +1948,10 @@ int snapraid_main(int argc, char* argv[])
ret = state_scrub(&state, plan100, olderthan);
/*
* On an operation error, intentionally leave snapshot mounts available
* so that the user can inspect the filesystem state.
*/
if (ret == 0) {
state_snapshot_cleanup(&state);
}
@ -2076,6 +2088,10 @@ int snapraid_main(int argc, char* argv[])
state_scan(&state);
}
/*
* On an operation error, intentionally leave snapshot mounts available
* so that the user can inspect the filesystem state.
*/
if (ret == 0) {
state_snapshot_cleanup(&state);
}

View file

@ -4946,9 +4946,14 @@ void state_commit(struct snapraid_state* state)
for (i = state->disklist; i != 0; i = i->next) {
struct snapraid_disk* disk = i->data;
/* clear the dealloc list */
tommy_list_foreach(&disk->dealloclist, (tommy_foreach_func*)dealloc_free);
tommy_list_init(&disk->dealloclist);
if (!tommy_list_empty(&disk->dealloclist)) {
/* clear the dealloc list */
tommy_list_foreach(&disk->dealloclist, (tommy_foreach_func*)dealloc_free);
tommy_list_init(&disk->dealloclist);
/* mark the state as needing write */
state->need_write = 1;
}
}
}

View file

@ -286,7 +286,8 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
++countpos;
/* progress */
if (state_progress(state, 0, blockcur, countpos, countmax, countsize)) {
alert = state_progress(state, 0, blockcur, countpos, countmax, countsize);
if (alert != 0) {
/* LCOV_EXCL_START */
*skip_sync = 1; /* avoid to run the next sync due user interruption */
break;
@ -318,6 +319,9 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
/* LCOV_EXCL_STOP */
}
}
if (*skip_sync)
break;
}
end:
@ -334,8 +338,6 @@ end:
msg_status("%8u soft errors\n", soft_error);
msg_status("%8u io errors\n", io_error);
msg_status("%8u data errors\n", silent_error);
} else {
msg_status("Everything OK\n");
}
if (soft_error)
@ -378,7 +380,7 @@ finish:
if (soft_error + io_error + silent_error != 0)
return -1;
if (alert < 0)
if (alert != 0)
return -1;
return 0;
@ -1346,7 +1348,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
++countpos;
/* progress */
if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) {
alert = state_progress(state, &io, blockcur, countpos, countmax, countsize);
if (alert != 0) {
/* LCOV_EXCL_START */
break;
/* LCOV_EXCL_STOP */
@ -1431,19 +1434,11 @@ end:
goto bail;
/* LCOV_EXCL_STOP */
}
/* now the parity is fully written, no need to keep deallocated files */
state_commit(state);
if (state->opt.kill_after_sync) {
log_fatal(EUSER, "WARNING! Killing due --test-kill-after-sync option.\n");
exit(EXIT_SUCCESS);
}
/* save the new state if required */
if ((state->need_write || state->opt.force_content_write))
state_write(state);
state_usage_print(state);
if (soft_error || silent_error || io_error) {
@ -1451,10 +1446,6 @@ end:
msg_status("%8u soft errors\n", soft_error);
msg_status("%8u io errors\n", io_error);
msg_status("%8u data errors\n", silent_error);
} else {
/* print the result only if processed something */
if (countpos != 0)
msg_status("Everything OK\n");
}
if (soft_error)
@ -1525,7 +1516,7 @@ bail:
return -1;
}
if (alert < 0)
if (alert != 0)
return -1;
return 0;
@ -1565,7 +1556,6 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (blockcount != 0 && blockcount < blockmax - blockstart) {
blockmax = blockstart + blockcount;
}
for (l = 0; l < state->level; ++l) {
data_off_t out_size;
block_off_t parityblocks;
@ -1723,6 +1713,16 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (process_error != 0)
return -1;
msg_status("Everything OK\n");
/* only a clean full sync makes all deallocation records obsolete */
state_commit(state);
/* persist progress and error markings only after all parity handles are closed */
if (state->need_write || state->opt.force_content_write)
state_write(state);
return 0;
}