diff options
author | Christopher Haster <chaster@utexas.edu> | 2017-05-15 09:26:29 +0300 |
---|---|---|
committer | Christopher Haster <chaster@utexas.edu> | 2017-05-15 10:32:49 +0300 |
commit | 69294ac4184757de6ef775e545587d75e313f615 (patch) | |
tree | 2ca22decfb1abbd9497c8c768f7c7923d08731fa /README.md | |
parent | fd1da602d77a812c15db8113960517ac99f5f6f7 (diff) |
Added better documentation
More documentation may still by worthwhile (design documentation?),
but for now this provides a reasonable baseline.
- readme
- license
- header documentation
Diffstat (limited to 'README.md')
-rw-r--r-- | README.md | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..5ba8a7f --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +## The little filesystem + +A little fail-safe filesystem designed for low ram/rom footprint. + +**Fail-safe** - The littlefs is designed to work consistently with random power +failures. During filesystem operations the storage on disk is always kept +in a valid state. The filesystem also has strong copy-on-write garuntees. +When updating a file, the original file will remain unmodified until the +file is closed, or sync is called. + +**Handles bad blocks** - While the littlefs does not implement static wear +leveling, if the underlying block device reports write errors, the littlefs +uses a form of dynamic wear leveling to manage blocks that go bad during +the lifetime of the filesystem. + +**Constrained memory** - The littlefs is designed to work in bounded memory, +recursion is avoided, and dynamic memory is kept to a minimum. The littlefs +allocates two fixed-size buffers for general operations, and one fixed-size +buffer per file. If there is only ever one file in use, these buffers can be +provided statically. + +## Example + +Here's a simple example that updates a file named `boot_count` every time +main runs. The program can be interrupted at any time without losing track +of how many times it has been booted and without corrupting the filesystem: + +``` c +#include "lfs.h" + +// variables used by the filesystem +lfs_t lfs; +lfs_file_t file; + +// configuration of the filesystem is provided by this struct +const struct lfs_config cfg = { + // block device operations + .read = user_provided_block_device_read, + .prog = user_provided_block_device_prog, + .erase = user_provided_block_device_erase, + .sync = user_provided_block_device_sync, + + // block device configuration + .read_size = 16, + .prog_size = 16, + .block_size = 4096, + .block_count = 128, + .lookahead = 128, +}; + +// entry point +int main(void) { + // mount the filesystem + int err = lfs_mount(&lfs, &cfg); + + // reformat if we can't mount the filesystem + // this should only happen on the first boot + if (err) { + lfs_format(&lfs, &cfg); + lfs_mount(&lfs, &cfg); + } + + // read current count + uint32_t boot_count = 0; + lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT); + lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count)); + + // update boot count + boot_count += 1; + printf("boot_count: %ld\n", boot_count); + lfs_file_rewind(&lfs, &file); + lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count)); + + // remember the storage is not updated until the file is closed successfully + lfs_file_close(&lfs, &file); + + // release and resources we were using + lfs_unmount(&lfs); +} +``` + +## Usage + +Detailed documentation (or at least as much detail as is currently available) +can be cound in the comments in [lfs.h](lfs.h). + +As you may have noticed, the littlefs takes in a configuration structure that +defines how the filesystem operates. The configuration struct provides the +filesystem with the block device operations and dimensions, tweakable +parameters that tradeoff memory usage for performance, and optional +static buffers if the user wants to avoid dynamic memory. + +The state of the littlefs is stored in the `lfs_t` type which is left up +to the user to allocate, allowing multiple filesystems to be in use +simultaneously. With the `lfs_t` and configuration struct, a user can either +format a block device or mount the filesystem. + +Once mounted, the littlefs provides a full set of posix-like file and +directory functions, with the deviation that the allocation of filesystem +structures must be provided by the user. An important addition is that +no file updates will actually be written to disk until a sync or close +is called. + +## Other notes + +All littlefs have the potential to return a negative error code. The errors +can be either one of those found in the `enum lfs_error` in [lfs.h](lfs.h), +or an error returned by the user's block device operations. + +It should also be noted that the littlefs does not do anything to insure +that the data written to disk is machine portable. It should be fine as +long as the machines involved share endianness and don't have really +strange padding requirements. If the question does come up, the littlefs +metadata should be stored on disk in little-endian format. + +## Testing + +The littlefs comes with a test suite designed to run on a pc using the +[emulated block device](emubd/lfs_emubd.h) found in the emubd directory. +The tests assume a linux environment and can be started with make: + +``` bash +make test +``` |