Skip to content

Commit 9ee112a

Browse files
committed
Fixed issue updating dir struct when extended dir chain
Like most of the lfs_dir_t functions, lfs_dir_append is responsible for updating the lfs_dir_t struct if the underlying directory block is moved. This property makes handling worn out blocks much easier by removing the amount of state that needs to be considered during a directory update. However, extending the dir chain is a bit of a corner case. It's not changing the old block, but callers of lfs_dir_append do assume the "entry" will reside in "dir" after lfs_dir_append completes. This issue only occurs when creating files, since mkdir does not use the entry after lfs_dir_append. Unfortunately, the tests against extending the directory chain were all made using mkdir. Found by schouleu
1 parent d9c3637 commit 9ee112a

File tree

3 files changed

+95
-10
lines changed

3 files changed

+95
-10
lines changed

lfs.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -658,17 +658,17 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
658658

659659
// we need to allocate a new dir block
660660
if (!(0x80000000 & dir->d.size)) {
661-
lfs_dir_t newdir;
662-
int err = lfs_dir_alloc(lfs, &newdir);
661+
lfs_dir_t olddir = *dir;
662+
int err = lfs_dir_alloc(lfs, dir);
663663
if (err) {
664664
return err;
665665
}
666666

667-
newdir.d.tail[0] = dir->d.tail[0];
668-
newdir.d.tail[1] = dir->d.tail[1];
669-
entry->off = newdir.d.size - 4;
667+
dir->d.tail[0] = olddir.d.tail[0];
668+
dir->d.tail[1] = olddir.d.tail[1];
669+
entry->off = dir->d.size - 4;
670670
lfs_entry_tole32(&entry->d);
671-
err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){
671+
err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){
672672
{entry->off, 0, &entry->d, sizeof(entry->d)},
673673
{entry->off, 0, data, entry->d.nlen}
674674
}, 2);
@@ -677,10 +677,10 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
677677
return err;
678678
}
679679

680-
dir->d.size |= 0x80000000;
681-
dir->d.tail[0] = newdir.pair[0];
682-
dir->d.tail[1] = newdir.pair[1];
683-
return lfs_dir_commit(lfs, dir, NULL, 0);
680+
olddir.d.size |= 0x80000000;
681+
olddir.d.tail[0] = dir->pair[0];
682+
olddir.d.tail[1] = dir->pair[1];
683+
return lfs_dir_commit(lfs, &olddir, NULL, 0);
684684
}
685685

686686
int err = lfs_dir_fetch(lfs, dir, dir->d.tail);

tests/test_dirs.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ tests/test.py << TEST
118118
sprintf((char*)buffer, "test%d", i);
119119
lfs_dir_read(&lfs, &dir[0], &info) => 1;
120120
strcmp(info.name, (char*)buffer) => 0;
121+
info.type => LFS_TYPE_DIR;
121122
}
122123
lfs_dir_read(&lfs, &dir[0], &info) => 0;
123124
lfs_unmount(&lfs) => 0;
@@ -355,5 +356,70 @@ tests/test.py << TEST
355356
lfs_unmount(&lfs) => 0;
356357
TEST
357358

