parent
88707097fb
commit
a88a33ef01
@ -0,0 +1,97 @@ |
|||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
|
||||||
|
#include <fs/mufs.h> |
||||||
|
|
||||||
|
#include "block.h" |
||||||
|
#include "tree.h" |
||||||
|
|
||||||
|
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]; |
||||||
|
uint32_t *table = (uint32_t *)data; |
||||||
|
size_t index; |
||||||
|
uint8_t log2_nentries = fs->dev->log2_block_size - ilog2(sizeof(uint32_t)); |
||||||
|
|
||||||
|
if (!base) |
||||||
|
return -1; |
||||||
|
|
||||||
|
if (!depth) { |
||||||
|
*page = base; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
if (flash_read(fs->dev, base << fs->dev->log2_block_size, data, |
||||||
|
sizeof data) == 0) |
||||||
|
return -1; |
||||||
|
|
||||||
|
index = va & ((1 << (log2_nentries * (depth - 1))) - 1); |
||||||
|
|
||||||
|
if (!table[index]) { |
||||||
|
if (!alloc || mufs_alloc_block(fs, &table[index]) < 0) |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
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, |
||||||
|
uint32_t va) |
||||||
|
{ |
||||||
|
return mufs_do_lookup(fs, page, tree->base, tree->depth, va, 0); |
||||||
|
} |
||||||
|
|
||||||
|
int mufs_alloc_page(struct mufs *fs, struct mufs_tree *tree, uint32_t *page, |
||||||
|
uint32_t va) |
||||||
|
{ |
||||||
|
return mufs_do_lookup(fs, page, tree->base, tree->depth, va, 1); |
||||||
|
} |
||||||
|
|
||||||
|
static int mufs_do_free_page(struct mufs *fs, uint32_t base, |
||||||
|
uint8_t depth, uint32_t va) |
||||||
|
{ |
||||||
|
char data[1 << fs->dev->log2_block_size]; |
||||||
|
uint32_t *table = (uint32_t *)data; |
||||||
|
size_t index; |
||||||
|
uint8_t log2_nentries = fs->dev->log2_block_size - ilog2(sizeof(uint32_t)); |
||||||
|
|
||||||
|
if (!base) |
||||||
|
return -1; |
||||||
|
|
||||||
|
if (!depth) { |
||||||
|
mufs_free_block(fs, base); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
if (flash_read(fs->dev, base << fs->dev->log2_block_size, data, |
||||||
|
sizeof data) == 0) |
||||||
|
return -1; |
||||||
|
|
||||||
|
index = va & ((1 << (log2_nentries * (depth - 1))) - 1); |
||||||
|
|
||||||
|
if (mufs_do_free_page(fs, table[index], depth - 1, va) < 0) |
||||||
|
return -1; |
||||||
|
|
||||||
|
table[index] = 0; |
||||||
|
|
||||||
|
for (index = 0; index < (UINT32_C(1) << log2_nentries); ++index) { |
||||||
|
if (!table[index]) |
||||||
|
continue; |
||||||
|
|
||||||
|
if (flash_write(fs->dev, base << fs->dev->log2_block_size, data, |
||||||
|
sizeof data) == 0) |
||||||
|
return -1; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
return mufs_free_block(fs, base); |
||||||
|
} |
||||||
|
|
||||||
|
void mufs_free_page(struct mufs *fs, struct mufs_tree *tree, uint32_t va) |
||||||
|
{ |
||||||
|
mufs_do_free_page(fs, tree->base, tree->depth, va); |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
struct mufs_tree { |
||||||
|
uint32_t base; |
||||||
|
uint8_t depth; |
||||||
|
}; |
||||||
|
|
||||||
|
int mufs_lookup_page(struct mufs *fs, struct mufs_tree *tree, uint32_t *page, |
||||||
|
uint32_t va); |
||||||
|
int mufs_alloc_page(struct mufs *fs, struct mufs_tree *tree, uint32_t *page, |
||||||
|
uint32_t va); |
||||||
|
void mufs_free_page(struct mufs *fs, struct mufs_tree *tree, uint32_t va); |
Loading…
Reference in new issue