diff --git a/source/fs/mufs/block.c b/source/fs/mufs/block.c index 30d896a..0cce7d0 100644 --- a/source/fs/mufs/block.c +++ b/source/fs/mufs/block.c @@ -6,68 +6,82 @@ #include "block.h" -static int mufs_mark_block(struct mufs *fs, uint32_t block, int status) +int mufs_mark_block(struct mufs *fs, uint32_t block, int status) { - char data[1 << fs->dev->log2_block_size]; - uint8_t log2_bits_per_block = fs->dev->log2_block_size + ilog2(8); - size_t index; + struct flash_dev *dev = fs->dev; + uint32_t data; + size_t offset, index; - index = block & ((UINT32_C(1) << log2_bits_per_block) - 1); - block >>= log2_bits_per_block; + if (block >= fs->nblocks) + return -1; - if (flash_read(fs->dev, (1 + block) << fs->dev->log2_block_size, data, - sizeof data) == 0) + offset = align(block >> ilog2(8), ilog2(4)); + index = mask(block, ilog2(8) + ilog2(4)); + + if (flash_read(fs->dev, (1 << dev->log2_block_size) + offset, &data, + sizeof data) ==0) return -1; if (status) { - set_bit(data, index); + data |= 1 << index; } else { - clear_bit(data, index); + data = data & ~(1 << index); } - if (flash_write(fs->dev, (1 + block) << fs->dev->log2_block_size, data, + if (flash_write(fs->dev, (1 << dev->log2_block_size) + offset, &data, sizeof data) == 0) return -1; return 0; } -int mufs_alloc_block(struct mufs *fs, uint32_t *found) +static size_t mufs_next_free_block(struct mufs *fs) { - char data[1 << fs->dev->log2_block_size]; - uint32_t nblocks = fs->nblocks; - uint32_t nbits; - uint32_t block = 0; - size_t index; - uint8_t log2_bits_per_block = fs->dev->log2_block_size + ilog2(8); - size_t nbitmap_size = align_up(fs->nblocks, log2_bits_per_block) >> - log2_bits_per_block; + struct flash_dev *dev = fs->dev; + char data[32]; + size_t nblocks = fs->nblocks; + size_t offset, index, bitlen, len; + + offset = 0; while (nblocks) { - if (flash_read(fs->dev, (1 + block) << fs->dev->log2_block_size, data, - sizeof data) == 0) - return -1; + bitlen = min(BIT_SIZE(data), nblocks); + len = bitlen >> ilog2(8); - nbits = min(nblocks, UINT32_C(1) << log2_bits_per_block); + if (flash_read(fs->dev, (1 << dev->log2_block_size) + offset, data, + len) == 0) + return SIZE_MAX; - if ((index = next_clear_bit(data, nbits)) == SIZE_MAX) { - ++block; - nblocks -= nbits; - continue; - } + if ((index = next_clear_bit(data, bitlen)) != SIZE_MAX) + return (offset >> (ilog2(8) + ilog2(32))) + index; - index += block << log2_bits_per_block; - *found = 1 + nbitmap_size + index; + if (flash_write(fs->dev, (1 << dev->log2_block_size) + offset, data, + len) == 0) + return SIZE_MAX; - return mufs_mark_block(fs, index, 1); + offset += len; + nblocks -= bitlen; } - return -1; + return SIZE_MAX; +} + +int mufs_alloc_block(struct mufs *fs, uint32_t *found) +{ + size_t index; + + if ((index = mufs_next_free_block(fs)) == SIZE_MAX) + return -1; + + *found = index; + + return mufs_mark_block(fs, index, 1); } int mufs_free_block(struct mufs *fs, uint32_t block) { - uint8_t log2_bits_per_block = fs->dev->log2_block_size + ilog2(8); + struct flash_dev *dev = fs->dev; + uint8_t log2_bits_per_block = dev->log2_block_size + ilog2(8); size_t nbitmap_size = align_up(fs->nblocks, log2_bits_per_block) >> log2_bits_per_block; @@ -76,5 +90,5 @@ int mufs_free_block(struct mufs *fs, uint32_t block) flash_erase(fs->dev, block, 1); - return mufs_mark_block(fs, block - 1 - nbitmap_size, 0); + return mufs_mark_block(fs, block, 0); } diff --git a/source/fs/mufs/block.h b/source/fs/mufs/block.h index fc9f2b4..a3c1355 100644 --- a/source/fs/mufs/block.h +++ b/source/fs/mufs/block.h @@ -1,4 +1,5 @@ #pragma once +int mufs_mark_block(struct mufs *fs, uint32_t block, int status); int mufs_alloc_block(struct mufs *fs, uint32_t *block); int mufs_free_block(struct mufs *fs, uint32_t block);