Removed clamping to block size in ctz linked-list
Initially, I was concerned that the number of pointers in the ctz linked-list could exceed the storage in a block. Long story short this isn't really possible outside of extremely small block sizes. Since clamping impacts the layout of files on disk, removing the block size removed quite a bit of logic and corner cases. Replaced with an assert on block size during initialization. --- Long story long, the minimum block size needed to store all ctz pointers in a filesystem can be found with this formula: B = (w/8)*log2(2^w / (B - 2*(w/8))) where: B = block size in bytes w = pointer width in bits It's not a very pretty formula, but does give us some useful info if we apply some math: min block size: 32 bit ctz linked-list = 104 bytes 64 bit ctz linked-list = 448 bytes For littlefs, 128 bytes is a perfectly reasonable minimum block size.
This commit is contained in:
@@ -1005,12 +1005,11 @@ int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
/// File index list operations ///
|
||||
static int lfs_index(lfs_t *lfs, lfs_off_t *off) {
|
||||
lfs_off_t i = 0;
|
||||
lfs_size_t words = lfs->cfg->block_size / 4;
|
||||
|
||||
while (*off >= lfs->cfg->block_size) {
|
||||
i += 1;
|
||||
*off -= lfs->cfg->block_size;
|
||||
*off += 4*lfs_min(lfs_ctz(i)+1, words-1);
|
||||
*off += 4*(lfs_ctz(i) + 1);
|
||||
}
|
||||
|
||||
return i;
|
||||
@@ -1028,12 +1027,11 @@ static int lfs_index_find(lfs_t *lfs,
|
||||
|
||||
lfs_off_t current = lfs_index(lfs, &(lfs_off_t){size-1});
|
||||
lfs_off_t target = lfs_index(lfs, &pos);
|
||||
lfs_size_t words = lfs->cfg->block_size / 4;
|
||||
|
||||
while (current > target) {
|
||||
lfs_size_t skip = lfs_min(
|
||||
lfs_npw2(current-target+1) - 1,
|
||||
lfs_min(lfs_ctz(current)+1, words-1) - 1);
|
||||
lfs_ctz(current));
|
||||
|
||||
int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4);
|
||||
if (err) {
|
||||
@@ -1102,8 +1100,7 @@ static int lfs_index_extend(lfs_t *lfs,
|
||||
|
||||
// append block
|
||||
index += 1;
|
||||
lfs_size_t words = lfs->cfg->block_size / 4;
|
||||
lfs_size_t skips = lfs_min(lfs_ctz(index)+1, words-1);
|
||||
lfs_size_t skips = lfs_ctz(index) + 1;
|
||||
|
||||
for (lfs_off_t i = 0; i < skips; i++) {
|
||||
int err = lfs_cache_prog(lfs, pcache, rcache,
|
||||
@@ -1880,6 +1877,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
}
|
||||
}
|
||||
|
||||
// check that the block size is large enough to fit ctz pointers
|
||||
assert(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))
|
||||
<= lfs->cfg->block_size);
|
||||
|
||||
// setup default state
|
||||
lfs->root[0] = 0xffffffff;
|
||||
lfs->root[1] = 0xffffffff;
|
||||
|
||||
Reference in New Issue
Block a user