diff --git a/lfs.c b/lfs.c index f589861b..f70fb321 100644 --- a/lfs.c +++ b/lfs.c @@ -2895,7 +2895,7 @@ failed:; } static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, - lfs_ssize_t start_rid, lfs_ssize_t end_rid, + lfs_size_t bid, lfs_ssize_t start_rid, lfs_ssize_t end_rid, const lfsr_attr_t *attrs, lfs_size_t attr_count) { // append each tag to the tree for (lfs_size_t i = 0; i < attr_count; i++) { @@ -2906,8 +2906,12 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, } // don't write tags outside of the requested range - if (attrs[i].rid >= start_rid - && (end_rid < 0 || attrs[i].rid < end_rid)) { + if (lfs_smax32(attrs[i].rid - bid, -1) >= start_rid + // note the use of rid+1 and unsigned comparison here to + // treat end_rid=-1 as "unbounded" in such a way that rid=-1 + // is still included + && (lfs_size_t)lfs_smax32(attrs[i].rid - bid, -1) + 1 + <= (lfs_size_t)end_rid) { // this is a bit of a hack, but ignore any gstate tags here, // these need to be handled specially by upper-layers if (lfsr_tag_suptype(attrs[i].tag) == LFSR_TAG_GSTATE) { @@ -2937,7 +2941,9 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, // append the attr err = lfsr_rbyd_append(lfs, rbyd, - attrs[i].rid - lfs_smax32(start_rid, 0), + lfs_smax32( + attrs[i].rid - bid - lfs_smax32(start_rid, 0), + -1), tag, 0, data); if (err) { return err; @@ -2949,7 +2955,9 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, LFS_ASSERT(!lfsr_tag_isinternal(attrs[i].tag)); int err = lfsr_rbyd_append(lfs, rbyd, - attrs[i].rid - lfs_smax32(start_rid, 0), + lfs_smax32( + attrs[i].rid - bid - lfs_smax32(start_rid, 0), + -1), attrs[i].tag, attrs[i].delta, attrs[i].data); if (err) { return err; @@ -2959,10 +2967,10 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, // we need to make sure we keep start_rid/end_rid updated with // weight changes - if (attrs[i].rid < start_rid) { + if (lfs_smax32(attrs[i].rid - bid, -1) < start_rid) { start_rid += attrs[i].delta; } - if (attrs[i].rid < end_rid) { + if (lfs_smax32(attrs[i].rid - bid, -1) < end_rid) { end_rid += attrs[i].delta; } } @@ -3014,7 +3022,7 @@ static int lfsr_rbyd_appendgdelta(lfs_t *lfs, lfsr_rbyd_t *rbyd) { static int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd, const lfsr_attr_t *attrs, lfs_size_t attr_count) { // append each tag to the tree - int err = lfsr_rbyd_appendattrs(lfs, rbyd, -1, -1, + int err = lfsr_rbyd_appendattrs(lfs, rbyd, 0, -1, -1, attrs, attr_count); if (err) { return err; @@ -3827,7 +3835,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, } // commit our attrs - err = lfsr_rbyd_appendattrs(lfs, &rbyd, -1, -1, + err = lfsr_rbyd_appendattrs(lfs, &rbyd, 0, -1, -1, attrs, attr_count); if (err) { return err; @@ -3903,7 +3911,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, // erased bytes? note that the btree trunk field prevents this from // interacting with other references to the rbyd lfsr_rbyd_t rbyd_ = rbyd; - err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, -1, + err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, -1, -1, attrs, attr_count); if (err && err != LFS_ERR_RANGE) { // TODO wait should we also move if there is corruption here? @@ -4059,7 +4067,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, // append any pending attrs, it's up to upper // layers to make sure these always fit - err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, -1, + err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, -1, -1, attrs, attr_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -4147,7 +4155,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, // // upper layers should make sure this can't fail by limiting the // maximum commit size - err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, bid+split_rid, + err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, 0, split_rid, attrs, attr_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -4172,7 +4180,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, // // upper layers should make sure this can't fail by limiting the // maximum commit size - err = lfsr_rbyd_appendattrs(lfs, &sibling, bid+split_rid, -1, + err = lfsr_rbyd_appendattrs(lfs, &sibling, bid, split_rid, -1, attrs, attr_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -4315,7 +4323,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, // append any pending attrs, it's up to upper // layers to make sure these always fit - err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, -1, + err = lfsr_rbyd_appendattrs(lfs, &rbyd_, bid, -1, -1, attrs, attr_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -4997,7 +5005,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // // upper layers should make sure this can't fail by limiting the // maximum commit size - err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, start_rid, end_rid, + err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, 0, start_rid, end_rid, attr1s, attr1_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -5006,7 +5014,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // note we don't filter attrs from our second pending list, this // is used for some auxiliary attrs in lfsr_mdir_commit - err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, -1, -1, + err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, 0, -1, -1, attr2s, attr2_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -5071,7 +5079,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir, // TODO let the lower rbyd layer handle this somehow? // mark mdir as unerased in case we fail mdir->u.r.rbyd.eoff = lfs->cfg->block_size; - int err = lfsr_rbyd_appendattrs(lfs, &mdir_.u.r.rbyd, start_rid, end_rid, + int err = lfsr_rbyd_appendattrs(lfs, &mdir_.u.r.rbyd, 0, start_rid, end_rid, attrs, attr_count); if (err && err != LFS_ERR_RANGE) { return err;