Skip to content

Commit 3b1bcbe

Browse files
committed
Removed .. and . entries
No longer need to be stored on disk, can be simulated on the chip side. As mentioned in other commits, the parent entries had dozens of problems with atomic updates, as well as making everything just a bit more complex than is needed.
1 parent 1f13006 commit 3b1bcbe

File tree

2 files changed

+56
-60
lines changed

2 files changed

+56
-60
lines changed

lfs.c

Lines changed: 55 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,7 @@ static int lfs_pair_shift(lfs_t *lfs, lfs_block_t pair[2],
522522

523523
/// Directory operations ///
524524

525-
static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir,
526-
lfs_block_t parent[2], lfs_block_t tail[2]) {
525+
static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t tail[2]) {
527526
// Allocate pair of dir blocks
528527
for (int i = 0; i < 2; i++) {
529528
int err = lfs_alloc(lfs, &dir->pair[i]);
@@ -549,35 +548,10 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir,
549548
dir->d.tail[1] = tail[1];
550549

551550
// Write out to memory
552-
if (!parent) {
553-
return lfs_pair_commit(lfs, dir->pair,
554-
1, (struct lfs_commit_region[]){
555-
{0, sizeof(dir->d), &dir->d}
556-
});
557-
} else {
558-
dir->d.size += 2*sizeof(struct lfs_disk_entry) + 3;
559-
return lfs_pair_commit(lfs, dir->pair,
560-
5, (struct lfs_commit_region[]){
561-
{0, sizeof(dir->d), &dir->d},
562-
{sizeof(dir->d), sizeof(struct lfs_disk_entry),
563-
&(struct lfs_disk_entry){
564-
.type = LFS_TYPE_DIR,
565-
.len = sizeof(struct lfs_disk_entry)+1,
566-
.u.dir[0] = dir->pair[0],
567-
.u.dir[1] = dir->pair[1],
568-
}},
569-
{sizeof(dir->d)+sizeof(struct lfs_disk_entry), 1, "."},
570-
{sizeof(dir->d)+sizeof(struct lfs_disk_entry)+1,
571-
sizeof(struct lfs_disk_entry),
572-
&(struct lfs_disk_entry){
573-
.type = LFS_TYPE_DIR,
574-
.len = sizeof(struct lfs_disk_entry)+2,
575-
.u.dir[0] = parent[0] ? parent[0] : dir->pair[0],
576-
.u.dir[1] = parent[1] ? parent[1] : dir->pair[1],
577-
}},
578-
{sizeof(dir->d)+2*sizeof(struct lfs_disk_entry)+1, 2, ".."},
579-
});
580-
}
551+
return lfs_pair_commit(lfs, dir->pair,
552+
1, (struct lfs_commit_region[]){
553+
{0, sizeof(dir->d), &dir->d}
554+
});
581555
}
582556

583557
static int lfs_dir_fetch(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t pair[2]) {
@@ -725,7 +699,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
725699
lfs_dir_t olddir;
726700
memcpy(&olddir, dir, sizeof(olddir));
727701

728-
int err = lfs_dir_alloc(lfs, dir, 0, olddir.d.tail);
702+
int err = lfs_dir_alloc(lfs, dir, olddir.d.tail);
729703
if (err) {
730704
return err;
731705
}
@@ -763,7 +737,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
763737

764738
// Build up new directory
765739
lfs_dir_t dir;
766-
err = lfs_dir_alloc(lfs, &dir, cwd.pair, cwd.d.tail);
740+
err = lfs_dir_alloc(lfs, &dir, cwd.d.tail);
767741
if (err) {
768742
return err;
769743
}
@@ -799,6 +773,8 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
799773
if (err) {
800774
return err;
801775
} else if (strcmp(path, "/") == 0) {
776+
// special offset for '.' and '..'
777+
dir->off = sizeof(dir->d) - 2;
802778
return 0;
803779
}
804780

@@ -810,7 +786,14 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
810786
return LFS_ERROR_NOT_DIR;
811787
}
812788

813-
return lfs_dir_fetch(lfs, dir, entry.d.u.dir);
789+
err = lfs_dir_fetch(lfs, dir, entry.d.u.dir);
790+
if (err) {
791+
return err;
792+
}
793+
794+
// special offset for '.' and '..'
795+
dir->off = sizeof(dir->d) - 2;
796+
return 0;
814797
}
815798

816799
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
@@ -821,6 +804,18 @@ int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
821804
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
822805
memset(info, 0, sizeof(*info));
823806

