Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] transactional filesystem #61

Closed
wants to merge 1 commit into from
Closed

Conversation

japaric
Copy link
Collaborator

@japaric japaric commented Apr 7, 2020

this PR adds a transactional::Fs newtype over the existing LittleFs API.

In "transactional" mode, the filesystem only exposes read-only fs operations (like read_dir and opening, not creating, a file). File writes are also allowed in this mode but they'll be cached to memory. The Fs.sync method ends the transactional mode by consuming the newtype and returning the original LittleFs value; Fs.sync will commit all pending file writes to the eMMC (*)

(*) fine print synchronizing all the files is NOT guaranteed to be atomic: the files will be synchronized to disk one by one. If power is lost during this operation some files may end up updated while others not -- littlefs ensures the files won't be corrupted in this scenario.

Although neither littlefs or the eMMC provides a way to atomically update a group of files (as these may live in different eMMC sectors), it should still be possible to implement such functionality on top of transactional::Fs. For instance something like the code below would check whether a group of files has been atomically updated or not.

// omitted creating files a.txt, b.txt, c.txt and .lock outside the transactional mode

// we are about to modify the files a, b and c so indicate that state in `.lock`
File::create(&fs, &mut fa1, ".lock")?.write(b"WIP")?.close()?;

let tfs = fs.transactional::<consts::U4>()?;
let a = tFile::create(&tfs, &mut fa2, "a.txt")
// repeat for b.txt, c.txt and .lock
// do stuff with files a, b and c

// as the last step of `Fs.sync` put the `.lock` file in "atomic update succeeded"
lock.write(b"DONE")?;

// sync files in this order: a, b, c and lock
tfs.sync()?;

Before reading files a, b or c one would check if .lock contains "WIP", which means the atomic file group update failed (e.g. because power was lost before .lock was updated in the last line of the previous snippet), or "DONE", which means the atomic file group update succeeded.

With checked atomic file group updates one could implement a revision, or backup, system for a group of files.

TODO

  • test fs API
  • remove print statement from storage.rs
  • document that transactional::File.write can fail due to the file cache being too small

@japaric
Copy link
Collaborator Author

japaric commented Apr 17, 2020

Closing this in favor of #67

@japaric japaric closed this Apr 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant