|
|
|
@ -439,6 +439,12 @@ err_not_found: |
|
|
|
|
static int ftl_write_upage(struct ftl_journal *j, const uint8_t *page, |
|
|
|
|
const struct ftl_page_desc *page_desc); |
|
|
|
|
|
|
|
|
|
/* For a given user page, attempt to claim more free space by checking if no
|
|
|
|
|
* recent mapping has obsoleted the older mapping. If a more recent mapping |
|
|
|
|
* exists, the page can be safely ignored and erased. Otherwise, we preserve |
|
|
|
|
* the page by copying the page to create a new mapping such that the old page |
|
|
|
|
* can be ignored and erased. |
|
|
|
|
*/ |
|
|
|
|
static int free_page(struct ftl_journal *j, uint32_t upage) |
|
|
|
|
{ |
|
|
|
|
struct ftl_page_desc page_desc; |
|
|
|
@ -462,6 +468,10 @@ static int free_page(struct ftl_journal *j, uint32_t upage) |
|
|
|
|
return ftl_write_upage(j, NULL, &page_desc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Claim more free space by checking which user pages in a page group are
|
|
|
|
|
* mapped and for which the mappings have been obsoleted by a more recent |
|
|
|
|
* mapping. The mapped user pages are preserved by copying. |
|
|
|
|
*/ |
|
|
|
|
static int free_group(struct ftl_journal *j, uint32_t group) |
|
|
|
|
{ |
|
|
|
|
uint32_t npages = UINT32_C(1) << j->log2_pages_per_group; |
|
|
|
@ -476,6 +486,10 @@ static int free_group(struct ftl_journal *j, uint32_t group) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Claim more free space by checking which user pages in a block are mapped and
|
|
|
|
|
* for which the mappings have been obsoleted by a more recent mapping. The |
|
|
|
|
* mapped user pages are preserved by copying. |
|
|
|
|
*/ |
|
|
|
|
static int free_block(struct ftl_journal *j, uint32_t block) |
|
|
|
|
{ |
|
|
|
|
uint32_t ngroups = UINT32_C(1) << j->log2_groups_per_block; |
|
|
|
@ -490,6 +504,11 @@ static int free_block(struct ftl_journal *j, uint32_t block) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Checks if there are sufficient pages available for writing. Otherwise this
|
|
|
|
|
* function attempts to claim more free space from unmapped pages for which |
|
|
|
|
* newer pages have obsoleted the mapping. Further, we move the user pages that |
|
|
|
|
* are still mapped as these should be preserved. |
|
|
|
|
*/ |
|
|
|
|
static int free_tail(struct ftl_journal *j) |
|
|
|
|
{ |
|
|
|
|
size_t log2_pages_per_block = j->log2_pages_per_group + |
|
|
|
@ -516,6 +535,11 @@ static int free_tail(struct ftl_journal *j) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Prepare the head for writing. If the user page to be written to is not
|
|
|
|
|
* aligned on a block boundary, the block must already be erased and there is |
|
|
|
|
* nothing to be done. Otherwise, we free the tail if necessary and erase the |
|
|
|
|
* block for writing. |
|
|
|
|
*/ |
|
|
|
|
static int prepare_head(struct ftl_journal *j) |
|
|
|
|
{ |
|
|
|
|
size_t log2_pages_per_block = j->log2_pages_per_group + |
|
|
|
|