Commit Graph

11 Commits

Author SHA1 Message Date
Christopher Haster
fd1da602d7 Added support for handling corrupted blocks
This provides a limited form of wear leveling. While wear is
not actually balanced across blocks, the filesystem can recover
from corrupted blocks and extend the lifetime of a device nearly
as much as dynamic wear leveling.

For use-cases where wear is important, it would be better to use
a full form of dynamic wear-leveling at the block level. (or
consider a logging filesystem).

Corrupted block handling was simply added on top of the existing
logic in place for the filesystem, so it's a bit more noodly than
it may have to be, but it gets the work done.
2017-05-15 00:40:56 -05:00
Christopher Haster
63b52c9f2e Added proper handling for removing open files
Conveniently we previously added a linked-list of files
for things like this. This should handle most of the corner
cases where files are open during strange operations.

This also brings up the point that we aren't doing anything similar
for directories and don't even have a dir linked-list. After thinking
about it for a while, I've decided to leave out this handling for dirs.
It will likely be very complicated, with little gains as directories
are less used in embedded systems. Additionally, dirs are only open
for reading, and corruption will probably just cause the dir iteration
to terminate. If needed, correct handling of open directories can be
added later.
2017-05-08 00:48:28 -05:00
Christopher Haster
ba8afb9d92 Added support for full seek operations
A rather involved upgrade for both files and directories, seek and
related functions are now completely supported:
- lfs_file_seek
- lfs_file_tell
- lfs_file_rewind
- lfs_file_size
- lfs_dir_seek
- lfs_dir_tell
- lfs_dir_rewind

This change also highlighted the concern that lfs_off_t is unsigned,
whereas off_t is traditionally signed. Unfortunately, lfs_off_t is
already used intensively through the codebase, so in focusing on
moving forward and avoiding getting bogged down by details, I'm going to
keep it as is and use the signed type lfs_soff_t where necessary.
2017-04-23 02:06:48 -05:00
Christopher Haster
3b9d6630c8 Restructured directory code
After quite a bit of prototyping, settled on the following functions:
- lfs_dir_alloc  - create a new dir
- lfs_dir_fetch  - load and check a dir pair from disk
- lfs_dir_commit - save a dir pair to disk
- lfs_dir_shift  - shrink a dir pair to disk
- lfs_dir_append - add a dir entry, creating dirs if needed
- lfs_dir_remove - remove a dir entry, dropping dirs if needed

Additionally, followed through with a few other tweaks
2017-04-18 01:44:01 -05:00
Christopher Haster
1f13006e36 Added dir navigation without needing parent entries
This should be the last step to removing the need for
parent entries.

Parent entries cause all sort of problems with atomic
directory updates, especially related to moving/deleting
directories.

I couldn't figure out a parser for '..' entries without,
O(n^2) runtime, a stack, or modifying the path itself.
Since the goal is constant memory consumption, I went
with the O(n^2) runtime solution, but this may need to
be optimized later.
2017-04-18 01:44:01 -05:00
Christopher Haster
c25c893219 Moved to brute-force deorphan without parent pointers
Removing the dependency to the parent pointer solves
many issues with non-atomic updates of children's
parent pointers with respect to any move operations.

However, this comes with an embarrassingly terrible
runtime as the only other option is to exhaustively
check every dir entry to find a child's parent.

Fortunately, deorphaning should be a relatively rare
operation.
2017-04-18 01:44:01 -05:00
Christopher Haster
8a674524fc Added full dir list and rudimentary block allocator
In writing the initial allocator, I ran into the rather
difficult problem of trying to iterate through the entire
filesystem cheaply and with only constant memory consumption
(which prohibits recursive functions).

The solution was to simply thread all directory blocks onto a
massive linked-list that spans the entire filesystem.

With the linked-list it was easy to create a traverse function
for all blocks in use on the filesystem (which has potential
for other utility), and add the rudimentary block allocator
using a bit-vector.

While the linked-list may add complexity (especially where
needing to maintain atomic operations), the linked-list helps
simplify what is currently the most expensive operation in
the filesystem, with no cost to space (the linked-list can
reuse the pointers used for chained directory blocks).
2017-04-18 01:44:01 -05:00
Christopher Haster
a711675607 Added dir tests, test fixes, config 2017-03-25 19:23:30 -05:00
Christopher Haster
afa4ad8254 Added a rudimentary test framework
Tests can be found in 'tests/test_blah.sh'
Tests can be run with 'make test'
2017-03-25 19:23:30 -05:00
Christopher Haster
c28a280c8d Adopted ctz skip-list structure earlier than expected
The primary data structure backing the little fs was planned
to be a little ctz based skip-list for O(logn) lookup and
O(1) append.

Was initially planning to start with a simple linked list of
index blocks, but was having trouble implementing the free-list
on top of the structure. Went ahead and adopted the skip-list
structure since it may have actually been easier.
2017-02-26 21:00:39 -06:00
Christopher Haster
02156cb47d Initial commit of block device interface and emulated block device 2017-02-25 14:31:14 -06:00