Implemented desynchronized files
Desynchronized files are a new concept intended to capture some useful
quirks of the previous multiple-open-file behavior.
This adds:
- LFS_O_DESYNC - Mark a file as desync during open
- lfsr_file_desync - Mark a file as desync whenever
- lfsr_file_sync - Mark a file as NOT desync, and sync the file
Desynced files:
1. Don't recieve updates from writes to other file handles. This makes
desynced files act as a sort of snapshot of the file at the time it
was marked desync.
2. Don't call lfsr_file_sync on close. Unless lfsr_file_sync is
explicitly called, changes to desynced files are not reflected on
disk and not broadcasted to other file handles.
A side-effect of 2., is that this gives you a quick way to abort a file
write. Marking a file as desync and then closing the file will never
error.
Additionally, if an error occurs during a write operation, the file is
implicitly marked as desync. This provides graceful write aborting in
unlikely error cases. This has actually always been a feature in
littlefs, it was just named differently and didn't have an optional
recovery mode.
Since littlefs actually has to do more work to keep files in sync, the
desync feature is quite cheap:
code stack
before: 33324 3072
after: 33360 (+0.1%) 3072 (+0.0%)
This commit is contained in:
@@ -162,12 +162,12 @@ enum lfs_open_flags {
|
||||
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
||||
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
||||
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
||||
LFS_O_DESYNC = 0x1000, // Do not sync or recieve file updates
|
||||
#endif
|
||||
|
||||
// internally used flags
|
||||
LFS_F_UNFLUSHED = 0x010000, // File's data does not match storage
|
||||
LFS_F_UNSYNCED = 0x020000, // File's metadata does not match storage
|
||||
LFS_F_ERRORED = 0x040000, // An error occurred during write
|
||||
};
|
||||
|
||||
// File seek flags
|
||||
@@ -778,8 +778,13 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
||||
|
||||
// Close a file
|
||||
//
|
||||
// Any pending writes are written out to storage as though
|
||||
// sync had been called and releases any allocated resources.
|
||||
// If the file is not desynchronized, any pending writes are written out
|
||||
// to storage as though sync had been called.
|
||||
//
|
||||
// Releases any allocated resources, even if there is an error.
|
||||
//
|
||||
// Readonly and desynchronized files do not touch disk and will always
|
||||
// return 0.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
|
||||
@@ -787,11 +792,30 @@ int lfsr_file_close(lfs_t *lfs, lfsr_file_t *file);
|
||||
|
||||
// Synchronize a file on storage
|
||||
//
|
||||
// Any pending writes are written out to storage.
|
||||
// Any pending writes are written out to storage and other open files.
|
||||
//
|
||||
// If the file was desynchronized, it is now marked as synchronized. It will
|
||||
// now recieve file updates and syncs on close.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
|
||||
int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file);
|
||||
|
||||
// Mark a file as desynchronized
|
||||
//
|
||||
// Desynchronized files do not recieve file updates and do not sync on close.
|
||||
// They effectively act as snapshots of the underlying file at that point
|
||||
// in time.
|
||||
//
|
||||
// If an error occurs during a write operation, the file is implicitly marked
|
||||
// as desynchronized.
|
||||
//
|
||||
// An explicit and successful call to lfsr_file_sync reverses this, marking
|
||||
// the file as synchronized again.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfsr_file_desync(lfs_t *lfs, lfsr_file_t *file);
|
||||
|
||||
// Read data from file
|
||||
//
|
||||
// Takes a buffer and size indicating where to store the read data.
|
||||
|
||||
Reference in New Issue
Block a user