FTL诊断增强:resume前裸NAND checkpoint扫描+header十六进制转储(定位编程落盘问题)
This commit is contained in:
@@ -56,6 +56,7 @@ static uint8_t s_initialized;
|
||||
|
||||
static int ftl_flush_cache(void);
|
||||
static int ftl_read_page(dhara_sector_t lpn);
|
||||
static void ftl_scan_checks_raw(void);
|
||||
|
||||
/* SPI 原语从 gd5f2gq5ue.h 获取 */
|
||||
|
||||
@@ -205,6 +206,12 @@ DSTATUS disk_initialize(BYTE pdrv) {
|
||||
|
||||
dhara_map_init(&s_map, &s_nand, s_page_buf, 4);
|
||||
|
||||
/* 诊断:resume 前的裸 NAND checkpoint 扫描(复位后地面真值,
|
||||
* 不经 FTL 缓存)——判定上一开机的 checkpoint 页是否真正写入芯片 */
|
||||
DBG_INFO("Pre-resume raw check scan start: blocks=%lu",
|
||||
(unsigned long)s_nand.num_blocks);
|
||||
ftl_scan_checks_raw();
|
||||
|
||||
memset(s_cache_buf, 0, FTL_PAGE_SIZE);
|
||||
s_cached_lpn = (dhara_sector_t)-1; /* -1 表示缓存未加载;LPN 0 合法,不能用 0 作哨兵 */
|
||||
s_cache_dirty = 0;
|
||||
@@ -421,9 +428,34 @@ void nand_ftl_log_state(const char *tag)
|
||||
(unsigned long)dhara_map_size(&s_map));
|
||||
}
|
||||
|
||||
/* 打印某块 checkpoint 页的 16 字节 header(magic/epoch/tail/bb),
|
||||
* 用于区分"未落盘(全FF)"/"编程失败(花)"/"完整" 三种状态 */
|
||||
static void ftl_dump_checkheader(uint32_t blk)
|
||||
{
|
||||
uint8_t hdr[16];
|
||||
|
||||
const uint32_t pg = ftl_phy_page((blk << s_nand.log2_ppb) |
|
||||
((1u << s_map.journal.log2_ppc) - 1u));
|
||||
if (gd5f_page_read(pg) != GD5F_OK) {
|
||||
DBG_INFO("check hdr blk %lu: read fail", (unsigned long)blk);
|
||||
return;
|
||||
}
|
||||
gd5f_read_from_cache(0, hdr, sizeof(hdr));
|
||||
DBG_INFO("check hdr blk %lu: %02X %02X %02X %02X %02X %02X %02X %02X "
|
||||
"%02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
(unsigned long)blk,
|
||||
(unsigned int)hdr[0], (unsigned int)hdr[1], (unsigned int)hdr[2],
|
||||
(unsigned int)hdr[3], (unsigned int)hdr[4], (unsigned int)hdr[5],
|
||||
(unsigned int)hdr[6], (unsigned int)hdr[7],
|
||||
(unsigned int)hdr[8], (unsigned int)hdr[9], (unsigned int)hdr[10],
|
||||
(unsigned int)hdr[11], (unsigned int)hdr[12], (unsigned int)hdr[13],
|
||||
(unsigned int)hdr[14], (unsigned int)hdr[15]);
|
||||
}
|
||||
|
||||
/* 全扫每块首组 checkpoint 页(magic+epoch),打印连续区段分布,
|
||||
* 用于识别 journal 环上的 epoch 分界与空洞 */
|
||||
void nand_ftl_scan_checks(void)
|
||||
* 用于识别 journal 环上的 epoch 分界与空洞。
|
||||
* 裸读(gd5f 页读),不受 FTL 缓存影响 = NAND 真实内容。 */
|
||||
static void ftl_scan_checks_raw(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t buf[8];
|
||||
@@ -434,12 +466,6 @@ void nand_ftl_scan_checks(void)
|
||||
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));
|
||||
@@ -457,6 +483,7 @@ void nand_ftl_scan_checks(void)
|
||||
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);
|
||||
ftl_dump_checkheader(run_start);
|
||||
}
|
||||
run_start = i;
|
||||
run_epoch = ep;
|
||||
@@ -471,6 +498,17 @@ void nand_ftl_scan_checks(void)
|
||||
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);
|
||||
ftl_dump_checkheader(run_start);
|
||||
}
|
||||
DBG_INFO("check scan done: %lu checkpoint blocks", (unsigned long)total);
|
||||
}
|
||||
|
||||
void nand_ftl_scan_checks(void)
|
||||
{
|
||||
if (!s_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
DBG_INFO("check scan start: blocks=%lu", (unsigned long)s_nand.num_blocks);
|
||||
ftl_scan_checks_raw();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user