From f3578e3250d1027bbc9e3fe2fa535b8ed540c5d8 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 10 Oct 2017 18:48:24 -0500 Subject: [PATCH] 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. --- lfs.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lfs.c b/lfs.c index 4733dcc..50760be 100644 --- a/lfs.c +++ b/lfs.c @@ -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;