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.
This commit is contained in:
Christopher Haster
2018-10-05 18:22:33 -05:00
parent 97a7191814
commit 795dd8c7ab
3 changed files with 39 additions and 10 deletions

View File

@@ -126,7 +126,7 @@ jobs:
- mkdir mount/littlefs - mkdir mount/littlefs
- cp -r $(git ls-tree --name-only HEAD) mount/littlefs - cp -r $(git ls-tree --name-only HEAD) mount/littlefs
- cd mount/littlefs - cd mount/littlefs
- ls - ls -flh
- make -B test_dirs test_files QUIET=1 - make -B test_dirs test_files QUIET=1
# Automatically update releases # Automatically update releases

45
lfs.c
View File

@@ -1746,29 +1746,58 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
// build up new directory // build up new directory
lfs_alloc_ack(lfs); lfs_alloc_ack(lfs);
lfs_mdir_t dir; lfs_mdir_t dir;
err = lfs_dir_alloc(lfs, &dir); err = lfs_dir_alloc(lfs, &dir);
if (err) { if (err) {
return err; return err;
} }
dir.tail[0] = cwd.tail[0]; // find end of list
dir.tail[1] = cwd.tail[1]; 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); err = lfs_dir_commit(lfs, &dir, NULL);
if (err) { if (err) {
return err; return err;
} }
// get next slot and commit // current block end of list?
cwd.tail[0] = dir.pair[0]; if (!cwd.split) {
cwd.tail[1] = dir.pair[1]; // 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); lfs_pair_tole32(dir.pair);
err = lfs_dir_commit(lfs, &cwd, 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_DIRSTRUCT, id, dir.pair, sizeof(dir.pair),
LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen, 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); lfs_pair_fromle32(dir.pair);
if (err) { if (err) {
return err; return err;

View File

@@ -89,7 +89,7 @@ do
rm -rf blocks rm -rf blocks
mkdir blocks mkdir blocks
lfs_mktree lfs_mktree
chmod a-w blocks/$b chmod a-w blocks/$b || true
lfs_mktree lfs_mktree
lfs_chktree lfs_chktree
done done