Added sticky-bit for preventing file syncs after write errors
Short story, files are no longer committed to directories during file sync/close if the last write did not complete successfully. This avoids a set of interesting user-experience issues related to the end-of-life behaviour of the filesystem. As a filesystem approaches end-of-life, the chances of running into LFS_ERR_NOSPC grows rather quickly. Since this condition occurs after at the end of a devices life, it's likely that operating in these conditions hasn't been tested thoroughly. In the specific case of file-writes, you can hit an LFS_ERR_NOSPC after parts of the file have been written out. If the program simply continues and closes the file, the file is written out half completed. Since littlefs has a strong garuntee the prevents half-writes, it's unlikely this state of the file would be expected. To make things worse, since close is also responsible for memory cleanup, it's actually _impossible_ to continue working as it was without leaking memory. By prevent the file commits, end-of-life behaviour should at least retain a previous copy of the filesystem without any surprises.
This commit is contained in:
@@ -1403,7 +1403,9 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((file->flags & LFS_F_DIRTY) && !lfs_pairisnull(file->pair)) {
|
||||
if ((file->flags & LFS_F_DIRTY) &&
|
||||
!(file->flags & LFS_F_ERRED) &&
|
||||
!lfs_pairisnull(file->pair)) {
|
||||
// update dir entry
|
||||
lfs_dir_t cwd;
|
||||
int err = lfs_dir_fetch(lfs, &cwd, file->pair);
|
||||
@@ -1537,6 +1539,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
||||
file->head, file->size,
|
||||
file->pos-1, &file->block, &file->off);
|
||||
if (err) {
|
||||
file->flags |= LFS_F_ERRED;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1550,6 +1553,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
||||
file->block, file->pos,
|
||||
&file->block, &file->off);
|
||||
if (err) {
|
||||
file->flags |= LFS_F_ERRED;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1565,6 +1569,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
||||
if (err == LFS_ERR_CORRUPT) {
|
||||
goto relocate;
|
||||
}
|
||||
file->flags |= LFS_F_ERRED;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1572,6 +1577,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
||||
relocate:
|
||||
err = lfs_file_relocate(lfs, file);
|
||||
if (err) {
|
||||
file->flags |= LFS_F_ERRED;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@@ -1584,6 +1590,7 @@ relocate:
|
||||
lfs_alloc_ack(lfs);
|
||||
}
|
||||
|
||||
file->flags &= ~LFS_F_ERRED;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user