diff --git a/lfs.c b/lfs.c index b21d209..b7cc675 100644 --- a/lfs.c +++ b/lfs.c @@ -278,7 +278,7 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) { % (lfs_soff_t)(lfs->cfg->block_count)) + lfs->cfg->block_count) % lfs->cfg->block_count; - if (off < lfs->cfg->lookahead) { + if (off < lfs->free.size) { lfs->free.buffer[off / 32] |= 1U << (off % 32); } @@ -287,18 +287,7 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) { static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { while (true) { - while (true) { - // check if we have looked at all blocks since last ack - if (lfs->free.begin + lfs->free.off == lfs->free.end) { - LFS_WARN("No more free space %d", lfs->free.end); - return LFS_ERR_NOSPC; - } - - if (lfs->free.off >= lfs_min( - lfs->cfg->lookahead, lfs->cfg->block_count)) { - break; - } - + while (lfs->free.off != lfs->free.size) { lfs_block_t off = lfs->free.off; lfs->free.off += 1; @@ -309,7 +298,15 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { } } - lfs->free.begin += lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count); + // check if we have looked at all blocks since last ack + if (lfs->free.off == lfs->free.ack - lfs->free.begin) { + LFS_WARN("No more free space %d", lfs->free.off + lfs->free.begin); + return LFS_ERR_NOSPC; + } + + lfs->free.begin += lfs->free.size; + lfs->free.size = lfs_min(lfs->cfg->lookahead, + lfs->free.ack - lfs->free.begin); lfs->free.off = 0; // find mask of free blocks from tree @@ -322,7 +319,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { } static void lfs_alloc_ack(lfs_t *lfs) { - lfs->free.end = lfs->free.begin + lfs->free.off + lfs->cfg->block_count; + lfs->free.ack = lfs->free.off-1 + lfs->free.begin + lfs->cfg->block_count; } @@ -2035,11 +2032,11 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { // create free lookahead memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); lfs->free.begin = 0; + lfs->free.size = lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count); lfs->free.off = 0; - lfs->free.end = lfs->free.begin + lfs->free.off + lfs->cfg->block_count; + lfs_alloc_ack(lfs); // create superblock dir - lfs_alloc_ack(lfs); lfs_dir_t superdir; err = lfs_dir_alloc(lfs, &superdir); if (err) { @@ -2112,9 +2109,10 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { } // setup free lookahead - lfs->free.begin = -lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count); - lfs->free.off = -lfs->free.begin; - lfs->free.end = lfs->free.begin + lfs->free.off + lfs->cfg->block_count; + lfs->free.begin = 0; + lfs->free.size = 0; + lfs->free.off = 0; + lfs_alloc_ack(lfs); // load superblock lfs_dir_t dir; diff --git a/lfs.h b/lfs.h index 4ce8878..e24c308 100644 --- a/lfs.h +++ b/lfs.h @@ -260,8 +260,9 @@ typedef struct lfs_superblock { typedef struct lfs_free { lfs_block_t begin; - lfs_block_t end; + lfs_block_t size; lfs_block_t off; + lfs_block_t ack; uint32_t *buffer; } lfs_free_t; diff --git a/tests/test_alloc.sh b/tests/test_alloc.sh index aaae655..493270d 100755 --- a/tests/test_alloc.sh +++ b/tests/test_alloc.sh @@ -266,6 +266,40 @@ tests/test.py << TEST lfs_mkdir(&lfs, "exhaustiondir2") => LFS_ERR_NOSPC; TEST +echo "--- Split dir test ---" +rm -rf blocks +tests/test.py << TEST + lfs_format(&lfs, &cfg) => 0; +TEST +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + + // create one block whole for half a directory + lfs_file_open(&lfs, &file[0], "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_write(&lfs, &file[0], (void*)"hi", 2) => 2; + lfs_file_close(&lfs, &file[0]) => 0; + + lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + size = strlen("blahblahblahblah"); + memcpy(buffer, "blahblahblahblah", size); + for (lfs_size_t i = 0; + i < (cfg.block_count-6)*(cfg.block_size-8); + i += size) { + lfs_file_write(&lfs, &file[0], buffer, size) => size; + } + lfs_file_close(&lfs, &file[0]) => 0; + + // open whole + lfs_remove(&lfs, "bump") => 0; + + lfs_mkdir(&lfs, "splitdir") => 0; + lfs_file_open(&lfs, &file[0], "splitdir/bump", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_write(&lfs, &file[0], buffer, size) => LFS_ERR_NOSPC; + lfs_file_close(&lfs, &file[0]) => 0; + + lfs_unmount(&lfs) => 0; +TEST echo "--- Results ---" tests/stats.py