Made lfsr_shrub_t its own struct

This now properly encodes the different eoff/estimate field usage
between the two types.

In theory this could save some RAM, but we don't actually allocate
lfsr_shrub_t anywhere it's not unioned with lfsr_btree_t, so:

           code          stack
  before: 33976           2824
  after:  33976 (+0.0%)   2824 (+0.0%)
This commit is contained in:
Christopher Haster
2024-05-02 02:12:38 -05:00
parent 45a4e9ffb4
commit 0ed38211bf
2 changed files with 45 additions and 24 deletions
+35 -16
View File
@@ -3960,7 +3960,8 @@ static int lfsr_rbyd_appendshrub(lfs_t *lfs, lfsr_rbyd_t *rbyd,
rbyd->trunk |= LFSR_RBYD_ISSHRUB; rbyd->trunk |= LFSR_RBYD_ISSHRUB;
// compact our shrub // compact our shrub
int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd, -1, -1, shrub); int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd, -1, -1,
(const lfsr_rbyd_t*)shrub);
if (err) { if (err) {
return err; return err;
} }
@@ -5219,10 +5220,25 @@ static int lfsr_sprout_compact(lfs_t *lfs, const lfsr_rbyd_t *rbyd_,
// shrub things // shrub things
// helper functions
static inline bool lfsr_shrub_isshrub(const lfsr_shrub_t *shrub) {
return lfsr_rbyd_isshrub((const lfsr_rbyd_t*)shrub);
}
static inline lfs_size_t lfsr_shrub_trunk(const lfsr_shrub_t *shrub) {
return lfsr_rbyd_trunk((const lfsr_rbyd_t*)shrub);
}
static inline bool lfsr_shrub_hastrunk(const lfsr_shrub_t *shrub) {
return lfsr_rbyd_trunk((const lfsr_rbyd_t*)shrub) != 0;
}
static inline int lfsr_shrub_cmp( static inline int lfsr_shrub_cmp(
const lfsr_shrub_t *a, const lfsr_shrub_t *a,
const lfsr_shrub_t *b) { const lfsr_shrub_t *b) {
return lfsr_rbyd_cmp(a, b); return lfsr_rbyd_cmp(
(const lfsr_rbyd_t*)a,
(const lfsr_rbyd_t*)b);
} }
// shrub on-disk encoding // shrub on-disk encoding
@@ -5242,11 +5258,11 @@ static inline int lfsr_shrub_cmp(
static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub, static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub,
uint8_t buffer[static LFSR_SHRUB_DSIZE]) { uint8_t buffer[static LFSR_SHRUB_DSIZE]) {
// shrub trunks should never be null // shrub trunks should never be null
LFS_ASSERT(lfsr_rbyd_trunk(shrub) != 0); LFS_ASSERT(lfsr_shrub_trunk(shrub) != 0);
// weight should not exceed 31-bits // weight should not exceed 31-bits
LFS_ASSERT(shrub->weight <= 0x7fffffff); LFS_ASSERT(shrub->weight <= 0x7fffffff);
// trunk should not exceed 28-bits // trunk should not exceed 28-bits
LFS_ASSERT(lfsr_rbyd_trunk(shrub) <= 0x0fffffff); LFS_ASSERT(lfsr_shrub_trunk(shrub) <= 0x0fffffff);
lfs_ssize_t d = 0; lfs_ssize_t d = 0;
// just write the trunk and weight, the rest of the rbyd is contextual // just write the trunk and weight, the rest of the rbyd is contextual
@@ -5254,7 +5270,8 @@ static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub,
LFS_ASSERT(d_ >= 0); LFS_ASSERT(d_ >= 0);
d += d_; d += d_;
d_ = lfs_toleb128(lfsr_rbyd_trunk(shrub), &buffer[d], 4); d_ = lfs_toleb128(lfsr_shrub_trunk(shrub),
&buffer[d], 4);
LFS_ASSERT(d_ >= 0); LFS_ASSERT(d_ >= 0);
d += d_; d += d_;
@@ -5267,7 +5284,7 @@ static int lfsr_data_readshrub(lfs_t *lfs, lfsr_data_t *data,
// copy the mdir block // copy the mdir block
shrub->blocks[0] = mdir->rbyd.blocks[0]; shrub->blocks[0] = mdir->rbyd.blocks[0];
// force estimate recalculation if we write to this shrub // force estimate recalculation if we write to this shrub
shrub->eoff = -1; shrub->estimate = -1;
int err = lfsr_data_readleb128(lfs, data, &shrub->weight); int err = lfsr_data_readleb128(lfs, data, &shrub->weight);
if (err) { if (err) {
@@ -5279,7 +5296,7 @@ static int lfsr_data_readshrub(lfs_t *lfs, lfsr_data_t *data,
return err; return err;
} }
// shrub trunks should never be null // shrub trunks should never be null
LFS_ASSERT(lfsr_rbyd_hastrunk(shrub)); LFS_ASSERT(lfsr_shrub_hastrunk(shrub));
// set the shrub bit in our trunk // set the shrub bit in our trunk
shrub->trunk |= LFSR_RBYD_ISSHRUB; shrub->trunk |= LFSR_RBYD_ISSHRUB;
@@ -5303,7 +5320,7 @@ static lfs_ssize_t lfsr_shrub_estimate(lfs_t *lfs,
return 0; return 0;
} }
return lfsr_rbyd_estimate(lfs, shrub, -1, -1, return lfsr_rbyd_estimate(lfs, (const lfsr_rbyd_t*)shrub, -1, -1,
NULL); NULL);
} }
@@ -5380,6 +5397,7 @@ static int lfsr_shrub_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
} }
/// Metadata pair stuff /// /// Metadata pair stuff ///
// metadata-id things // metadata-id things
@@ -10053,7 +10071,7 @@ static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
// bshrub/btree? // bshrub/btree?
} else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) { } else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) {
int err = lfsr_btree_traverse_(lfs, &file->bshrub.u.bshrub, t, int err = lfsr_btree_traverse_(lfs, &file->bshrub.u.btree, t,
bid_, tinfo_); bid_, tinfo_);
if (err) { if (err) {
return err; return err;
@@ -10206,8 +10224,8 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file, lfsr_bid_t bid,
// does our estimate exceed our shrub_size? need to recalculate an // does our estimate exceed our shrub_size? need to recalculate an
// accurate estimate // accurate estimate
lfs_ssize_t estimate = (alloc) lfs_ssize_t estimate = (alloc)
? -1 ? (lfs_size_t)-1
: file->bshrub.u.bshrub.eoff; : file->bshrub.u.bshrub.estimate;
// this double condition avoids overflow issues // this double condition avoids overflow issues
if ((lfs_size_t)estimate > lfs->cfg->shrub_size if ((lfs_size_t)estimate > lfs->cfg->shrub_size
|| estimate + commit_estimate > lfs->cfg->shrub_size) { || estimate + commit_estimate > lfs->cfg->shrub_size) {
@@ -10251,15 +10269,15 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file, lfsr_bid_t bid,
if (file_->m.type == LFS_TYPE_REG if (file_->m.type == LFS_TYPE_REG
&& file_->m.mdir.mid == file->m.mdir.mid && file_->m.mdir.mid == file->m.mdir.mid
&& lfsr_bshrub_isbshrub(&file_->m.mdir, &file_->bshrub)) { && lfsr_bshrub_isbshrub(&file_->m.mdir, &file_->bshrub)) {
file_->bshrub.u.bshrub.eoff = estimate; file_->bshrub.u.bshrub.estimate = estimate;
} }
} }
LFS_ASSERT(file->bshrub.u.bshrub.eoff = (lfs_size_t)estimate); LFS_ASSERT(file->bshrub.u.bshrub.estimate == (lfs_size_t)estimate);
return 0; return 0;
} }
LFS_ASSERT(lfsr_rbyd_hastrunk(&file->bshrub.u.bshrub)); LFS_ASSERT(lfsr_shrub_hastrunk(&file->bshrub.u.bshrub));
return 0; return 0;
evict:; evict:;
@@ -10272,7 +10290,8 @@ evict:;
// note this may be a new root // note this may be a new root
if (!alloc) { if (!alloc) {
err = lfsr_rbyd_compact(lfs, &rbyd, -1, -1, &file->bshrub.u.bshrub); err = lfsr_rbyd_compact(lfs, &rbyd, -1, -1,
&file->bshrub.u.btree);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
@@ -10339,7 +10358,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
file->bshrub.u.bshrub.trunk = LFSR_RBYD_ISSHRUB | 0; file->bshrub.u.bshrub.trunk = LFSR_RBYD_ISSHRUB | 0;
file->bshrub.u.bshrub.weight = 0; file->bshrub.u.bshrub.weight = 0;
// force estimate recalculation // force estimate recalculation
file->bshrub.u.bshrub.eoff = -1; file->bshrub.u.bshrub.estimate = -1;
if (attr_count > 0) { if (attr_count > 0) {
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t)); LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
+10 -8
View File
@@ -355,6 +355,16 @@ typedef struct lfsr_rbyd {
// a btree is just the root rbyd // a btree is just the root rbyd
typedef lfsr_rbyd_t lfsr_btree_t; typedef lfsr_rbyd_t lfsr_btree_t;
// a shrub is a secondary trunk in an mdir
typedef struct {
// this mostly lines up with lfsr_rbyd_t
lfsr_rid_t weight;
lfs_block_t blocks[2];
lfs_ssize_t trunk;
// except for shrub estimate, which takes the place of eoff, etc
lfs_size_t estimate;
} lfsr_shrub_t;
typedef struct lfsr_mptr { typedef struct lfsr_mptr {
lfs_block_t blocks[2]; lfs_block_t blocks[2];
} lfsr_mptr_t; } lfsr_mptr_t;
@@ -464,14 +474,6 @@ typedef struct lfsr_bptr {
uint32_t cksum; uint32_t cksum;
} lfsr_bptr_t; } lfsr_bptr_t;
// a shrub is a secondary trunk in an mdir
//
// note:
// - sign(trunk)=1 => shrub
// - we shove our shrub estimate into rbyd.eoff, C makes it too annoying
// to union another field
typedef lfsr_rbyd_t lfsr_shrub_t;
// the lfsr_bshrub_t struct represents the on-disk component of a file // the lfsr_bshrub_t struct represents the on-disk component of a file
typedef struct lfsr_bshrub { typedef struct lfsr_bshrub {
// navigating this union is a bit tricky, and relies on the related // navigating this union is a bit tricky, and relies on the related