FTL复位丢失修复:journal epoch 锚定最新 checkpoint(根治重格式化循环)+ checkpoint 诊断
This commit is contained in:
@@ -401,3 +401,76 @@ int nand_ftl_format(void) {
|
||||
DBG_INFO("NAND FTL formatted, capacity: %lu pages", dhara_map_capacity(&s_map));
|
||||
return GD5F_OK;
|
||||
}
|
||||
|
||||
/* ======================== 诊断(跨复位日志持久性分析) ======================== */
|
||||
|
||||
/* 打印当前 journal/map 状态(epoch/head/tail/root/容量) */
|
||||
void nand_ftl_log_state(const char *tag)
|
||||
{
|
||||
const struct dhara_journal *j = &s_map.journal;
|
||||
|
||||
if (!s_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
DBG_INFO("FTL state %s: epoch=%u head=%lu tail=%lu root=%lu jsize=%lu map=%lu",
|
||||
tag, (unsigned int)j->epoch,
|
||||
(unsigned long)j->head, (unsigned long)j->tail,
|
||||
(unsigned long)j->root,
|
||||
(unsigned long)dhara_journal_size(j),
|
||||
(unsigned long)dhara_map_size(&s_map));
|
||||
}
|
||||
|
||||
/* 全扫每块首组 checkpoint 页(magic+epoch),打印连续区段分布,
|
||||
* 用于识别 journal 环上的 epoch 分界与空洞 */
|
||||
void nand_ftl_scan_checks(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t buf[8];
|
||||
uint32_t total = 0;
|
||||
uint32_t run_start = 0;
|
||||
uint32_t run_prev = 0;
|
||||
uint32_t run_len = 0;
|
||||
uint8_t run_epoch = 0;
|
||||
uint8_t run_open = 0;
|
||||
|
||||
if (!s_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
DBG_INFO("check scan start: blocks=%lu", (unsigned long)s_nand.num_blocks);
|
||||
|
||||
for (i = 0; i < s_nand.num_blocks; i++) {
|
||||
const uint32_t pg = ftl_phy_page((i << s_nand.log2_ppb) |
|
||||
((1u << s_map.journal.log2_ppc) - 1u));
|
||||
|
||||
if (gd5f_page_read(pg) != GD5F_OK) {
|
||||
continue;
|
||||
}
|
||||
gd5f_read_from_cache(0, buf, sizeof(buf));
|
||||
if (buf[0] == 'D' && buf[1] == 'h' && buf[2] == 'a') {
|
||||
const uint8_t ep = buf[3];
|
||||
|
||||
total++;
|
||||
if (!run_open || (i != run_prev + 1) || (ep != run_epoch)) {
|
||||
if (run_open) {
|
||||
DBG_INFO("check run: blk %lu..%lu epoch=%u (%lu blocks)",
|
||||
(unsigned long)run_start, (unsigned long)run_prev,
|
||||
(unsigned int)run_epoch, (unsigned long)run_len);
|
||||
}
|
||||
run_start = i;
|
||||
run_epoch = ep;
|
||||
run_len = 0;
|
||||
run_open = 1;
|
||||
}
|
||||
run_prev = i;
|
||||
run_len++;
|
||||
}
|
||||
}
|
||||
if (run_open) {
|
||||
DBG_INFO("check run: blk %lu..%lu epoch=%u (%lu blocks)",
|
||||
(unsigned long)run_start, (unsigned long)run_prev,
|
||||
(unsigned int)run_epoch, (unsigned long)run_len);
|
||||
}
|
||||
DBG_INFO("check scan done: %lu checkpoint blocks", (unsigned long)total);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user