Dropped fragmenting blocks > 1 fragment

So we now keep blocks around until they can be replaced with a single
fragment. This is simpler, cheaper, and reduces the number of commits
needed to graft (though note arbitrary range removals still keep this
unbounded).

---

So, this is a delicate tradeoff.

On one hand, not fully fragmenting blocks risks keeping around bptrs
containing very little data, depending on fragment_size.

On the other hand:

- It's expensive, and disk utilization during random _deletes_ is not
  the biggest of concerns.

  Note our crystallization algorithm should still clean up partial
  blocks _eventually_, so this doesn't really impact random writes.
  The main concerns are lfs3_file_truncate/fruncate, and in the future
  collapserange/punchhole.

- Fragmenting bptrs introduces more commits, which have their own
  prog/erase cost, and it's unclear how this impacts logging operations.

  There's no point in fragmenting blocks at the head of a log if we're
  going to fruncate them eventually.

I figure lets err on minimizing complexity/code size for now, and if
this turns out to be a mistake, we can always revert or introduce
fragmenting >1 fragment blocks as an optional feature in the future.

---

Saves a big chunk of code, stack, and even some ctx (no more
fragment_thresh):

           code          stack          ctx
  before: 37504           2448          656
  after:  37024 (-1.3%)   2416 (-1.3%)  652 (-0.6%)
This commit is contained in:
Christopher Haster
2025-07-03 19:15:10 -05:00
parent 3f2e8b53c5
commit b700c8c819
5 changed files with 11 additions and 100 deletions
+5 -5
View File
@@ -2003,12 +2003,12 @@ code = '''
lfs3_unmount(&lfs3) => 0;
'''
# test that carving below fragment_thresh breaks blocks into fragments
# test that carving to fragment_size breaks blocks into fragments
[cases.test_fwrite_truncate_litmus_fragment]
defines.N = [1, 2, 8]
defines.SIZE = 'N*BLOCK_SIZE'
# 1 vs multiple fragments are implemented slightly differently
defines.FRAGMENTS = [1, 2, 3]
# currently we only support fragmenting blocks <= 1 fragment
defines.FRAGMENTS = [1]
defines.TSIZE = 'FRAGMENTS*FRAGMENT_SIZE'
defines.SYNC = [false, true]
in = 'lfs3.c'
@@ -2159,8 +2159,8 @@ code = '''
[cases.test_fwrite_fruncate_litmus_fragment]
defines.N = [1, 2, 8]
defines.SIZE = 'N*BLOCK_SIZE'
# 1 vs multiple fragments are implemented slightly differently
defines.FRAGMENTS = [1, 2, 3]
# currently we only support fragmenting blocks <= 1 fragment
defines.FRAGMENTS = [1]
defines.TSIZE = 'FRAGMENTS*FRAGMENT_SIZE'
defines.SYNC = [false, true]
in = 'lfs3.c'