Skip to content

Commit

Permalink
Enabled btree tests on all geometries, fixed some revealed bugs
Browse files Browse the repository at this point in the history
The main issue with the btree tests cross-geometry is the number of ways
large btrees can run out of memory without garbage collection.

- Large progs => A lot of padding on non-compacting commits
- Small blocks => Deeper trees and more compacts

Rather than figure out every precondition, I've just added code that
ignores out-of-space errors.

As a plus this is now also testing that errors don't corrupt the btree
being modified.

Bugs found:

- Thanks to lazy merges, it's possible for an in-btree rbyd weight to
  equal the total btree weight even when it's not the child of the root
  of the btree.

  The behavior is the same (collapse all degenerate parent), but the
  assert that we were the root's child is incorrect.

- Thanks again to lazy merges, it's possible to merge siblings where one
  of the blocks has no entries. Attempting to reintroduce the split name
  in this case can lead to LFS_ERR_NOENT issues.

  Fortunately we can simply skip the reintroduction of the split name in
  this case.

Also added more asserts for LFS_ERR_RANGE in lfsr_btree_commit. This is
still a rather fragile part of the algorithm so the asserts here help
identify when the pending attribute size is the problem.
  • Loading branch information
geky committed Apr 16, 2023
1 parent da8fa4b commit 3a470f9
Show file tree
Hide file tree
Showing 2 changed files with 442 additions and 140 deletions.
54 changes: 31 additions & 23 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3169,6 +3169,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
attrs[i].id, attrs[i].tag, attrs[i].delta,
attrs[i].data);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}
}
Expand All @@ -3183,6 +3184,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
// finalize commit
err = lfsr_rbyd_commit(lfs, &rbyd_, NULL, 0);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}

Expand Down Expand Up @@ -3307,6 +3309,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
attrs[i].id, attrs[i].tag, attrs[i].delta,
attrs[i].data);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}
}
Expand Down Expand Up @@ -3365,6 +3368,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
attrs[i].id-split_id_, attrs[i].tag, attrs[i].delta,
attrs[i].data);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}
}
Expand All @@ -3378,6 +3382,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
// finalize commit
err = lfsr_rbyd_commit(lfs, &sibling, NULL, 0);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}

Expand Down Expand Up @@ -3555,45 +3560,48 @@ static int lfsr_btree_commit(lfs_t *lfs,
}
}

// bring in name that previously split the siblings
lfsr_tag_t split_tag;
lfsr_data_t split_data;
err = lfsr_rbyd_lookup(lfs, &parent,
(sdelta == 0 ? pid : sid), LFSR_TAG_NAME,
NULL, &split_tag, NULL, &split_data);
if (err) {
return err;
}

if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
// lookup the id (weight really) of the previously-split entry
lfs_ssize_t split_id;
err = lfsr_rbyd_lookup(lfs, &rbyd_,
(sdelta == 0 ? sweight : rweight_), LFSR_TAG_NAME,
&split_id, NULL, NULL, NULL);
if (sweight > 0 && rweight_ > 0) {
// bring in name that previously split the siblings
lfsr_tag_t split_tag;
lfsr_data_t split_data;
err = lfsr_rbyd_lookup(lfs, &parent,
(sdelta == 0 ? pid : sid), LFSR_TAG_NAME,
NULL, &split_tag, NULL, &split_data);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}

err = lfsr_rbyd_append(lfs, &rbyd_,
split_id, LFSR_TAG_BNAME, 0, split_data);
if (err) {
return err;
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
// lookup the id (weight really) of the previously-split entry
lfs_ssize_t split_id;
err = lfsr_rbyd_lookup(lfs, &rbyd_,
(sdelta == 0 ? sweight : rweight_), LFSR_TAG_NAME,
&split_id, NULL, NULL, NULL);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
return err;
}

err = lfsr_rbyd_append(lfs, &rbyd_,
split_id, LFSR_TAG_BNAME, 0, split_data);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}
}
}

err = lfsr_rbyd_commit(lfs, &rbyd_, NULL, 0);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}

// we must have a parent at this point, but is our parent degenerate?
LFS_ASSERT(pid != -1);
if (pweight+sweight == lfsr_btree_weight(btree)) {
// collapse our parent, decreasing the height of the tree
LFS_ASSERT(btree->root.block == parent.block
&& btree->root.trunk == parent.trunk);
*rbyd = rbyd_;
break;

Expand Down
Loading

0 comments on commit 3a470f9

Please sign in to comment.