807+
if (dir->off == sizeof(dir->d) - 2) {
808+
info->type = LFS_TYPE_DIR;
809+
strcpy(info->name, ".");
810+
dir->off += 1;
811+
return 1;
812+
} else if (dir->off == sizeof(dir->d) - 1) {
813+
info->type = LFS_TYPE_DIR;
814+
strcpy(info->name, "..");
815+
dir->off += 1;
816+
return 1;
817+
}
818+
824819
lfs_entry_t entry;
825820
int err = lfs_dir_next(lfs, dir, &entry);
826821
if (err) {
@@ -1100,8 +1095,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) {
11001095

11011096
// Write root directory
11021097
lfs_dir_t root;
1103-
err = lfs_dir_alloc(lfs, &root,
1104-
(lfs_block_t[2]){0, 0}, (lfs_block_t[2]){0, 0});
1098+
err = lfs_dir_alloc(lfs, &root, (lfs_block_t[2]){0, 0});
11051099
if (err) {
11061100
return err;
11071101
}
@@ -1195,9 +1189,6 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
11951189
return err;
11961190
}
11971191

1198-
// skip '.' and '..'
1199-
dir.off += 2*sizeof(struct lfs_disk_entry) + 3;
1200-
12011192
// iterate over contents
12021193
while ((0x7fffffff & dir.d.size) >= dir.off + sizeof(file.entry.d)) {
12031194
int err = lfs_bd_read(lfs, dir.pair[0], dir.off,
@@ -1248,14 +1239,6 @@ static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2]) {
12481239
return err;
12491240
}
12501241

1251-
// skip .. and . entries
1252-
for (int i = 0; i < 2; i++) {
1253-
int err = lfs_dir_next(lfs, &parent, &entry);
1254-
if (err) {
1255-
return err;
1256-
}
1257-
}
1258-
12591242
while (true) {
12601243
int err = lfs_dir_next(lfs, &parent, &entry);
12611244
if (err && err != LFS_ERROR_NO_ENTRY) {
@@ -1339,12 +1322,13 @@ int lfs_remove(lfs_t *lfs, const char *path) {
13391322

13401323
lfs_dir_t dir;
13411324
if (entry.d.type == LFS_TYPE_DIR) {
1342-
// must be empty before removal
1325+
// must be empty before removal, checking size
1326+
// without masking top bit checks for any case where
1327+
// dir is not empty
13431328
int err = lfs_dir_fetch(lfs, &dir, entry.d.u.dir);
13441329
if (err) {
13451330
return err;
1346-
} else if (dir.d.size != sizeof(dir.d) +
1347-
2*sizeof(struct lfs_disk_entry) + 3) {
1331+
} else if (dir.d.size != sizeof(dir.d)) {
13481332
return LFS_ERROR_INVALID;
13491333
}
13501334
}
@@ -1367,16 +1351,28 @@ int lfs_remove(lfs_t *lfs, const char *path) {
13671351
}
13681352
}
13691353

1370-
pdir.d.tail[0] = cwd.d.tail[0];
1371-
pdir.d.tail[1] = cwd.d.tail[1];
1372-
pdir.d.rev += 1;
1354+
// TODO easier check for head block? (common case)
1355+
if (!(pdir.d.size & 0x80000000)) {
1356+
int err = lfs_pair_shift(lfs, entry.dir,
1357+
1, (struct lfs_commit_region[]) {
1358+
{0, sizeof(cwd.d), &cwd.d},
1359+
},
1360+
entry.off, entry.d.len);
1361+
if (err) {
1362+
return err;
1363+
}
1364+
} else {
1365+
pdir.d.tail[0] = cwd.d.tail[0];
1366+
pdir.d.tail[1] = cwd.d.tail[1];
1367+
pdir.d.rev += 1;
13731368

1374-
err = lfs_pair_commit(lfs, pdir.pair,
1375-
1, (struct lfs_commit_region[]) {
1376-
{0, sizeof(pdir.d), &pdir.d},
1377-
});
1378-
if (err) {
1379-
return err;
1369+
err = lfs_pair_commit(lfs, pdir.pair,
1370+
1, (struct lfs_commit_region[]) {
1371+
{0, sizeof(pdir.d), &pdir.d},
1372+
});
1373+
if (err) {
1374+
return err;
1375+
}
13801376
}
13811377
} else {
13821378
int err = lfs_pair_shift(lfs, entry.dir,

tests/test_orphan.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ tests/test.py << TEST
1717
TEST
1818
# remove most recent file, this should be the update to the previous
1919
# linked-list entry and should orphan the child
20-
rm -v "blocks/$(ls -t blocks | sed -n '/^[0-9a-f]*$/p' | sed -n '1p')"
20+
rm -v blocks/8
2121
tests/test.py << TEST
2222
lfs_mount(&lfs, &config) => 0;
2323
lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERROR_NO_ENTRY;

0 commit comments

Comments
 (0)