Added filesystem-level info flags to lfsr_fs_stat

Thinking again of use cases, lfsr_fs_gc provides the perfect API to call
in the background to perform any pending filesystem work. But what if
there's no work to be done? Sure we could just spin forever, but that's
a waste. Especially on devices that can turn on sleep modes to save
power.

To help with this, this commit adds a set of flags to struct lfs_fsinfo
that signals when lfsr_fs_gc can accomplish work:

  LFS_I_INCONSISTENT     = 0x01, // Filesystem needs mkconsistent to write
  LFS_I_NEEDSUPGRADE*    = 0x02, // Filesystem needs an upgrade to write
  LFS_I_CANLOOKAHEAD     = 0x04, // Lookahead buffer is not full
  LFS_I_CANPREERASE+     = 0x08, // Pre-erase buffer is not full
  LFS_I_UNCOMPACTED      = 0x10, // Filesystem may have uncompacted metadata
  LFS_I_NEEDSREPAIRMETA+ = 0x20, // Filesystem contains damaged metadata
  LFS_I_NEEDSREPAIRDATA+ = 0x40, // Filesystem contains damaged data

  *Hypothetical
  +Planned

This flags field also provides a useful place internally to store other
filesystem-related flags, currently LFS_F_ORPHANS, though this may be
expanded in the future.

These flags allow users to know exactly what work can/needs to be done
for the filesystem to make progress:

- LFS_I_INCONSISTENT => LFS_GC_MKCONSISTENT or lfsr_fs_mkconsistent
- LFS_I_CANLOOKAHEAD => LFS_GC_LOOKAHEAD

- LFS_I_UNCOMPACTED => LFS_GC_COMPACT

  The one is new!

  If we complete a compaction-traversal without any mutation, we know
  all mdirs/btree nodes have been compacted and future traversals won't
  accomplish anything. Of course, we need to clear this bit on
  filesystem mutation.

  Right now we just pessimistically assume the filesystem is uncompacted
  during mount, but in theory we can also figure this out during our
  initial mount traversal.

- LFS_GC_CKMETA/CKDATA?

  LFS_GC_CKMETA and LFS_GC_CKDATA are a bit trickier. In theory,
  LFS_GC_CKMETA/CKDATA will always accomplish something, since time is
  the only ingredient necessary to introduce bit errors.

  So there isn't really a reasonable flag here. It's entirely up to the
  user to decide when to do an LFS_GC_CKMETA/CKDATA traversal.

Code changes:

           code          stack
  before: 35740           2672
  after:  35880 (+0.4%)   2672 (+0.0%)
This commit is contained in:
Christopher Haster
2024-07-14 19:27:27 -05:00
parent d18633e4e8
commit 0a3cb2dd3a
5 changed files with 1594 additions and 101 deletions
+22 -13
View File
@@ -125,6 +125,16 @@ enum lfs_type {
LFS_TYPE_TRAVERSAL = 9,
};
// Block types
enum lfs_btype {
LFS_BTYPE_MDIR = 1,
LFS_BTYPE_BTREE = 2,
LFS_BTYPE_DATA = 3,
// TODO
// LFS_BTYPE_PARITY = 4,
// LFS_BTYPE_BAD = 5,
};
// File open flags
enum lfs_open_flags {
// open flags
@@ -155,14 +165,15 @@ enum lfs_whence_flags {
LFS_SEEK_END = 2, // Seek relative to the end of the file
};
// Block types
enum lfs_btype {
LFS_BTYPE_MDIR = 1,
LFS_BTYPE_BTREE = 2,
LFS_BTYPE_DATA = 3,
// TODO
// LFS_BTYPE_PARITY = 4,
// LFS_BTYPE_BAD = 5,
// Filesystem info flags
enum lfs_fsinfo_flags {
// state flags
LFS_I_INCONSISTENT = 0x01, // Filesystem needs mkconsistent to write
LFS_I_CANLOOKAHEAD = 0x04, // Lookahead buffer is not full
LFS_I_UNCOMPACTED = 0x10, // Filesystem may have uncompacted metadata
// internally used flags
LFS_F_ORPHANS = 0x80, // Filesystem may have untracked orphans
};
// Traversal flags
@@ -391,7 +402,8 @@ struct lfs_info {
// Filesystem info structure
struct lfs_fsinfo {
// TODO should we add rcompat/wcompat flags here?
// Filesystem flags
uint8_t flags;
// Size of a logical block in bytes.
lfs_size_t block_size;
@@ -713,10 +725,7 @@ typedef struct lfs {
lfs_size_t name_limit;
lfs_off_t file_limit;
// TODO we should put this flag somewhere, should lfs_t have a general
// purpose flags field? this has been useful for lfsr_file_t
bool hasorphans;
uint8_t flags;
int8_t recycle_bits;
uint8_t attr_estimate;
uint8_t mdir_bits;