diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | lfs.c | 26 | ||||
-rwxr-xr-x | tests/test_parallel.sh | 186 |
3 files changed, 213 insertions, 2 deletions
@@ -31,7 +31,8 @@ size: $(OBJ) $(SIZE) -t $^ .SUFFIXES: -test: test_format test_dirs test_files test_seek test_alloc test_paths test_orphan +test: test_format test_dirs test_files test_seek test_parallel \ + test_alloc test_paths test_orphan test_%: tests/test_%.sh ./$< @@ -1155,7 +1155,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { return err; } - if (file->flags & LFS_F_DIRTY) { + if ((file->flags & LFS_F_DIRTY) && !lfs_pairisnull(file->pair)) { // update dir entry lfs_dir_t cwd; int err = lfs_dir_fetch(lfs, &cwd, file->pair); @@ -1406,6 +1406,18 @@ int lfs_remove(lfs_t *lfs, const char *path) { return err; } + // shift over any files that are affected + for (lfs_file_t *f = lfs->files; f; f = f->next) { + if (lfs_paircmp(f->pair, cwd.pair) == 0) { + if (f->poff == entry.off) { + f->pair[0] = 0xffffffff; + f->pair[1] = 0xffffffff; + } else if (f->poff > entry.off) { + f->poff -= entry.d.len; + } + } + } + // if we were a directory, just run a deorphan step, this should // collect us, although is expensive if (entry.d.type == LFS_TYPE_DIR) { @@ -1498,6 +1510,18 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { return err; } + // shift over any files that are affected + for (lfs_file_t *f = lfs->files; f; f = f->next) { + if (lfs_paircmp(f->pair, oldcwd.pair) == 0) { + if (f->poff == oldentry.off) { + f->pair[0] = 0xffffffff; + f->pair[1] = 0xffffffff; + } else if (f->poff > oldentry.off) { + f->poff -= oldentry.d.len; + } + } + } + // if we were a directory, just run a deorphan step, this should // collect us, although is expensive if (prevexists && preventry.d.type == LFS_TYPE_DIR) { diff --git a/tests/test_parallel.sh b/tests/test_parallel.sh new file mode 100755 index 0000000..71c9c1f --- /dev/null +++ b/tests/test_parallel.sh @@ -0,0 +1,186 @@ +#!/bin/bash +set -eu + +echo "=== Parallel tests ===" +rm -rf blocks +tests/test.py << TEST + lfs_format(&lfs, &cfg) => 0; +TEST + +echo "--- Parallel file test ---" +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + lfs_file_open(&lfs, &file[0], "a", LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_open(&lfs, &file[1], "b", LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_open(&lfs, &file[2], "c", LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_open(&lfs, &file[3], "d", LFS_O_WRONLY | LFS_O_CREAT) => 0; + + for (int i = 0; i < 10; i++) { + lfs_file_write(&lfs, &file[0], (const void*)"a", 1) => 1; + lfs_file_write(&lfs, &file[1], (const void*)"b", 1) => 1; + lfs_file_write(&lfs, &file[2], (const void*)"c", 1) => 1; + lfs_file_write(&lfs, &file[3], (const void*)"d", 1) => 1; + } + + lfs_file_close(&lfs, &file[0]); + lfs_file_close(&lfs, &file[1]); + lfs_file_close(&lfs, &file[2]); + lfs_file_close(&lfs, &file[3]); + + lfs_dir_open(&lfs, &dir[0], "/") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, ".") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "..") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "a") => 0; + info.type => LFS_TYPE_REG; + info.size => 10; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "b") => 0; + info.type => LFS_TYPE_REG; + info.size => 10; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "c") => 0; + info.type => LFS_TYPE_REG; + info.size => 10; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "d") => 0; + info.type => LFS_TYPE_REG; + info.size => 10; + lfs_dir_read(&lfs, &dir[0], &info) => 0; + lfs_dir_close(&lfs, &dir[0]) => 0; + + lfs_file_open(&lfs, &file[0], "a", LFS_O_RDONLY) => 0; + lfs_file_open(&lfs, &file[1], "b", LFS_O_RDONLY) => 0; + lfs_file_open(&lfs, &file[2], "c", LFS_O_RDONLY) => 0; + lfs_file_open(&lfs, &file[3], "d", LFS_O_RDONLY) => 0; + + for (int i = 0; i < 10; i++) { + lfs_file_read(&lfs, &file[0], buffer, 1) => 1; + buffer[0] => 'a'; + lfs_file_read(&lfs, &file[1], buffer, 1) => 1; + buffer[0] => 'b'; + lfs_file_read(&lfs, &file[2], buffer, 1) => 1; + buffer[0] => 'c'; + lfs_file_read(&lfs, &file[3], buffer, 1) => 1; + buffer[0] => 'd'; + } + + lfs_file_close(&lfs, &file[0]); + lfs_file_close(&lfs, &file[1]); + lfs_file_close(&lfs, &file[2]); + lfs_file_close(&lfs, &file[3]); + + lfs_unmount(&lfs) => 0; +TEST + +echo "--- Parallel remove file test ---" +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + lfs_file_open(&lfs, &file[0], "e", LFS_O_WRONLY | LFS_O_CREAT) => 0; + + for (int i = 0; i < 5; i++) { + lfs_file_write(&lfs, &file[0], (const void*)"e", 1) => 1; + } + + lfs_remove(&lfs, "a") => 0; + lfs_remove(&lfs, "b") => 0; + lfs_remove(&lfs, "c") => 0; + lfs_remove(&lfs, "d") => 0; + + for (int i = 0; i < 5; i++) { + lfs_file_write(&lfs, &file[0], (const void*)"e", 1) => 1; + } + + lfs_file_close(&lfs, &file[0]); + + lfs_dir_open(&lfs, &dir[0], "/") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, ".") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "..") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "e") => 0; + info.type => LFS_TYPE_REG; + info.size => 10; + lfs_dir_read(&lfs, &dir[0], &info) => 0; + lfs_dir_close(&lfs, &dir[0]) => 0; + + lfs_file_open(&lfs, &file[0], "e", LFS_O_RDONLY) => 0; + + for (int i = 0; i < 10; i++) { + lfs_file_read(&lfs, &file[0], buffer, 1) => 1; + buffer[0] => 'e'; + } + + lfs_file_close(&lfs, &file[0]); + + lfs_unmount(&lfs) => 0; +TEST + +echo "--- Remove inconveniently test ---" +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + lfs_file_open(&lfs, &file[0], "e", LFS_O_WRONLY | LFS_O_TRUNC) => 0; + lfs_file_open(&lfs, &file[1], "f", LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_open(&lfs, &file[2], "g", LFS_O_WRONLY | LFS_O_CREAT) => 0; + + for (int i = 0; i < 5; i++) { + lfs_file_write(&lfs, &file[0], (const void*)"e", 1) => 1; + lfs_file_write(&lfs, &file[1], (const void*)"f", 1) => 1; + lfs_file_write(&lfs, &file[2], (const void*)"g", 1) => 1; + } + + lfs_remove(&lfs, "f") => 0; + + for (int i = 0; i < 5; i++) { + lfs_file_write(&lfs, &file[0], (const void*)"e", 1) => 1; + lfs_file_write(&lfs, &file[1], (const void*)"f", 1) => 1; + lfs_file_write(&lfs, &file[2], (const void*)"g", 1) => 1; + } + + lfs_file_close(&lfs, &file[0]); + lfs_file_close(&lfs, &file[1]); + lfs_file_close(&lfs, &file[2]); + + lfs_dir_open(&lfs, &dir[0], "/") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, ".") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "..") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "e") => 0; + info.type => LFS_TYPE_REG; + info.size => 10; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "g") => 0; + info.type => LFS_TYPE_REG; + info.size => 10; + lfs_dir_read(&lfs, &dir[0], &info) => 0; + lfs_dir_close(&lfs, &dir[0]) => 0; + + lfs_file_open(&lfs, &file[0], "e", LFS_O_RDONLY) => 0; + lfs_file_open(&lfs, &file[1], "g", LFS_O_RDONLY) => 0; + + for (int i = 0; i < 10; i++) { + lfs_file_read(&lfs, &file[0], buffer, 1) => 1; + buffer[0] => 'e'; + lfs_file_read(&lfs, &file[1], buffer, 1) => 1; + buffer[0] => 'g'; + } + + lfs_file_close(&lfs, &file[0]); + lfs_file_close(&lfs, &file[1]); + + lfs_unmount(&lfs) => 0; +TEST + +echo "--- Results ---" +tests/stats.py |