E-31修复:dhara resume失败按错误分类(仅真空白判新卷),mount失败自检上报+主循环有界重试

This commit is contained in:
2026-09-21 18:38:23 +08:00
parent 83b599a4b4
commit 1d2a53bbc9
3 changed files with 246 additions and 130 deletions
+53 -16
View File
@@ -218,12 +218,20 @@ void dhara_journal_init(struct dhara_journal *j,
/* Find the first checkpoint-containing block. If a block contains any
* checkpoints at all, then it must contain one in the first checkpoint
* location -- otherwise, we would have considered the block eraseable.
*
* Error contract (E-31 fix, 2026-09-21): DHARA_E_TOO_BAD is reported
* only when the scan completed without any I/O error (genuinely blank
* chip -- safe for the caller to start fresh). Any read failure in the
* scan is reported instead as the first such error, so callers can
* distinguish "no checkpoints exist" from "the scan was interrupted by
* I/O trouble" -- treating the latter as blank would wipe a live volume.
*/
static int find_checkblock(struct dhara_journal *j,
dhara_block_t blk, dhara_block_t *where,
dhara_error_t *err)
{
int i;
dhara_error_t io_err = DHARA_E_NONE;
for (i = 0; (blk < j->nand->num_blocks) &&
(i < DHARA_MAX_RETRIES); i++) {
@@ -231,19 +239,27 @@ static int find_checkblock(struct dhara_journal *j,
(blk << j->nand->log2_ppb) |
((1 << j->log2_ppc) - 1);
if (!(dhara_nand_is_bad(j->nand, blk) ||
dhara_nand_read(j->nand, p,
0, 1 << j->nand->log2_page_size,
j->page_buf, err)) &&
hdr_has_magic(j->page_buf)) {
*where = blk;
return 0;
if (dhara_nand_is_bad(j->nand, blk)) {
/* Bad block: no read performed, no I/O error */
} else {
dhara_error_t read_err = DHARA_E_NONE;
if (dhara_nand_read(j->nand, p,
0, 1 << j->nand->log2_page_size,
j->page_buf, &read_err) < 0) {
if (io_err == DHARA_E_NONE)
io_err = read_err;
} else if (hdr_has_magic(j->page_buf)) {
*where = blk;
return 0;
}
}
blk++;
}
dhara_set_error(err, DHARA_E_TOO_BAD);
dhara_set_error(err,
(io_err != DHARA_E_NONE) ? io_err : DHARA_E_TOO_BAD);
return -1;
}
@@ -315,7 +331,11 @@ static dhara_block_t find_last_checkblock_any(struct dhara_journal *j,
}
/* Re-read the first-group checkpoint header of the given block into
* j->page_buf. Returns 0 on success. */
* j->page_buf. Returns 0 on success. A failed read reports the I/O
* error; a successful read that no longer carries the checkpoint magic
* is an inconsistency (the block was verified to hold a checkpoint
* during the scan) and reports DHARA_E_CORRUPT_MAP -- never
* DHARA_E_TOO_BAD, which callers treat as a blank chip (E-31 fix). */
static int read_checkpage(struct dhara_journal *j, dhara_block_t blk,
dhara_error_t *err)
{
@@ -323,10 +343,14 @@ static int read_checkpage(struct dhara_journal *j, dhara_block_t blk,
((1 << j->log2_ppc) - 1);
if (dhara_nand_read(j->nand, p, 0, 1 << j->nand->log2_page_size,
j->page_buf, err) < 0 ||
!hdr_has_magic(j->page_buf))
j->page_buf, err) < 0)
return -1;
if (!hdr_has_magic(j->page_buf)) {
dhara_set_error(err, DHARA_E_CORRUPT_MAP);
return -1;
}
return 0;
}
@@ -437,16 +461,20 @@ static int find_root(struct dhara_journal *j, dhara_page_t start,
{
const dhara_block_t blk = start >> j->nand->log2_ppb;
int i = (start & ((1 << j->nand->log2_ppb) - 1)) >> j->log2_ppc;
dhara_error_t io_err = DHARA_E_NONE;
while (i >= 0) {
const dhara_page_t p = (blk << j->nand->log2_ppb) +
((i + 1) << j->log2_ppc) - 1;
dhara_error_t read_err = DHARA_E_NONE;
if (!dhara_nand_read(j->nand, p,
if (dhara_nand_read(j->nand, p,
0, 1 << j->nand->log2_page_size,
j->page_buf, err) &&
(hdr_has_magic(j->page_buf)) &&
(hdr_get_epoch(j->page_buf) == j->epoch)) {
j->page_buf, &read_err) < 0) {
if (io_err == DHARA_E_NONE)
io_err = read_err;
} else if ((hdr_has_magic(j->page_buf)) &&
(hdr_get_epoch(j->page_buf) == j->epoch)) {
j->root = p - 1;
return 0;
}
@@ -454,7 +482,16 @@ static int find_root(struct dhara_journal *j, dhara_page_t start,
i--;
}
dhara_set_error(err, DHARA_E_TOO_BAD);
/* The checkpoint ring is already established by the time this
* runs (find_checkblock + epoch verification succeeded), so
* "no matching checkpoint" here means the stored checkpoint is
* inconsistent (read flakiness or real corruption): report an
* I/O error if one occurred, else DHARA_E_CORRUPT_MAP -- never
* DHARA_E_TOO_BAD, which callers treat as a blank chip
* (E-31 fix, 2026-09-21).
*/
dhara_set_error(err,
(io_err != DHARA_E_NONE) ? io_err : DHARA_E_CORRUPT_MAP);
return -1;
}