|
|
|
@ -14,7 +14,8 @@ |
|
|
|
|
static int mufs_do_lookup(struct mufs *fs, uint32_t *page, |
|
|
|
|
uint32_t base, uint8_t depth, uint32_t va, unsigned alloc) |
|
|
|
|
{ |
|
|
|
|
char data[1 << fs->dev->log2_block_size]; |
|
|
|
|
struct flash_dev *dev = fs->dev; |
|
|
|
|
char data[1 << dev->log2_block_size]; |
|
|
|
|
uint32_t *table = (uint32_t *)data; |
|
|
|
|
size_t index; |
|
|
|
|
|
|
|
|
@ -26,7 +27,7 @@ static int mufs_do_lookup(struct mufs *fs, uint32_t *page, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (flash_read(fs->dev, base << fs->dev->log2_block_size, data, |
|
|
|
|
if (flash_read(dev, base << dev->log2_block_size, data, |
|
|
|
|
sizeof data) == 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
@ -36,7 +37,7 @@ static int mufs_do_lookup(struct mufs *fs, uint32_t *page, |
|
|
|
|
if (!alloc || mufs_alloc_block(fs, &table[index]) < 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
if (flash_write(fs->dev, base << fs->dev->log2_block_size, data, |
|
|
|
|
if (flash_write(dev, base << dev->log2_block_size, data, |
|
|
|
|
sizeof data) == 0) |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
@ -44,15 +45,17 @@ static int mufs_do_lookup(struct mufs *fs, uint32_t *page, |
|
|
|
|
return mufs_do_lookup(fs, page, table[index], depth - 1, va, alloc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int mufs_lookup_page(struct mufs *fs, struct mufs_tree *tree, uint32_t *page, |
|
|
|
|
int mufs_lookup_page(struct mufs_tree *tree, uint32_t *page, |
|
|
|
|
uint32_t va) |
|
|
|
|
{ |
|
|
|
|
return mufs_do_lookup(fs, page, tree->root, tree->depth, va, 0); |
|
|
|
|
return mufs_do_lookup(tree->fs, page, tree->root, tree->depth, va, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int mufs_alloc_page(struct mufs *fs, struct mufs_tree *tree, uint32_t *page, |
|
|
|
|
int mufs_alloc_page(struct mufs_tree *tree, uint32_t *page, |
|
|
|
|
uint32_t va) |
|
|
|
|
{ |
|
|
|
|
struct mufs *fs = tree->fs; |
|
|
|
|
|
|
|
|
|
if (!tree->root && mufs_alloc_block(fs, &tree->root) < 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
@ -62,6 +65,7 @@ int mufs_alloc_page(struct mufs *fs, struct mufs_tree *tree, uint32_t *page, |
|
|
|
|
static int mufs_do_free_page(struct mufs *fs, uint32_t base, |
|
|
|
|
uint8_t depth, uint32_t va) |
|
|
|
|
{ |
|
|
|
|
struct flash_dev *dev = fs->dev; |
|
|
|
|
char data[1 << fs->dev->log2_block_size]; |
|
|
|
|
uint32_t *table = (uint32_t *)data; |
|
|
|
|
size_t index; |
|
|
|
@ -74,7 +78,7 @@ static int mufs_do_free_page(struct mufs *fs, uint32_t base, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (flash_read(fs->dev, base << fs->dev->log2_block_size, data, |
|
|
|
|
if (flash_read(fs->dev, base << dev->log2_block_size, data, |
|
|
|
|
sizeof data) == 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
@ -89,7 +93,7 @@ static int mufs_do_free_page(struct mufs *fs, uint32_t base, |
|
|
|
|
if (!table[index]) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (flash_write(fs->dev, base << fs->dev->log2_block_size, data, |
|
|
|
|
if (flash_write(dev, base << dev->log2_block_size, data, |
|
|
|
|
sizeof data) == 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
@ -99,13 +103,15 @@ static int mufs_do_free_page(struct mufs *fs, uint32_t base, |
|
|
|
|
return mufs_free_block(fs, base); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void mufs_free_page(struct mufs *fs, struct mufs_tree *tree, uint32_t va) |
|
|
|
|
void mufs_free_page(struct mufs_tree *tree, uint32_t va) |
|
|
|
|
{ |
|
|
|
|
mufs_do_free_page(fs, tree->root, tree->depth, va); |
|
|
|
|
mufs_do_free_page(tree->fs, tree->root, tree->depth, va); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int mufs_extend_tree(struct mufs *fs, struct mufs_tree *tree, uint8_t depth) |
|
|
|
|
int mufs_extend_tree(struct mufs_tree *tree, uint8_t depth) |
|
|
|
|
{ |
|
|
|
|
struct mufs *fs = tree->fs; |
|
|
|
|
struct flash_dev *dev = fs->dev; |
|
|
|
|
uint32_t root; |
|
|
|
|
|
|
|
|
|
for (; tree->depth <= depth; ++tree->depth) { |
|
|
|
@ -115,7 +121,7 @@ int mufs_extend_tree(struct mufs *fs, struct mufs_tree *tree, uint8_t depth) |
|
|
|
|
if (!root) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (flash_write(fs->dev, root << fs->dev->log2_block_size, &tree->root, |
|
|
|
|
if (flash_write(dev, root << dev->log2_block_size, &tree->root, |
|
|
|
|
sizeof tree->root) == 0) { |
|
|
|
|
mufs_free_block(fs, root); |
|
|
|
|
return -1; |
|
|
|
@ -127,9 +133,11 @@ int mufs_extend_tree(struct mufs *fs, struct mufs_tree *tree, uint8_t depth) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int mufs_shrink_tree(struct mufs *fs, struct mufs_tree *tree, uint32_t max_size) |
|
|
|
|
int mufs_shrink_tree(struct mufs_tree *tree, uint32_t max_size) |
|
|
|
|
{ |
|
|
|
|
char data[1 << fs->dev->log2_block_size]; |
|
|
|
|
struct mufs *fs = tree->fs; |
|
|
|
|
struct flash_dev *dev = fs->dev; |
|
|
|
|
char data[1 << dev->log2_block_size]; |
|
|
|
|
uint32_t *table = (uint32_t *)data; |
|
|
|
|
size_t index; |
|
|
|
|
uint32_t base, size; |
|
|
|
@ -138,15 +146,15 @@ int mufs_shrink_tree(struct mufs *fs, struct mufs_tree *tree, uint32_t max_size) |
|
|
|
|
base = tree->root; |
|
|
|
|
|
|
|
|
|
for (depth = tree->depth; depth; --depth) { |
|
|
|
|
size = 1 << (depth * fs->log2_nentries + fs->dev->log2_block_size); |
|
|
|
|
size = 1 << (depth * fs->log2_nentries + dev->log2_block_size); |
|
|
|
|
|
|
|
|
|
if (size < max_size) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
index = max_size >> ((depth - 1) * fs->log2_nentries + |
|
|
|
|
fs->dev->log2_block_size); |
|
|
|
|
dev->log2_block_size); |
|
|
|
|
|
|
|
|
|
if (flash_read(fs->dev, base, data, sizeof data) == 0) |
|
|
|
|
if (flash_read(dev, base, data, sizeof data) == 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
if (index <= 1) { |
|
|
|
@ -162,7 +170,7 @@ int mufs_shrink_tree(struct mufs *fs, struct mufs_tree *tree, uint32_t max_size) |
|
|
|
|
table[index] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (flash_write(fs->dev, base << fs->dev->log2_block_size, data, |
|
|
|
|
if (flash_write(dev, base << dev->log2_block_size, data, |
|
|
|
|
sizeof data) == 0) |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
@ -170,32 +178,32 @@ int mufs_shrink_tree(struct mufs *fs, struct mufs_tree *tree, uint32_t max_size) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static size_t mufs_do_read(struct mufs *fs, struct mufs_tree *tree, |
|
|
|
|
void *data, uint32_t va, size_t len) |
|
|
|
|
static size_t mufs_do_read(struct mufs_tree *tree, void *data, uint32_t va, |
|
|
|
|
size_t len) |
|
|
|
|
{ |
|
|
|
|
struct mufs *fs = tree->fs; |
|
|
|
|
struct flash_dev *dev = fs->dev; |
|
|
|
|
uint32_t page, offset; |
|
|
|
|
|
|
|
|
|
offset = va & ((UINT32_C(1) << fs->dev->log2_block_size) - 1); |
|
|
|
|
va = align(va, fs->dev->log2_block_size); |
|
|
|
|
offset = va & ((UINT32_C(1) << dev->log2_block_size) - 1); |
|
|
|
|
va = align(va, dev->log2_block_size); |
|
|
|
|
|
|
|
|
|
memset(data, 0, len); |
|
|
|
|
len = min(len, (UINT32_C(1) << fs->dev->log2_block_size) - offset); |
|
|
|
|
len = min(len, (UINT32_C(1) << dev->log2_block_size) - offset); |
|
|
|
|
|
|
|
|
|
if (mufs_lookup_page(fs, tree, &page, va) < 0) |
|
|
|
|
if (mufs_lookup_page(tree, &page, va) < 0) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
return flash_read(fs->dev, (page << fs->dev->log2_block_size) + offset, |
|
|
|
|
data, len); |
|
|
|
|
return flash_read(dev, (page << dev->log2_block_size) + offset, data, len); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t mufs_read(struct mufs *fs, struct mufs_tree *tree, void *data, |
|
|
|
|
uint32_t va, size_t len) |
|
|
|
|
size_t mufs_read(struct mufs_tree *tree, void *data, uint32_t va, size_t len) |
|
|
|
|
{ |
|
|
|
|
uint8_t *buf = data; |
|
|
|
|
size_t ret, nbytes = 0; |
|
|
|
|
|
|
|
|
|
while (len) { |
|
|
|
|
if ((ret = mufs_do_read(fs, tree, buf, va, len)) == 0) |
|
|
|
|
if ((ret = mufs_do_read(tree, buf, va, len)) == 0) |
|
|
|
|
return nbytes; |
|
|
|
|
|
|
|
|
|
buf += ret; |
|
|
|
@ -207,33 +215,35 @@ size_t mufs_read(struct mufs *fs, struct mufs_tree *tree, void *data, |
|
|
|
|
return nbytes; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static size_t mufs_do_write(struct mufs *fs, struct mufs_tree *tree, |
|
|
|
|
static size_t mufs_do_write(struct mufs_tree *tree, |
|
|
|
|
void *data, uint32_t va, size_t len) |
|
|
|
|
{ |
|
|
|
|
struct mufs *fs = tree->fs; |
|
|
|
|
struct flash_dev *dev = fs->dev; |
|
|
|
|
uint32_t page, offset; |
|
|
|
|
|
|
|
|
|
offset = va & ((UINT32_C(1) << fs->dev->log2_block_size) - 1); |
|
|
|
|
va = align(va, fs->dev->log2_block_size); |
|
|
|
|
len = min(len, (UINT32_C(1) << fs->dev->log2_block_size) - offset); |
|
|
|
|
offset = va & ((UINT32_C(1) << dev->log2_block_size) - 1); |
|
|
|
|
va = align(va, dev->log2_block_size); |
|
|
|
|
len = min(len, (UINT32_C(1) << dev->log2_block_size) - offset); |
|
|
|
|
|
|
|
|
|
if (mufs_extend_tree(fs, tree, 1) < 0) |
|
|
|
|
if (mufs_extend_tree(tree, 1) < 0) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
if (mufs_alloc_page(fs, tree, &page, va) < 0) |
|
|
|
|
if (mufs_alloc_page(tree, &page, va) < 0) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
return flash_write(fs->dev, (page << fs->dev->log2_block_size) + offset, |
|
|
|
|
data, len); |
|
|
|
|
return flash_write(dev, (page << dev->log2_block_size) + offset, data, |
|
|
|
|
len); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t mufs_write(struct mufs *fs, struct mufs_tree *tree, void *data, |
|
|
|
|
size_t mufs_write(struct mufs_tree *tree, void *data, |
|
|
|
|
uint32_t va, size_t len) |
|
|
|
|
{ |
|
|
|
|
uint8_t *buf = data; |
|
|
|
|
size_t ret, nbytes = 0; |
|
|
|
|
|
|
|
|
|
while (len) { |
|
|
|
|
if ((ret = mufs_do_write(fs, tree, buf, va, len)) == 0) |
|
|
|
|
if ((ret = mufs_do_write(tree, buf, va, len)) == 0) |
|
|
|
|
return nbytes; |
|
|
|
|
|
|
|
|
|
buf += ret; |
|
|
|
|