From bbfb9ca8003fd3fe9166947e1dcebc63850a8703 Mon Sep 17 00:00:00 2001 From: "S.J.R. van Schaik" Date: Wed, 20 Sep 2017 14:30:08 +0200 Subject: [PATCH] ftl: mock is_group_erased() and find_block() and simplify implementation of binary search --- source/ftl/map.c | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/source/ftl/map.c b/source/ftl/map.c index 1e39528..609c23e 100644 --- a/source/ftl/map.c +++ b/source/ftl/map.c @@ -12,7 +12,12 @@ /* Given the group number, this function checks if a page group is erased by * checking if the pages that compose the page group are erased. */ -static int is_group_erased(struct ftl_map *map, uint32_t group) +#ifdef is_group_erased +#undef is_group_erased +#define is_group_erased __real_is_group_erased +#endif + +int is_group_erased(struct ftl_map *map, uint32_t group) { uint8_t data[32]; struct flash_dev *dev = map->dev; @@ -37,6 +42,13 @@ static int is_group_erased(struct ftl_map *map, uint32_t group) return 1; } +#ifdef is_group_erased +#undef is_group_erased +#define is_group_erased __wrap_is_group_erased +#endif + +int __wrap_is_group_erased(struct ftl_map *map, uint32_t group); + /* Given the current user page, this function computes the page number of the * next user page by incrementing the page number. However, if incrementing the * page number results in the page number of a page containing page @@ -215,7 +227,12 @@ int find_block_div(struct ftl_map *map) * use, as a block can only be erased as a whole. Therefore, if the first page * group is not in use, neither will the other page groups in a block. */ -static int find_block(struct ftl_map *map, struct ftl_page_group *group, +#ifdef find_block +#undef find_block +#define find_block __real_find_block +#endif + +int find_block(struct ftl_map *map, struct ftl_page_group *group, uint32_t *where, uint32_t block) { uint32_t page; @@ -240,43 +257,46 @@ static int find_block(struct ftl_map *map, struct ftl_page_group *group, return -1; } +#ifdef find_block +#undef find_block +#define find_block __wrap_find_block +#endif + +int find_block(struct ftl_map *map, struct ftl_page_group *group, + uint32_t *where, uint32_t block); + /* Given the block number of the first block, attempts to use binary search to * find the last block that is in use. */ -static uint32_t find_last_block(struct ftl_map *map, uint32_t first) +uint32_t find_last_block(struct ftl_map *map, uint32_t first) { struct ftl_page_group group; uint32_t mid, low = first, high = map->nblocks - 1; uint32_t found, next; - while (low <= high) { + while (low < high) { mid = (low + high) / 2; if (find_block(map, &group, &found, mid) < 0 || group.epoch != map->epoch) { - if (!mid) - return first; - high = mid - 1; - continue; } - if (((found + 1) > map->nblocks) || - find_block(map, &group, &next, found + 1) < 0 || + if (find_block(map, &group, &next, found + 1) < 0 || group.epoch != map->epoch) return found; low = next; } - return first; + return low; } /* Attempts to find the last page group that is in use within a block by * performing a binary search on the page groups. */ -static uint32_t find_last_group(struct ftl_map *map, uint32_t block) +uint32_t find_last_group(struct ftl_map *map, uint32_t block) { uint32_t ngroups = UINT32_C(1) << map->log2_groups_per_block; uint32_t mid, low = 0, high = ngroups - 1; @@ -284,7 +304,7 @@ static uint32_t find_last_group(struct ftl_map *map, uint32_t block) low += block << map->log2_groups_per_block; high += block << map->log2_groups_per_block; - while (low <= high) { + while (low < high) { mid = (low + high) / 2; if (is_group_erased(map, mid)) { @@ -298,7 +318,7 @@ static uint32_t find_last_group(struct ftl_map *map, uint32_t block) low = mid + 1; } - return block << map->log2_groups_per_block; + return low; } static int find_root(struct ftl_map *map, uint32_t group)