ftl: mock is_group_erased() and find_block() and simplify implementation of binary search
This commit is contained in:
parent
8e4dc856e7
commit
bbfb9ca800
1 changed files with 34 additions and 14 deletions
|
@ -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…
Add table
Reference in a new issue