bmap: Simplified bmap configs, reduced to one LFS3_F_GBMAP flag

TLDR: This drops the idea of different bmap strategies/modes, and sorts
out most of the compile-time/runtime conditional bmap interactions.

---

Motivation: Benchmarking (at least up to the 32-bit word limit) has
shown the bmap will unlikely be a significant bottleneck, even on large
disks. The largest disks tend to be NAND, and NAND's ridiculous block
size limits pressure on block allocation.

There are still concerns for areas I haven't measured yet:

- SD/eMMC/FTL - Small blocks, so more pressure on block allocation. In
  theory the logical block size can be artificially increased, but this
  comes with a granularity tradeoff.

- I've only measured throughput, latency is a whole other story.

  However, users have reported lfs3_fs_gc is useful for mitigating this,
  so maybe latency is less of a concern now?

But while there may still be room for improvement via alternative bmap
strategies, the risk a concerning amount of complexity. Yes,
configuration gets more complicated, but the real issue is any bmap
strategies that try to track _deallocations_ (the original idea being
treediffing) risk falling leaking blocks if all cases aren't covered.

The current "bmap cache" strategy strikes a really nice balance where it
reduces _amortized_ block allocation -> ~O(log n) without RAM, while
retaining the safe, bug-resistant, single-source-of-truth properties
that come with lookahead-based allocation.

---

So, long story short, dropping other strategies, and now the presence of
the bmap is a boolean flag.

This is also the first format-specific flag:

- Define LFS3_BMAP to enable the bmap logic, but note by default the
  bmap will still not be used.

- Define LFS3_YES_BMAP to force the bmap to be used.

- With LFS3_BMAP, passing LFS3_F_GBMAP to lfs3_format will include the
  on-disk block-map.

- No flag is needed during mount, the presence of the bmap is determined
  by the on-disk wcompat flags (LFS3_WCOMPAT_GBMAP). This also prevents
  rw mounting if the bmap is not supported, but rdonly mounting is
  allowed.

- Users can check if the bmap is in use via lfs3_fs_stat, which reports
  LFS3_I_GBMAP in the flags field.

There's still some missing pieces, but these will be a bit more
involved:

- lfs3_fs_grow needs to be made bmap aware!

- We probably want something like lfs3_fs_mkgbmap and lfs3_fs_rmgbmap to
  allow converting between bmap backed/not-backed filesystem images.

Code changes minimal:

                code          stack          ctx
  before:      37172           2352          684
  after:       37172 (+0.0%)   2352 (+0.0%)  684 (+0.0%)

                code          stack          ctx
  bmap before: 38844           2456          800
  bmap after:  38852 (+0.0%)   2456 (+0.0%)  800 (+0.0%)
This commit is contained in:
Christopher Haster
2025-10-06 13:06:38 -05:00
parent 38cfa5cc5e
commit 9d322741ca
8 changed files with 374 additions and 449 deletions
+10 -23
View File
@@ -47,10 +47,9 @@
#ifndef LFS3_GC
#define LFS3_GC
#endif
// TODO how interact with bmap?
// #ifndef LFS3_BMAP
// #define LFS3_BMAP
// #endif
#ifndef LFS3_BMAP
#define LFS3_BMAP
#endif
#endif
// LFS3_YES_* variants imply the relevant LFS3_* macro
@@ -88,25 +87,6 @@
#define LFS3_BMAP
#endif
// LFS3_BMAP mappings
//
// TODO eventually allow runtime flags
//
// LFS3_YES_BMAP* => LFS3_BMAP
#if defined(LFS3_YES_BMAPCACHE) \
|| defined(LFS3_YES_BMAPVFR) \
|| defined(LFS3_YES_BMAPIFR)
#define LFS3_BMAP
#endif
// TODO figure out the best default bmap mode
// if LFS3_BMAP but no algorithm defined, default to LFS3_YES_BMAPCACHE
#if defined(LFS3_BMAP) \
&& !defined(LFS3_BMAPCACHE) \
&& !defined(LFS3_BMAPVFR) \
&& !defined(LFS3_BMAPIFR)
#define LFS3_YES_BMAPCACHE
#endif
// LFS3_NO_LOG disables all logging macros
#ifdef LFS3_NO_LOG
#ifndef LFS3_NO_DEBUG
@@ -289,6 +269,13 @@
#define LFS3_IFDEF_BMAP(a, b) (b)
#endif
// TODO other LFS3_IFDEF_YES_* macros?
#ifdef LFS3_YES_BMAP
#define LFS3_IFDEF_YES_BMAP(a, b) (a)
#else
#define LFS3_IFDEF_YES_BMAP(a, b) (b)
#endif
// Some function attributes, no way around these