FlashDB
FlashDB copied to clipboard
tsdb绕回写入时异常掉电,可能导致整个分区异常
测试发现在tsdb写入时如果有异常掉电,重新上电可能导致分区异常,log如下: Sector (0x00000000) header info is incorrect. All sector format finished.
review代码,疑似问题点如下: 如果使能绕回,在update_sec_status()函数中,有format_sector(db, new_sec_addr)调用,绕回时new_sec_addr为0。 如果在format_sector时候掉电,可能sector header还没写入,下次上电sector 0检查失败,就直接调用tsl_format_all(),把分区全擦除了。
这么分析确实有可能的,此时分区要么非常干净都是 0xFF ,要么扇区头部信息写入一半
你有啥建议吗
这种情况,如果sector 0信息丢失,是不是也是可以恢复到绕回之前的状态? 如果可以的话,那么改下上电检查的判断,如果sector 0出问题,再继续检查一下sector 1,sector 1正常的话是不是就不用全擦了?
嗯,可否增加一个逻辑,如果只有当前这一个 sector 的 header 是坏的,那么就只把当前的删除格式化,其他还能继续用
我初步研究了一下tsdb初始化流程,不知道如下修改方式是否可行:
- 检查每个sector的interator中,如果检查失败,就format_sector()格式化,按照empty处理,继续iterator sector
- 由于步骤1中的iterator中已经做了format,原先的check_sec_arg.check_failed检查然后tsl_format_all()的逻辑,就不再需要了
可以的
-
arg->check_failed
从 bool 改为记录错误扇区的数量及地址 - 迭代完后
- 如果错误数量等于1并且没有找到正在使用的扇区,则格式化这个扇区并指定为正在使用扇区
- 如果错误数量大于1,恐怕不能修复了,则只能全部格式化了
我的意思是,迭代时把header检查失败的sector,做一次format,然后走empty的分支,就不会有check_failed的情况
static bool check_sec_hdr_cb(tsdb_sec_info_t sector, void *arg1, void *arg2)
{
struct check_sec_hdr_cb_args *arg = arg1;
fdb_tsdb_t db = arg->db;
if (!sector->check_ok) {
FDB_INFO("Sector (0x%08" PRIu32 ") header info is incorrect.\n", sector->addr);
format_sector(db, sector->addr);
sector->check_ok = true;
sector->status = FDB_SECTOR_STORE_EMPTY;
// is it necessary to call read_sector_info() ???
}
if (sector->status == FDB_SECTOR_STORE_USING) {
if (db->cur_sec.addr == FDB_DATA_UNUSED) {
memcpy(&db->cur_sec, sector, sizeof(struct tsdb_sec_info));
} else {
FDB_INFO("Warning: Sector status is wrong, there are multiple sectors in use.\n");
(arg->check_failed) = true;
return true;
}
} else if (sector->status == FDB_SECTOR_STORE_EMPTY) {
(arg->empty_num) += 1;
arg->empty_addr = sector->addr;
if ((arg->empty_num) == 1 && db->cur_sec.addr == FDB_DATA_UNUSED) {
memcpy(&db->cur_sec, sector, sizeof(struct tsdb_sec_info));
}
}
return false;
}
好的,你可以先验证一下