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