Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--lfs.c26
-rwxr-xr-xtests/test_parallel.sh186
3 files changed, 213 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 4f8b79a..10afda9 100644
--- a/Makefile
+++ b/Makefile
@@ -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
./$<
diff --git a/lfs.c b/lfs.c
index 5c8baea..da329fe 100644
--- a/lfs.c
+++ b/lfs.c
@@ -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