ftl: mock is_group_erased() and find_block() and simplify implementation of binary search

tags/0.1.0
S.J.R. van Schaik 7 years ago
parent 8e4dc856e7
commit bbfb9ca800
  1. 48
      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)

Loading…
Cancel
Save