|
|
|
@ -41,61 +41,108 @@ size_t ftl_read(struct ftl_map *map, void *data, size_t len, uint32_t va) |
|
|
|
|
len); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t ftl_write(struct ftl_map *map, uint32_t va, const void *udata, |
|
|
|
|
size_t len) |
|
|
|
|
static int ftl_seek(struct ftl_map *map, uint32_t va) |
|
|
|
|
{ |
|
|
|
|
struct ftl_page_desc page_desc; |
|
|
|
|
size_t nbytes; |
|
|
|
|
size_t len; |
|
|
|
|
int ret; |
|
|
|
|
uint32_t offset, page, dst, src; |
|
|
|
|
|
|
|
|
|
if (va >= ftl_get_capacity(map)) |
|
|
|
|
return 0; |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
offset = va & ((1 << map->log2_page_size) - 1); |
|
|
|
|
va >>= map->log2_page_size; |
|
|
|
|
|
|
|
|
|
if ((ret = trace_path(map, &page_desc, &page, va)) < 0 && |
|
|
|
|
ret != -ERR_NOT_FOUND) |
|
|
|
|
return 0; |
|
|
|
|
if ((map->flags & FTL_CACHED_VA) && map->last_va != va && |
|
|
|
|
ftl_sync(map) < 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
if (ret == -ERR_NOT_FOUND) |
|
|
|
|
++map->nused_pages; |
|
|
|
|
if ((ret = trace_path(map, NULL, &page, va)) < 0 && |
|
|
|
|
ret != -ERR_NOT_FOUND) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
page_desc.nused_pages = map->nused_pages; |
|
|
|
|
if (offset < map->offset) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
if (prepare_head(map) < 0) |
|
|
|
|
if (offset == map->offset) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
if (map->offset == 0) { |
|
|
|
|
if (prepare_head(map) < 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
if (ret == -ERR_NOT_FOUND) |
|
|
|
|
++map->nused_pages; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dst = map->head << map->log2_page_size; |
|
|
|
|
src = page << map->log2_page_size; |
|
|
|
|
len = min(len, (1 << map->log2_page_size) - offset); |
|
|
|
|
len = offset - map->offset; |
|
|
|
|
|
|
|
|
|
if (ret == -ERR_NOT_FOUND) |
|
|
|
|
flash_write0(map->dev, dst, offset); |
|
|
|
|
flash_write0(map->dev, dst, len); |
|
|
|
|
else |
|
|
|
|
flash_copy(map->dev, dst, src, offset); |
|
|
|
|
flash_copy(map->dev, dst, src, len); |
|
|
|
|
|
|
|
|
|
src += offset; |
|
|
|
|
dst += offset; |
|
|
|
|
map->offset += len; |
|
|
|
|
|
|
|
|
|
flash_write(map->dev, dst, udata, len); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
src += len; |
|
|
|
|
dst += len; |
|
|
|
|
nbytes = (1 << map->log2_page_size) - len - offset; |
|
|
|
|
size_t ftl_write(struct ftl_map *map, uint32_t va, const void *udata, |
|
|
|
|
size_t len) |
|
|
|
|
{ |
|
|
|
|
uint32_t dst; |
|
|
|
|
|
|
|
|
|
if (ret == -ERR_NOT_FOUND) |
|
|
|
|
flash_write0(map->dev, dst, nbytes); |
|
|
|
|
else |
|
|
|
|
flash_copy(map->dev, dst, src, nbytes); |
|
|
|
|
if (ftl_seek(map, va) < 0) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
if (write_page_desc(map, &page_desc) < 0) |
|
|
|
|
dst = (map->head << map->log2_page_size) + map->offset; |
|
|
|
|
len = min(len, (1 << map->log2_page_size) - map->offset); |
|
|
|
|
|
|
|
|
|
if ((len = flash_write(map->dev, dst, udata, len)) == 0) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
map->offset += len; |
|
|
|
|
map->flags |= FTL_DIRTY; |
|
|
|
|
|
|
|
|
|
return len; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ftl_sync(struct ftl_map *map) |
|
|
|
|
{ |
|
|
|
|
struct ftl_page_desc page_desc; |
|
|
|
|
size_t len; |
|
|
|
|
int ret; |
|
|
|
|
uint32_t page, dst, src; |
|
|
|
|
|
|
|
|
|
if (!(map->flags & FTL_DIRTY)) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
if ((ret = trace_path(map, &page_desc, &page, map->last_va)) < 0 && |
|
|
|
|
ret != -ERR_NOT_FOUND) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
dst = (map->head << map->log2_page_size) + map->offset; |
|
|
|
|
src = (page << map->log2_page_size) + map->offset; |
|
|
|
|
len = (1 << map->log2_page_size) - map->offset; |
|
|
|
|
|
|
|
|
|
if (map->flags & FTL_UNMAPPED) |
|
|
|
|
flash_write0(map->dev, dst, len); |
|
|
|
|
else |
|
|
|
|
flash_copy(map->dev, dst, src, len); |
|
|
|
|
|
|
|
|
|
page_desc.nused_pages = map->nused_pages; |
|
|
|
|
|
|
|
|
|
if (write_page_desc(map, &page_desc) < 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
map->offset = 0; |
|
|
|
|
map->flags &= ~FTL_DIRTY; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ftl_trim(struct ftl_map *map, uint32_t va) |
|
|
|
|
{ |
|
|
|
|
struct ftl_page_desc page_desc, alt_page_desc; |
|
|
|
|