Skip to content

Commit 795dd8c

Browse files
committed
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.
1 parent 97a7191 commit 795dd8c

File tree

3 files changed

+39
-10
lines changed

3 files changed

+39
-10
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ jobs:
126126
- mkdir mount/littlefs
127127
- cp -r $(git ls-tree --name-only HEAD) mount/littlefs
128128
- cd mount/littlefs
129-
- ls
129+
- ls -flh
130130
- make -B test_dirs test_files QUIET=1
131131

132132
# Automatically update releases

lfs.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,29 +1746,58 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
17461746

17471747
// build up new directory
17481748
lfs_alloc_ack(lfs);
1749-
17501749
lfs_mdir_t dir;
17511750
err = lfs_dir_alloc(lfs, &dir);
17521751
if (err) {
17531752
return err;
17541753
}
17551754

1756-
dir.tail[0] = cwd.tail[0];
1757-
dir.tail[1] = cwd.tail[1];
1755+
// find end of list
1756+
lfs_mdir_t pred = cwd;
1757+
while (pred.split) {
1758+
err = lfs_dir_fetch(lfs, &pred, pred.tail);
1759+
if (err) {
1760+
return err;
1761+
}
1762+
}
1763+
1764+
// setup dir
1765+
dir.tail[0] = pred.tail[0];
1766+
dir.tail[1] = pred.tail[1];
17581767
err = lfs_dir_commit(lfs, &dir, NULL);
17591768
if (err) {
17601769
return err;
17611770
}
17621771

1763-
// get next slot and commit
1764-
cwd.tail[0] = dir.pair[0];
1765-
cwd.tail[1] = dir.pair[1];
1772+
// current block end of list?
1773+
if (!cwd.split) {
1774+
// update atomically
1775+
cwd.tail[0] = dir.pair[0];
1776+
cwd.tail[1] = dir.pair[1];
1777+
} else {
1778+
// update tails, this creates a desync
1779+
pred.tail[0] = dir.pair[0];
1780+
pred.tail[1] = dir.pair[1];
1781+
lfs_global_orphans(lfs, +1);
1782+
err = lfs_dir_commit(lfs, &pred,
1783+
LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff,
1784+
pred.tail, sizeof(pred.tail),
1785+
NULL));
1786+
if (err) {
1787+
return err;
1788+
}
1789+
lfs_global_orphans(lfs, -1);
1790+
}
1791+
1792+
// now insert into our parent block
17661793
lfs_pair_tole32(dir.pair);
17671794
err = lfs_dir_commit(lfs, &cwd,
1768-
LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff, cwd.tail, sizeof(cwd.tail),
17691795
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair),
17701796
LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen,
1771-
NULL))));
1797+
(!cwd.split)
1798+
? LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff,
1799+
cwd.tail, sizeof(cwd.tail), NULL)
1800+
: NULL)));
17721801
lfs_pair_fromle32(dir.pair);
17731802
if (err) {
17741803
return err;

tests/test_corrupt.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ do
8989
rm -rf blocks
9090
mkdir blocks
9191
lfs_mktree
92-
chmod a-w blocks/$b
92+
chmod a-w blocks/$b || true
9393
lfs_mktree
9494
lfs_chktree
9595
done

0 commit comments

Comments
 (0)