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