diff options
author | Christopher Haster <chaster@utexas.edu> | 2017-11-17 02:25:41 +0300 |
---|---|---|
committer | Christopher Haster <chaster@utexas.edu> | 2017-11-17 02:25:41 +0300 |
commit | 843e3c6c7544de3ebb03821514f9cb7b1135e8cf (patch) | |
tree | d9b674c9478455b07060afe5bba51e9ad5372874 /lfs.c | |
parent | 2612e1b3faaa72cd79343c2d43187aafa0492b76 (diff) |
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.
Diffstat (limited to 'lfs.c')
-rw-r--r-- | lfs.c | 9 |
1 files changed, 8 insertions, 1 deletions
@@ -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; } |