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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user