Fixed block crystallization not triggering on boundary underflow

It's expected for our crystal boundary calculation to underflow, but
when checking for holes we were using the wrong signed/unsigned
comparison, so lfsr_file_carve thought there was a hole when there
wasn't:

  -crs   pos                              pos    -crs
  .-------|       <-- this lookup    ------|       .--
  '---.   | +crs                     --.   | +crs  '--
  .   |---|---.       ended up         |---|---.   .
  .   v   v   v       looking   -->    v   v   v   .
  .   .---.           like this        .---.       .
  .   |dat|                            |dat|       .
  .   '---'                            '---'       .
  .   0   .   n                        0   .   n   .

  '---.---'                                '---.---'
   no hole                               clearly a hole

This led to unoptimal block compaction and weird block alignment for
even relatively simple files.

The crystallization threshold is only a heuristic so this didn't exactly
break anything, but it was causing block-aligned files to waste a bit of
of space which wasn't great.

---

To hopefully protect against this in the future, I've added a couple
*_litmus tests to check that at least some simple block-aligned files
end up with the correct number of branches/blocks. This should at least
give us some confidence our crystallization algorithm is working as
intended.

We don't have all that many tests (any?) over the exact topology of
files, mainly because of how many heuristics are involved. Maybe we
should look into adding a couple more.

No code changes:

           code          stack
  before: 36396           2664
  after:  36396 (+0.0%)   2664 (+0.0%)
This commit is contained in:
Christopher Haster
2024-07-29 13:12:58 -05:00
parent 0ab0406d53
commit 7fe6e2ce45
2 changed files with 421 additions and 37 deletions
+7 -5
View File
@@ -10665,12 +10665,14 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
return err;
}
// if left crystal neighbor is a fragment and there is no hole
// between our own crystal and our neighbor, include as a part
// of our crystal
// if left crystal neighbor is a fragment and there is no
// obvious hole between our own crystal and our neighbor,
// include as a part of our crystal
if (tag == LFSR_TAG_DATA
&& bid-(weight-1)+lfsr_data_size(bptr.data)
>= pos - (lfs->cfg->crystal_thresh-1)) {
// hole? holes can be quite large and shouldn't trigger
// crystallization
&& (lfs_soff_t)(bid-(weight-1)+lfsr_data_size(bptr.data))
>= (lfs_soff_t)(pos - (lfs->cfg->crystal_thresh-1))) {
crystal_start = bid-(weight-1);
// otherwise our neighbor determines our crystal boundary