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
|
/* 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.
|
* 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];
|
uint8_t data[32];
|
||||||
struct flash_dev *dev = map->dev;
|
struct flash_dev *dev = map->dev;
|
||||||
|
@ -37,6 +42,13 @@ static int is_group_erased(struct ftl_map *map, uint32_t group)
|
||||||
return 1;
|
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
|
/* 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
|
* next user page by incrementing the page number. However, if incrementing the
|
||||||
* page number results in the page number of a page containing page
|
* 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
|
* 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.
|
* 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 *where, uint32_t block)
|
||||||
{
|
{
|
||||||
uint32_t page;
|
uint32_t page;
|
||||||
|
@ -240,43 +257,46 @@ static int find_block(struct ftl_map *map, struct ftl_page_group *group,
|
||||||
return -1;
|
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
|
/* Given the block number of the first block, attempts to use binary search to
|
||||||
* find the last block that is in use.
|
* 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;
|
struct ftl_page_group group;
|
||||||
uint32_t mid, low = first, high = map->nblocks - 1;
|
uint32_t mid, low = first, high = map->nblocks - 1;
|
||||||
uint32_t found, next;
|
uint32_t found, next;
|
||||||
|
|
||||||
while (low <= high) {
|
while (low < high) {
|
||||||
mid = (low + high) / 2;
|
mid = (low + high) / 2;
|
||||||
|
|
||||||
if (find_block(map, &group, &found, mid) < 0 ||
|
if (find_block(map, &group, &found, mid) < 0 ||
|
||||||
group.epoch != map->epoch) {
|
group.epoch != map->epoch) {
|
||||||
if (!mid)
|
|
||||||
return first;
|
|
||||||
|
|
||||||
high = mid - 1;
|
high = mid - 1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((found + 1) > map->nblocks) ||
|
if (find_block(map, &group, &next, found + 1) < 0 ||
|
||||||
find_block(map, &group, &next, found + 1) < 0 ||
|
|
||||||
group.epoch != map->epoch)
|
group.epoch != map->epoch)
|
||||||
return found;
|
return found;
|
||||||
|
|
||||||
low = next;
|
low = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return first;
|
return low;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempts to find the last page group that is in use within a block by
|
/* Attempts to find the last page group that is in use within a block by
|
||||||
* performing a binary search on the page groups.
|
* 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 ngroups = UINT32_C(1) << map->log2_groups_per_block;
|
||||||
uint32_t mid, low = 0, high = ngroups - 1;
|
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;
|
low += block << map->log2_groups_per_block;
|
||||||
high += block << map->log2_groups_per_block;
|
high += block << map->log2_groups_per_block;
|
||||||
|
|
||||||
while (low <= high) {
|
while (low < high) {
|
||||||
mid = (low + high) / 2;
|
mid = (low + high) / 2;
|
||||||
|
|
||||||
if (is_group_erased(map, mid)) {
|
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;
|
low = mid + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return block << map->log2_groups_per_block;
|
return low;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_root(struct ftl_map *map, uint32_t group)
|
static int find_root(struct ftl_map *map, uint32_t group)
|
||||||
|
|
Loading…
Add table
Reference in a new issue