Simplified lfsr_bshrub_t representation
Now that we don't use bmoss or bsprouts anymore, we can drop the
LFSR_BSHRUB_ISNULLORBMOSSORBPTR flag and simplify our lfsr_bshrub_t
struct quite a bit.
However, we do still need a bnull representation, which is surprisingly
tricky... And annoying...
Current solution: Bnulls are bshrubs with weight=0. This works, but
unfortunately does mean we need to update bnull blocks on mdir
relocation/compaction, and risks bnull blocks falling out-of-sync, which
is a really weird thing to worry about:
bnull: bshrub: btree:
.---+---+---+---. .. .---+---+---+---. .. .---+---+---+---.
| weight=0 | | weight>0 | | weight |
+---+---+---+---+ +---+---+---+---+ +---+---+---+---+
| block=mdir | | block=mdir | | block!=mdir |
+---+---+---+---+ .. +---+---+---+---+ +---+---+---+---+
| (unused) | | (unused) | | (unused) |
+ + +---+---+---+---+ +---+---+---+---+
| | | trunk | | trunk |
+ + +---+---+---+---+ .. +---+---+---+---+
| | | estimate | | eoff |
+ + +---+---+---+---+ +---+---+---+---+
| | | (unused) | | cksum |
'---+---+---+---' '---+---+---+---' '---+---+---+---'
Note we can't just assume all weight=0 files are bnulls, or else we
won't use erased-state in empty btree roots. This risks thrashing in
files oscillating around weight=0.
Technically, weight=0 bshrubs _are_ slightly different than bnulls (
bshrubs point to a null tag, while bnulls simply have no tree), but
unlike btrees, there's no reason to keep weight=0 bshrubs around. Any
bshrub erased-state can still be used by the mdir.
This change also makes LFS_O_TRUNC and lfsr_file_truncate/fruncate
behave slightly differently, with LFS_O_TRUNC unconditionally reverting
to a bnull, while lfsr_file_truncate/fruncate tries to keep the btree
root around. This may be worth revisiting...
---
Despite the awkward encoding, this simplification still ends up saving a
nice bit of code and stack:
code stack ctx
before: 36668 2616 640
after: 36460 (-0.6%) 2608 (-0.3%) 640 (+0.0%)
This commit is contained in:
@@ -694,20 +694,15 @@ typedef struct lfsr_bptr {
|
||||
} lfsr_bptr_t;
|
||||
|
||||
// the lfsr_bshrub_t struct represents the on-disk component of a file
|
||||
//
|
||||
// navigating this union is a bit tricky, and relies on the related
|
||||
// mdir block:
|
||||
// block==mdir.block, weight==0 => bnull
|
||||
// block==mdir.block, weight!=0 => bshrub
|
||||
// block!=mdir.block => btree
|
||||
typedef struct lfsr_bshrub {
|
||||
// navigating this union is a bit tricky, and relies on the related
|
||||
// mdir's block:
|
||||
//
|
||||
// sign(size)=1, data.size==0 => bnull
|
||||
// sign(size)=1, data.block==mdir.block => bmoss
|
||||
// sign(size)=1, data.block!=mdir.block => bptr
|
||||
// sign(size)=0, data.block==mdir.block => bshrub
|
||||
// sign(size)=0, data.block!=mdir.block => btree
|
||||
//
|
||||
union {
|
||||
lfs_off_t size;
|
||||
lfsr_data_t bmoss;
|
||||
lfsr_bptr_t bsprout;
|
||||
lfs_size_t weight;
|
||||
lfsr_shrub_t bshrub;
|
||||
lfsr_btree_t btree;
|
||||
} u;
|
||||
|
||||
Reference in New Issue
Block a user