bugfix for kv workspace locate

if only one fresh block left when kv_init, we should not just locate the workspace to this fresh one, otherwise we probably get a KV_ERR_NO_WRITEABLE_BLK in kv_init next time(if we write something to this workspace). We try a gc here to locate workspace to an inuse block rather than the fresh.
This commit is contained in:
daishengdong
2021-09-06 13:06:31 +08:00
parent c13e3d95e4
commit 427b13d14a
2 changed files with 53 additions and 15 deletions

View File

@@ -145,6 +145,20 @@ __STATIC__ uint32_t kv_blk_next_fresh(void)
return KV_BLK_INVALID;
}
__STATIC__ uint32_t kv_blk_get_a_fresh(void)
{
uint32_t cur_blk;
KV_BLK_FOR_EACH(cur_blk) {
if (kv_blk_is_fresh(cur_blk)) {
return cur_blk;
}
}
return KV_BLK_INVALID;
}
__STATIC__ uint32_t kv_blk_search_inuse(uint32_t item_size)
{
uint32_t cur_blk;
@@ -940,6 +954,26 @@ __STATIC__ int kv_mgr_blk_index_rebuild(void)
return is_rebuild_done;
}
__STATIC__ kv_err_t kv_try_gc(void)
{
uint32_t cur_blk, blk_dst;
blk_dst = kv_blk_get_a_fresh();
if (blk_dst == KV_BLK_INVALID) {
return KV_ERR_GC_NOTHING;
}
KV_BLK_FOR_EACH(cur_blk) {
if (kv_blk_is_dirty(cur_blk)) {
if (kv_do_gc(cur_blk, blk_dst, K_FALSE) == KV_ERR_NONE) {
return KV_ERR_NONE;
}
}
}
return KV_ERR_GC_NOTHING;
}
__STATIC__ kv_err_t kv_mgr_workspace_locate(void)
{
uint32_t cur_blk;
@@ -949,6 +983,12 @@ __STATIC__ kv_err_t kv_mgr_workspace_locate(void)
kv_mgr_blk_index_rebuild();
}
if (KV_MGR_BLK_NUM_INUSE == 0 && KV_MGR_BLK_NUM_FRESH == 1) {
/* if here, we cannot just give out the last fresh block, otherwise the kv will get into
KV_ERR_NO_WRITEABLE_BLK next time, try a gc here to get a "rescue" */
kv_try_gc();
}
if (KV_NO_WRITEABLE_BLK()) {
return KV_ERR_NO_WRITEABLE_BLK;
}
@@ -1078,7 +1118,6 @@ __STATIC__ int kv_handle_incomplete_gc(struct blk_info gc_src_blk, struct blk_in
__STATIC__ int kv_mgr_ctl_build(void)
{
kv_err_t err;
uint32_t cur_blk;
kv_blk_hdr_t blk_hdr;
@@ -1176,22 +1215,21 @@ __STATIC__ kv_err_t kv_gc(void)
// there must be at least one fresh block left, make workspace pointer to the fresh one
blk_dst = kv_blk_next_fresh();
if (blk_dst == KV_BLK_INVALID) {
/* kinda a bug here, KV_MGR_BLK_NUM_FRESH == 1 */
return KV_ERR_GC_NOTHING;
}
KV_BLK_FOR_EACH(cur_blk) {
if (kv_blk_is_dirty(cur_blk)) {
if (kv_do_gc(cur_blk, blk_dst, K_FALSE) != KV_ERR_NONE) {
// cannot do gc for this block, give others a try
continue;
if (kv_do_gc(cur_blk, blk_dst, K_FALSE) == KV_ERR_NONE) {
is_gc_done = K_TRUE;
break;
}
is_gc_done = K_TRUE;
break;
}
}
if (is_gc_done) {
// if do nothing, should restore the workspace;
KV_MGR_WORKSPACE = blk_dst;
}