diff --git a/Makefile b/Makefile index a22fc22..95c26da 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ test: \ test_attrs \ test_move \ test_orphan \ + test_relocations \ test_corrupt @rm test.c test_%: tests/test_%.sh diff --git a/lfs.c b/lfs.c index 95a3b6a..e71faff 100644 --- a/lfs.c +++ b/lfs.c @@ -2103,8 +2103,6 @@ int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) { return err; } - dir->m.pair[0] = dir->head[0]; - dir->m.pair[1] = dir->head[1]; dir->id = 0; dir->pos = 0; LFS_TRACE("lfs_dir_rewind -> %d", 0); @@ -3887,6 +3885,12 @@ static int lfs_fs_relocate(lfs_t *lfs, d->m.pair[0] = newpair[0]; d->m.pair[1] = newpair[1]; } + + if (d->type == LFS_TYPE_DIR && + lfs_pair_cmp(oldpair, ((lfs_dir_t*)d)->head) == 0) { + ((lfs_dir_t*)d)->head[0] = newpair[0]; + ((lfs_dir_t*)d)->head[1] = newpair[1]; + } } // find parent diff --git a/tests/test_relocations.sh b/tests/test_relocations.sh new file mode 100755 index 0000000..4a371ea --- /dev/null +++ b/tests/test_relocations.sh @@ -0,0 +1,88 @@ +#!/bin/bash +set -eu +export TEST_FILE=$0 +trap 'export TEST_LINE=$LINENO' DEBUG + +ITERATIONS=20 +COUNT=10 + +echo "=== Relocation tests ===" +rm -rf blocks +scripts/test.py << TEST + lfs_format(&lfs, &cfg) => 0; + // fill up filesystem so only ~16 blocks are left + lfs_mount(&lfs, &cfg) => 0; + lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; + memset(buffer, 0, 512); + while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { + lfs_file_write(&lfs, &file, buffer, 512) => 512; + } + lfs_file_close(&lfs, &file) => 0; + // make a child dir to use in bounded space + lfs_mkdir(&lfs, "child") => 0; + lfs_unmount(&lfs) => 0; +TEST + +echo "--- Outdated head test ---" +scripts/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + for (int j = 0; j < $ITERATIONS; j++) { + for (int i = 0; i < $COUNT; i++) { + sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); + lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + lfs_dir_open(&lfs, &dir, "child") => 0; + lfs_dir_read(&lfs, &dir, &info) => 1; + lfs_dir_read(&lfs, &dir, &info) => 1; + for (int i = 0; i < $COUNT; i++) { + sprintf(path, "test%03d_loooooooooooooooooong_name", i); + lfs_dir_read(&lfs, &dir, &info) => 1; + strcmp(info.name, path) => 0; + info.size => 0; + + sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); + lfs_file_open(&lfs, &file, path, LFS_O_WRONLY) => 0; + lfs_file_write(&lfs, &file, "hi", 2) => 2; + lfs_file_close(&lfs, &file) => 0; + } + lfs_dir_read(&lfs, &dir, &info) => 0; + + lfs_dir_rewind(&lfs, &dir) => 0; + lfs_dir_read(&lfs, &dir, &info) => 1; + lfs_dir_read(&lfs, &dir, &info) => 1; + for (int i = 0; i < $COUNT; i++) { + sprintf(path, "test%03d_loooooooooooooooooong_name", i); + lfs_dir_read(&lfs, &dir, &info) => 1; + strcmp(info.name, path) => 0; + info.size => 2; + + sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); + lfs_file_open(&lfs, &file, path, LFS_O_WRONLY) => 0; + lfs_file_write(&lfs, &file, "hi", 2) => 2; + lfs_file_close(&lfs, &file) => 0; + } + lfs_dir_read(&lfs, &dir, &info) => 0; + + lfs_dir_rewind(&lfs, &dir) => 0; + lfs_dir_read(&lfs, &dir, &info) => 1; + lfs_dir_read(&lfs, &dir, &info) => 1; + for (int i = 0; i < $COUNT; i++) { + sprintf(path, "test%03d_loooooooooooooooooong_name", i); + lfs_dir_read(&lfs, &dir, &info) => 1; + strcmp(info.name, path) => 0; + info.size => 2; + } + lfs_dir_read(&lfs, &dir, &info) => 0; + lfs_dir_close(&lfs, &dir) => 0; + + for (int i = 0; i < $COUNT; i++) { + sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); + lfs_remove(&lfs, path) => 0; + } + } + lfs_unmount(&lfs) => 0; +TEST + +scripts/results.py