359+
echo "--- Multi-block directory with files ---"
360+
tests/test.py << TEST
361+
lfs_mount(&lfs, &cfg) => 0;
362+
lfs_mkdir(&lfs, "prickly-pear") => 0;
363+
for (int i = 0; i < $LARGESIZE; i++) {
364+
sprintf((char*)buffer, "prickly-pear/test%d", i);
365+
lfs_file_open(&lfs, &file[0], (char*)buffer,
366+
LFS_O_WRONLY | LFS_O_CREAT) => 0;
367+
size = 6;
368+
memcpy(wbuffer, "Hello", size);
369+
lfs_file_write(&lfs, &file[0], wbuffer, size) => size;
370+
lfs_file_close(&lfs, &file[0]) => 0;
371+
}
372+
lfs_unmount(&lfs) => 0;
373+
TEST
374+
tests/test.py << TEST
375+
lfs_mount(&lfs, &cfg) => 0;
376+
lfs_dir_open(&lfs, &dir[0], "prickly-pear") => 0;
377+
lfs_dir_read(&lfs, &dir[0], &info) => 1;
378+
strcmp(info.name, ".") => 0;
379+
info.type => LFS_TYPE_DIR;
380+
lfs_dir_read(&lfs, &dir[0], &info) => 1;
381+
strcmp(info.name, "..") => 0;
382+
info.type => LFS_TYPE_DIR;
383+
for (int i = 0; i < $LARGESIZE; i++) {
384+
sprintf((char*)buffer, "test%d", i);
385+
lfs_dir_read(&lfs, &dir[0], &info) => 1;
386+
strcmp(info.name, (char*)buffer) => 0;
387+
info.type => LFS_TYPE_REG;
388+
info.size => 6;
389+
}
390+
lfs_dir_read(&lfs, &dir[0], &info) => 0;
391+
lfs_unmount(&lfs) => 0;
392+
TEST
393+
394+
echo "--- Multi-block remove with files ---"
395+
tests/test.py << TEST
396+
lfs_mount(&lfs, &cfg) => 0;
397+
lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY;
398+
399+
for (int i = 0; i < $LARGESIZE; i++) {
400+
sprintf((char*)buffer, "prickly-pear/test%d", i);
401+
lfs_remove(&lfs, (char*)buffer) => 0;
402+
}
403+
404+
lfs_remove(&lfs, "prickly-pear") => 0;
405+
lfs_unmount(&lfs) => 0;
406+
TEST
407+
tests/test.py << TEST
408+
lfs_mount(&lfs, &cfg) => 0;
409+
lfs_dir_open(&lfs, &dir[0], "/") => 0;
410+
lfs_dir_read(&lfs, &dir[0], &info) => 1;
411+
strcmp(info.name, ".") => 0;
412+
info.type => LFS_TYPE_DIR;
413+
lfs_dir_read(&lfs, &dir[0], &info) => 1;
414+
strcmp(info.name, "..") => 0;
415+
info.type => LFS_TYPE_DIR;
416+
lfs_dir_read(&lfs, &dir[0], &info) => 1;
417+
strcmp(info.name, "burito") => 0;
418+
info.type => LFS_TYPE_REG;
419+
lfs_dir_read(&lfs, &dir[0], &info) => 0;
420+
lfs_dir_close(&lfs, &dir[0]) => 0;
421+
lfs_unmount(&lfs) => 0;
422+
TEST
423+
358424
echo "--- Results ---"
359425
tests/stats.py

tests/test_files.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,5 +135,24 @@ tests/test.py << TEST
135135
lfs_unmount(&lfs) => 0;
136136
TEST
137137

138+
echo "--- Many file test ---"
139+
tests/test.py << TEST
140+
lfs_format(&lfs, &cfg) => 0;
141+
TEST
142+
tests/test.py << TEST
143+
// Create 300 files of 6 bytes
144+
lfs_mount(&lfs, &cfg) => 0;
145+
lfs_mkdir(&lfs, "directory") => 0;
146+
for (unsigned i = 0; i < 300; i++) {
147+
snprintf((char*)buffer, sizeof(buffer), "file_%03d", i);
148+
lfs_file_open(&lfs, &file[0], (char*)buffer, LFS_O_WRONLY | LFS_O_CREAT) => 0;
149+
size = 6;
150+
memcpy(wbuffer, "Hello", size);
151+
lfs_file_write(&lfs, &file[0], wbuffer, size) => size;
152+
lfs_file_close(&lfs, &file[0]) => 0;
153+
}
154+
lfs_unmount(&lfs) => 0;
155+
TEST
156+
138157
echo "--- Results ---"
139158
tests/stats.py

0 commit comments

Comments
 (0)