Clarify CHG block handling during interrupted sync recovery

This commit is contained in:
Andrea Mazzoleni 2026-08-17 21:57:02 +02:00
parent b959f0056e
commit 65e6564e13
2 changed files with 18 additions and 2 deletions

View file

@ -1298,8 +1298,19 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
*/
if (block_state == BLOCK_STATE_CHG) {
/*
* We DO NOT mark them as bad to avoid to overwrite them with wrong data.
* if we don't have a hash, we always assume the first read of the block correct.
* A CHG block has no hash for the current data. The stored hash
* refers to the previous content, and after an interrupted sync
* parity may refer either to the old or to the new content.
*
* If the block is readable, preserve it and assume it is the best
* available copy of the current data. We must not try to validate it
* against block->hash, as a match would only identify the old data
* and a mismatch would not prove that the current data is correct.
*
* This also intentionally applies to data reused from a previous
* multistep fix through an .unrecoverable file: already readable CHG
* data is preserved, while fix attempts to recover only missing or
* unreadable blocks.
*/
failed[failed_count].is_bad = 0; /* we assume the CHG block correct */
failed[failed_count].is_outofdate = 0;

View file

@ -61,6 +61,11 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in
/* check if exists a .unrecoverable copy, and rename to the real one */
pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path);
/*
* Reuse a previous partial recovery as the starting point for a
* multistep fix. Readable CHG blocks in this file are intentionally
* preserved because their current hash is not available.
*/
if (rename(path_from, handle->path) == 0) {
/* open for read write */
handle->f = open(handle->path, flags | O_RDWR);