Deduped bshrub/btree fetching
This adds lfs3_bshrub_fetch to better deduplicate the common pattern of
fetching either a bshrub or btree based on tag.
The API ends up a bit funny because of how mdirs are attached to
specific mids. All we need is the relevant mdir object, and we can do a
single masked mdir lookup to find any bshrubs/btrees.
Saves a little bit of code:
code stack ctx
before: 37920 2424 636
after: 37896 (-0.1%) 2424 (+0.0%) 636 (+0.0%)
Also flipped around some lfs3_data_read* parameters to better match
common tag+weight+data ordering in lfs3_*_lookup functions.
This commit is contained in:
@@ -5039,7 +5039,7 @@ static lfs3_data_t lfs3_data_frombranch(const lfs3_rbyd_t *branch,
|
||||
|
||||
#ifndef LFS3_2BONLY
|
||||
static int lfs3_data_readbranch(lfs3_t *lfs3,
|
||||
lfs3_data_t *data, lfs3_bid_t weight,
|
||||
lfs3_bid_t weight, lfs3_data_t *data,
|
||||
lfs3_rbyd_t *branch) {
|
||||
// setting eoff to 0 here will trigger asserts if we try to append
|
||||
// without fetching first
|
||||
@@ -5108,7 +5108,7 @@ static int lfs3_data_fetchbranch(lfs3_t *lfs3,
|
||||
lfs3_data_t *data, lfs3_bid_t weight,
|
||||
lfs3_rbyd_t *branch) {
|
||||
// decode branch and fetch
|
||||
int err = lfs3_data_readbranch(lfs3, data, weight,
|
||||
int err = lfs3_data_readbranch(lfs3, weight, data,
|
||||
branch);
|
||||
if (err) {
|
||||
return err;
|
||||
@@ -5154,7 +5154,7 @@ static int lfs3_data_readbtree(lfs3_t *lfs3, lfs3_data_t *data,
|
||||
return err;
|
||||
}
|
||||
|
||||
err = lfs3_data_readbranch(lfs3, data, weight, btree);
|
||||
err = lfs3_data_readbranch(lfs3, weight, data, btree);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -5361,7 +5361,7 @@ static int lfs3_btree_parent(lfs3_t *lfs3, const lfs3_btree_t *btree,
|
||||
|
||||
// fetch the next branch
|
||||
lfs3_rbyd_t child_;
|
||||
err = lfs3_data_readbranch(lfs3, &data__, weight__, &child_);
|
||||
err = lfs3_data_readbranch(lfs3, weight__, &data__, &child_);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -6400,8 +6400,8 @@ static lfs3_data_t lfs3_data_fromshrub(const lfs3_shrub_t *shrub,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lfs3_data_readshrub(lfs3_t *lfs3, lfs3_data_t *data,
|
||||
const lfs3_mdir_t *mdir,
|
||||
static int lfs3_data_readshrub(lfs3_t *lfs3,
|
||||
const lfs3_mdir_t *mdir, lfs3_data_t *data,
|
||||
lfs3_shrub_t *shrub) {
|
||||
// copy the mdir block
|
||||
shrub->blocks[0] = mdir->rbyd.blocks[0];
|
||||
@@ -6564,11 +6564,58 @@ static inline int lfs3_bshrub_cmp(
|
||||
return lfs3_rbyd_cmp(&a->shrub, &b->shrub);
|
||||
}
|
||||
|
||||
// needed in lfs3_bshrub_estimate
|
||||
// needed in lfs3_bshrub_fetch
|
||||
static int lfs3_mdir_lookup(lfs3_t *lfs3, const lfs3_mdir_t *mdir,
|
||||
lfs3_tag_t tag,
|
||||
lfs3_tag_t *tag_, lfs3_data_t *data_);
|
||||
|
||||
// fetch the bshrub/btree attatched to the current mdir+mid, if there
|
||||
// is one
|
||||
//
|
||||
// note we don't mess with bshrub on error!
|
||||
static int lfs3_bshrub_fetch(lfs3_t *lfs3, lfs3_bshrub_t *bshrub) {
|
||||
// lookup the file struct, if there is one
|
||||
lfs3_tag_t tag;
|
||||
lfs3_data_t data;
|
||||
int err = lfs3_mdir_lookup(lfs3, &bshrub->o.mdir,
|
||||
LFS3_TAG_MASK8 | LFS3_TAG_STRUCT,
|
||||
&tag, &data);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// these functions leave bshrub undefined if there is an error, so
|
||||
// first read into the staging shrub
|
||||
|
||||
// found a bshrub? (inlined btree)
|
||||
if (tag == LFS3_TAG_BSHRUB) {
|
||||
err = lfs3_data_readshrub(lfs3, &bshrub->o.mdir, &data,
|
||||
&bshrub->shrub_);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// found a btree?
|
||||
} else if (LFS3_IFDEF_2BONLY(false, tag == LFS3_TAG_BTREE)) {
|
||||
#ifndef LFS3_2BONLY
|
||||
err = lfs3_data_fetchbtree(lfs3, &data,
|
||||
&bshrub->shrub_);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
// we can run into other structs, dids in lfs3_mtree_traverse for
|
||||
// example, just ignore these for now
|
||||
} else {
|
||||
return LFS3_ERR_NOENT;
|
||||
}
|
||||
|
||||
// update the bshrub/btree
|
||||
bshrub->shrub = bshrub->shrub_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// find a tight upper bound on the _full_ bshrub size, this includes
|
||||
// any on-disk bshrubs, and all pending bshrubs
|
||||
#ifndef LFS3_RDONLY
|
||||
@@ -6588,7 +6635,7 @@ static lfs3_ssize_t lfs3_bshrub_estimate(lfs3_t *lfs3,
|
||||
|
||||
if (err != LFS3_ERR_NOENT) {
|
||||
lfs3_shrub_t shrub;
|
||||
err = lfs3_data_readshrub(lfs3, &data, &bshrub->o.mdir,
|
||||
err = lfs3_data_readshrub(lfs3, &bshrub->o.mdir, &data,
|
||||
&shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
@@ -8107,7 +8154,7 @@ static int lfs3_mdir_commit__(lfs3_t *lfs3, lfs3_mdir_t *mdir,
|
||||
// as well to bring it along with us
|
||||
if (tag == LFS3_TAG_BSHRUB) {
|
||||
lfs3_shrub_t shrub;
|
||||
err = lfs3_data_readshrub(lfs3, &data, mdir__,
|
||||
err = lfs3_data_readshrub(lfs3, mdir__, &data,
|
||||
&shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
@@ -8342,7 +8389,8 @@ static lfs3_ssize_t lfs3_mdir_estimate__(lfs3_t *lfs3, const lfs3_mdir_t *mdir,
|
||||
dsize_ += LFS3_SHRUB_DSIZE;
|
||||
|
||||
lfs3_shrub_t shrub;
|
||||
err = lfs3_data_readshrub(lfs3, &data, mdir, &shrub);
|
||||
err = lfs3_data_readshrub(lfs3, mdir, &data,
|
||||
&shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -8445,7 +8493,7 @@ static int lfs3_mdir_compact__(lfs3_t *lfs3, lfs3_mdir_t *mdir_,
|
||||
// bring it along with us
|
||||
if (tag == LFS3_TAG_BSHRUB) {
|
||||
lfs3_shrub_t shrub;
|
||||
err = lfs3_data_readshrub(lfs3, &data, mdir,
|
||||
err = lfs3_data_readshrub(lfs3, mdir, &data,
|
||||
&shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
@@ -9797,38 +9845,14 @@ static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t,
|
||||
}
|
||||
|
||||
// do we have a bshrub/btree?
|
||||
err = lfs3_mdir_lookup(lfs3, &t->b.o.mdir,
|
||||
LFS3_TAG_MASK8 | LFS3_TAG_STRUCT,
|
||||
&tag, &data);
|
||||
err = lfs3_bshrub_fetch(lfs3, &t->b);
|
||||
if (err && err != LFS3_ERR_NOENT) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// found a bshrub/btree? note we may also run into
|
||||
// dirs/dids here
|
||||
if (err != LFS3_ERR_NOENT
|
||||
&& (tag == LFS3_TAG_BSHRUB
|
||||
|| tag == LFS3_TAG_BTREE)) {
|
||||
// found a bshrub (inlined btree)?
|
||||
if (tag == LFS3_TAG_BSHRUB) {
|
||||
err = lfs3_data_readshrub(lfs3, &data, &t->b.o.mdir,
|
||||
&t->b.shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// found a btree?
|
||||
} else if (tag == LFS3_TAG_BTREE) {
|
||||
err = lfs3_data_fetchbtree(lfs3, &data,
|
||||
&t->b.shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
} else {
|
||||
LFS3_UNREACHABLE();
|
||||
}
|
||||
|
||||
// found a bshrub/btree? note we may also run into dirs/dids
|
||||
// here, lfs3_bshrub_fetch ignores these for us
|
||||
if (err != LFS3_ERR_NOENT) {
|
||||
// start traversing
|
||||
lfs3_btraversal_init(&t->u.bt);
|
||||
lfs3_t_settstate(&t->b.o.flags, LFS3_TSTATE_BTREE);
|
||||
@@ -11530,48 +11554,12 @@ static void lfs3_file_init(lfs3_file_t *file, uint32_t flags,
|
||||
static int lfs3_file_fetch(lfs3_t *lfs3, lfs3_file_t *file, uint32_t flags) {
|
||||
// don't bother reading disk if we're not created or truncating
|
||||
if (!lfs3_o_isuncreat(flags) && !lfs3_o_istrunc(flags)) {
|
||||
// lookup the file struct, if there is one
|
||||
lfs3_tag_t tag;
|
||||
lfs3_data_t data;
|
||||
int err = lfs3_mdir_lookup(lfs3, &file->b.o.mdir,
|
||||
LFS3_TAG_MASK8 | LFS3_TAG_DATA,
|
||||
&tag, &data);
|
||||
// fetch the file's bshrub/btree, if there is one
|
||||
int err = lfs3_bshrub_fetch(lfs3, &file->b);
|
||||
if (err && err != LFS3_ERR_NOENT) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// note many of these functions leave bshrub undefined if there
|
||||
// is an error, so we first read into a temporary bshrub/btree
|
||||
lfs3_rbyd_t shrub = file->b.shrub;
|
||||
|
||||
// found a bshrub/btree?
|
||||
if (err != LFS3_ERR_NOENT) {
|
||||
// may be a bshrub (inlined btree)
|
||||
if (tag == LFS3_TAG_BSHRUB) {
|
||||
err = lfs3_data_readshrub(lfs3, &data, &file->b.o.mdir,
|
||||
&shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// or a btree
|
||||
} else if (LFS3_IFDEF_2BONLY(false, tag == LFS3_TAG_BTREE)) {
|
||||
#ifndef LFS3_2BONLY
|
||||
err = lfs3_data_fetchbtree(lfs3, &data,
|
||||
&shrub);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
LFS3_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// update the bshrub/btree
|
||||
file->b.shrub = shrub;
|
||||
|
||||
// mark as in-sync
|
||||
file->b.o.flags &= ~LFS3_o_UNSYNC;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user