littlefs-project / littlefs

A little fail-safe filesystem designed for microcontrollers
BSD 3-Clause "New" or "Revised" License
5.23k stars 801 forks source link

How practical is union mounts in littlefs? E.g. UnionFS in linux #1006

Open mofosyne opened 4 months ago

mofosyne commented 4 months ago

I've seen in openWRT where they use UnionFS plus SquashFS to provide a read only fallback/default file system which will then have user modification on top.

I know the compression part is not practical in https://github.com/littlefs-project/littlefs/issues/672, but hopefully the same won't be true for having a union mount feature.

There is two different approach... you could simply replace on a per file level... or if you have a sparse encoding of the upper layer... a byte replacement of changed areas of the file.

This would allow for an easier/faster factory reset. Also plus you could have a setup where you would have one mount in the MCU (likely read only) then the user files overlay in the main external flash. (Or you would have both in one flash but partitioned)

geky commented 2 months ago

Hi @mofosyne, thanks for creating and issue, sorry about the late response.

This is an interesting question.

672 will probable be worth revisiting in the future, but it's just low priority right now.

Reading up on UnionFS, it seems like most of the complexity comes from mapping multiple different filesystems. If you only have one filesystem you should be able to map things at the block layer, which would be quite a bit simpler.

Mapping blocks would also provide a bit of the sparsity you described. Mapping bytes risks too much metadata building up to describe the mapping, and is some of the reason filesystems describe things in blocks/sectors/pages/chunks/fragments/ohmy.

Two ways this could be done:

  1. Adding constraints to littlefs's block allocator
  2. Mapping blocks in the block device

I've been toying around with 1., since it would also provide some interesting use cases such as RAID. You could imaging telling littlefs half the address space is readonly and half is writeable, and littlefs allocating from the writable region to satisfy new file writes.

But while this would be powerful, it would also be really complicated to express/implement, and I'm not really sure what the API would look like. Like compression, this feature will probably be low priority for a while.

As for 2., this can actually be implemented right now, but depends on your application and if you have a place to store the mapping. Mapping RAM-over-ROM would be quite easy since you could keep the mapping in RAM, but for persistent storage, like Flash-over-ROM, it would get a bit more complicated. Maybe you could prefix each block in Flash with its address and rebuild the in-RAM block mapping during mount?