diff --git a/components/fs/kv/include/tos_kv.h b/components/fs/kv/include/tos_kv.h index 8d97ea09..0cf8b1cb 100644 --- a/components/fs/kv/include/tos_kv.h +++ b/components/fs/kv/include/tos_kv.h @@ -81,7 +81,7 @@ typedef uint64_t kv_dword_t; // double word #define KV_NO_WRITEABLE_BLK() (KV_MGR_BLK_NUM_INUSE == 0 && KV_MGR_BLK_NUM_FRESH == 0) -#define KV_ITEM_HDR_MAGIC 0xABCD1234DCBA4321 +#define KV_ITEM_HDR_MAGIC 0x69745F6D61676963 /* "it_magic" */ #define KV_ITEM_DISCARDED 0x0F0F0F0F0F0F0F0F #define KV_ITEM_IS_DISCARDED(item_hdr) ((item_hdr)->discarded_flag == KV_ITEM_DISCARDED) #define KV_ITEM_IS_LEGAL(item_hdr) ((item_hdr)->magic == KV_ITEM_HDR_MAGIC) @@ -100,10 +100,10 @@ typedef uint64_t kv_dword_t; // double word #define KV_ITEM_SIZE_OF_BODY(item) KV_ITEM_BODY_SIZE(item->hdr.k_len, item->hdr.v_len) #define KV_ITEM_ADDR_OF_BODY(item) (item->pos + KV_ITEM_HDR_SIZE) -#define KV_BLK_HDR_MAGIC 0x1234ABCD4321DCBA -#define KV_BLK_HDR_GC_SRC 0x5678DCBA8765ABCD -#define KV_BLK_HDR_GC_DST 0x8765ABCD8765DCBA -#define KV_BLK_HDR_GC_DONE 0x4321DCBA1234ABCD +#define KV_BLK_HDR_MAGIC 0x48445F4D41474943 /* "HD_MAGIC" */ +#define KV_BLK_HDR_GC_SRC 0x6D61726B5F737263 /* "mark_src" */ +#define KV_BLK_HDR_GC_DST 0x6D61726B5F647374 /* "mark_dst" */ +#define KV_BLK_HDR_GC_DONE 0x6B67635F646F6E65 /* "kgc_done" */ #define KV_BLK_IS_LEGAL(blk_hdr) ((blk_hdr)->magic == KV_BLK_HDR_MAGIC) @@ -196,7 +196,7 @@ typedef struct kv_item_st { uint8_t *body; /*< item body: key/value buffer */ } kv_item_t; -__STATIC__ kv_ctl_t kv_ctl; +extern kv_ctl_t kv_ctl; __STATIC_INLINE__ void kv_blk_freesz_set(uint32_t blk_start, uint32_t free_size) { diff --git a/components/fs/kv/tos_kv.c b/components/fs/kv/tos_kv.c index b4de95af..2bf362e9 100644 --- a/components/fs/kv/tos_kv.c +++ b/components/fs/kv/tos_kv.c @@ -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; }