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:
authorChristopher Haster <chaster@utexas.edu>2018-10-06 02:22:33 +0300
committerChristopher Haster <chaster@utexas.edu>2018-10-18 18:00:49 +0300
commit795dd8c7ab930892536c6c2ee7c29b8bfac477db (patch)
treea006878cc33f41db9733c2e0ca98e6b598bb719c
parent97a7191814a5900a35f11c3ebac0f6a710a6bb90 (diff)
Fixed mkdir when inserting into a non-end block
This was an oversight on my part when adding strict ordering to directories. Unfortunately now we can't take advantage of the atomic creation of tail+dir entries. Now we need to first create the tail, then create the actually directory entry. If we lose power, the orphan is cleaned up like orphans created during remove. Note that we still take advantage of the atomic tail+dir entries if we are an end block. This is actually because this corner case is complicated to _not_ do atomically, needing to update the directory we just committed to.
-rw-r--r--.travis.yml2
-rw-r--r--lfs.c45
-rwxr-xr-xtests/test_corrupt.sh2
3 files changed, 39 insertions, 10 deletions
diff --git a/.travis.yml b/.travis.yml
index e3f786b..255e84b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -126,7 +126,7 @@ jobs:
- mkdir mount/littlefs
- cp -r $(git ls-tree --name-only HEAD) mount/littlefs
- cd mount/littlefs
- - ls
+ - ls -flh
- make -B test_dirs test_files QUIET=1
# Automatically update releases
diff --git a/lfs.c b/lfs.c
index 0d5f079..32e626f 100644
--- a/lfs.c
+++ b/lfs.c
@@ -1746,29 +1746,58 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
// build up new directory
lfs_alloc_ack(lfs);
-
lfs_mdir_t dir;
err = lfs_dir_alloc(lfs, &dir);
if (err) {
return err;
}
- dir.tail[0] = cwd.tail[0];
- dir.tail[1] = cwd.tail[1];
+ // find end of list
+ lfs_mdir_t pred = cwd;
+ while (pred.split) {
+ err = lfs_dir_fetch(lfs, &pred, pred.tail);
+ if (err) {
+ return err;
+ }
+ }
+
+ // setup dir
+ dir.tail[0] = pred.tail[0];
+ dir.tail[1] = pred.tail[1];
err = lfs_dir_commit(lfs, &dir, NULL);
if (err) {
return err;
}
- // get next slot and commit
- cwd.tail[0] = dir.pair[0];
- cwd.tail[1] = dir.pair[1];
+ // current block end of list?
+ if (!cwd.split) {
+ // update atomically
+ cwd.tail[0] = dir.pair[0];
+ cwd.tail[1] = dir.pair[1];
+ } else {
+ // update tails, this creates a desync
+ pred.tail[0] = dir.pair[0];
+ pred.tail[1] = dir.pair[1];
+ lfs_global_orphans(lfs, +1);
+ err = lfs_dir_commit(lfs, &pred,
+ LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff,
+ pred.tail, sizeof(pred.tail),
+ NULL));
+ if (err) {
+ return err;
+ }
+ lfs_global_orphans(lfs, -1);
+ }
+
+ // now insert into our parent block
lfs_pair_tole32(dir.pair);
err = lfs_dir_commit(lfs, &cwd,
- LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff, cwd.tail, sizeof(cwd.tail),
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair),
LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen,
- NULL))));
+ (!cwd.split)
+ ? LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff,
+ cwd.tail, sizeof(cwd.tail), NULL)
+ : NULL)));
lfs_pair_fromle32(dir.pair);
if (err) {
return err;
diff --git a/tests/test_corrupt.sh b/tests/test_corrupt.sh
index a73b7f8..81b0674 100755
--- a/tests/test_corrupt.sh
+++ b/tests/test_corrupt.sh
@@ -89,7 +89,7 @@ do
rm -rf blocks
mkdir blocks
lfs_mktree
- chmod a-w blocks/$b
+ chmod a-w blocks/$b || true
lfs_mktree
lfs_chktree
done