diff --git a/lfs.c b/lfs.c index ee8a7a8f..2d174a2c 100644 --- a/lfs.c +++ b/lfs.c @@ -658,7 +658,7 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit, int32_t res = lfs_commit_get(lfs, commit->block, commit->off, commit->ptag, lfs_tag_isuser(tag) ? 0x7ffff000 : 0x7c3ff000, - LFS_MKTAG(lfs_tag_type(tag), toid, 0), + (tag & 0x7fc00000) | LFS_MKTAG(0, toid, 0), 0, NULL, true); if (res < 0 && res != LFS_ERR_NOENT) { return res; @@ -1166,7 +1166,7 @@ static int lfs_dir_compact(lfs_t *lfs, tail.tail[0] = dir->tail[0]; tail.tail[1] = dir->tail[1]; - err = lfs_dir_compact(lfs, &tail, attrs, dir, ack+1-expanding, end); + err = lfs_dir_compact(lfs, &tail, attrs, source, ack+1-expanding, end); if (err) { return err; } @@ -1346,8 +1346,12 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, lfs_global_xor(&lfs->globals, &canceldiff); // update any directories that are affected + lfs_mdir_t copy = *dir; + + // two passes, once for things that aren't us, and one + // for things that are for (lfs_mlist_t *d = lfs->mlist; d; d = d->next) { - if (lfs_pair_cmp(d->m.pair, dir->pair) == 0) { + if (lfs_pair_cmp(d->m.pair, copy.pair) == 0) { d->m = *dir; if (d->id == lfs_tag_id(deletetag)) { d->m.pair[0] = 0xffffffff; diff --git a/tests/test_alloc.sh b/tests/test_alloc.sh index 2be8e17d..7fe5a039 100755 --- a/tests/test_alloc.sh +++ b/tests/test_alloc.sh @@ -194,56 +194,98 @@ tests/test.py << TEST lfs_file_read(&lfs, &file[0], buffer, size) => size; memcmp(buffer, "exhaustion", size) => 0; lfs_file_close(&lfs, &file[0]) => 0; + lfs_remove(&lfs, "exhaustion") => 0; lfs_unmount(&lfs) => 0; TEST echo "--- Dir exhaustion test ---" tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "exhaustion") => 0; - lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + // find out max file size + lfs_mkdir(&lfs, "exhaustiondir") => 0; size = strlen("blahblahblahblah"); memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < (cfg.block_count-4)*(cfg.block_size-8); - i += size) { + lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + int count = 0; + int err; + while (true) { + err = lfs_file_write(&lfs, &file[0], buffer, size); + if (err < 0) { + break; + } + + count += 1; + } + err => LFS_ERR_NOSPC; + lfs_file_close(&lfs, &file[0]) => 0; + + lfs_remove(&lfs, "exhaustion") => 0; + lfs_remove(&lfs, "exhaustiondir") => 0; + + // see if dir fits with max file size + lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + for (int i = 0; i < count; i++) { lfs_file_write(&lfs, &file[0], buffer, size) => size; } lfs_file_close(&lfs, &file[0]) => 0; lfs_mkdir(&lfs, "exhaustiondir") => 0; lfs_remove(&lfs, "exhaustiondir") => 0; + lfs_remove(&lfs, "exhaustion") => 0; - lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_APPEND); - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < (cfg.block_size-8); - i += size) { + // see if dir fits with > max file size + lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + for (int i = 0; i < count+1; i++) { lfs_file_write(&lfs, &file[0], buffer, size) => size; } lfs_file_close(&lfs, &file[0]) => 0; lfs_mkdir(&lfs, "exhaustiondir") => LFS_ERR_NOSPC; + + lfs_remove(&lfs, "exhaustion") => 0; lfs_unmount(&lfs) => 0; TEST echo "--- Chained dir exhaustion test ---" tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "exhaustion") => 0; - lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + // find out max file size + lfs_mkdir(&lfs, "exhaustiondir") => 0; + for (int i = 0; i < 9; i++) { + sprintf((char*)buffer, "dirwithanexhaustivelylongnameforpadding%d", i); + lfs_mkdir(&lfs, (char*)buffer) => 0; + } size = strlen("blahblahblahblah"); memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < (cfg.block_count-24)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file[0], buffer, size) => size; + lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + int count = 0; + int err; + while (true) { + err = lfs_file_write(&lfs, &file[0], buffer, size); + if (err < 0) { + break; + } + + count += 1; } + err => LFS_ERR_NOSPC; lfs_file_close(&lfs, &file[0]) => 0; + lfs_remove(&lfs, "exhaustion") => 0; + lfs_remove(&lfs, "exhaustiondir") => 0; + for (int i = 0; i < 9; i++) { + sprintf((char*)buffer, "dirwithanexhaustivelylongnameforpadding%d", i); + lfs_remove(&lfs, (char*)buffer) => 0; + } + + // see that chained dir fails + lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); + for (int i = 0; i < count+1; i++) { + lfs_file_write(&lfs, &file[0], buffer, size) => size; + } + for (int i = 0; i < 9; i++) { sprintf((char*)buffer, "dirwithanexhaustivelylongnameforpadding%d", i); lfs_mkdir(&lfs, (char*)buffer) => 0; @@ -251,19 +293,24 @@ tests/test.py << TEST lfs_mkdir(&lfs, "exhaustiondir") => LFS_ERR_NOSPC; - lfs_remove(&lfs, "exhaustion") => 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-26)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file[0], buffer, size) => size; + // shorten file to try a second chained dir + while (true) { + err = lfs_mkdir(&lfs, "exhaustiondir"); + if (err != LFS_ERR_NOSPC) { + break; + } + + lfs_ssize_t filesize = lfs_file_size(&lfs, &file[0]); + filesize > 0 => true; + + lfs_file_truncate(&lfs, &file[0], filesize - size) => 0; } - lfs_file_close(&lfs, &file[0]) => 0; + err => 0; - lfs_mkdir(&lfs, "exhaustiondir") => 0; lfs_mkdir(&lfs, "exhaustiondir2") => LFS_ERR_NOSPC; + + lfs_file_close(&lfs, &file[0]) => 0; + lfs_unmount(&lfs) => 0; TEST echo "--- Split dir test ---" diff --git a/tests/test_entries.sh b/tests/test_entries.sh index 447d9bca..4728b7f3 100755 --- a/tests/test_entries.sh +++ b/tests/test_entries.sh @@ -4,7 +4,8 @@ set -eu # Note: These tests are intended for 512 byte inline size at different # inline sizes they should still pass, but won't be testing anything -echo "=== Directory tests ===" +echo "=== Entry tests ===" +rm -rf blocks function read_file { cat << TEST