Rearranged lfsr_file_carve a bit to avoid attr_tnuoc shenanigans
The reason for carving up the right sibling before appending our new
data is because we 1. want to carve both left+right siblings in a single
lookup if possible, and 2. we don't want to keep unnecessary lookup state
around as much as possible.
But is keeping some lookup state around cheaper than the attr_tnuoc +
memmove mess? The answer is yes:
code stack
before: 34028 2896
after: 33944 (-0.2%) 2888 (-0.3%)
attr_tnuoc is one of those "if it's stupid and it works it's not stupid"
solutions, but that doesn't make it not stupid. (I'm joking a bit, but
the new code is cleaner + more readable, which was the original
motivation for looking at this function again)
This commit is contained in:
@@ -9989,7 +9989,6 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
lfsr_bid_t bid = lfsr_bshrub_size(&file->bshrub);
|
lfsr_bid_t bid = lfsr_bshrub_size(&file->bshrub);
|
||||||
lfsr_attr_t attrs[5];
|
lfsr_attr_t attrs[5];
|
||||||
lfs_size_t attr_count = 0;
|
lfs_size_t attr_count = 0;
|
||||||
lfs_size_t attr_tnuoc = 0;
|
|
||||||
uint8_t buf[3*LFSR_BPTR_DSIZE+2*LFSR_ECKSUM_DSIZE];
|
uint8_t buf[3*LFSR_BPTR_DSIZE+2*LFSR_ECKSUM_DSIZE];
|
||||||
lfs_size_t buf_size = 0;
|
lfs_size_t buf_size = 0;
|
||||||
|
|
||||||
@@ -10048,6 +10047,10 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to carve any existing data
|
// try to carve any existing data
|
||||||
|
lfsr_tag_t right_tag_ = 0;
|
||||||
|
lfsr_bid_t right_weight_;
|
||||||
|
lfsr_bptr_t right_bptr_;
|
||||||
|
lfsr_ecksum_t right_becksum_;
|
||||||
while (pos < lfsr_bshrub_size(&file->bshrub)) {
|
while (pos < lfsr_bshrub_size(&file->bshrub)) {
|
||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
lfsr_bid_t weight_;
|
lfsr_bid_t weight_;
|
||||||
@@ -10101,7 +10104,8 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
while (tag_ == LFSR_TAG_BLOCK
|
while (tag_ == LFSR_TAG_BLOCK
|
||||||
&& lfsr_data_size(right_slice_) > lfs->cfg->fragment_size
|
&& lfsr_data_size(right_slice_) > lfs->cfg->fragment_size
|
||||||
&& lfsr_data_size(right_slice_) < lfs->cfg->crystal_thresh) {
|
&& lfsr_data_size(right_slice_) < lfs->cfg->crystal_thresh) {
|
||||||
bptr_.data = lfsr_data_truncate(bptr_.data,
|
bptr_.data = lfsr_data_slice(bptr_.data,
|
||||||
|
-1,
|
||||||
lfsr_data_size(bptr_.data) - lfs->cfg->fragment_size);
|
lfsr_data_size(bptr_.data) - lfs->cfg->fragment_size);
|
||||||
|
|
||||||
err = lfsr_bshrub_commit(lfs, file, bid, LFSR_ATTRS(
|
err = lfsr_bshrub_commit(lfs, file, bid, LFSR_ATTRS(
|
||||||
@@ -10132,25 +10136,28 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
attrs[attr_count++] = LFSR_ATTR(
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
LFSR_TAG_GROW, -(bid+1 - pos), LFSR_DATA_NULL());
|
LFSR_TAG_GROW, -(bid+1 - pos), LFSR_DATA_NULL());
|
||||||
|
|
||||||
// carve bptr?
|
|
||||||
} else if (tag_ == LFSR_TAG_BLOCK) {
|
|
||||||
lfsr_bptr_t bptr__ = {
|
|
||||||
.data = left_slice_,
|
|
||||||
.cksize = bptr_.cksize,
|
|
||||||
.cksum = bptr_.cksum,
|
|
||||||
};
|
|
||||||
attrs[attr_count++] = LFSR_ATTR(
|
|
||||||
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
|
|
||||||
-(bid+1 - pos),
|
|
||||||
lfsr_data_frombptr(&bptr__, &buf[buf_size]));
|
|
||||||
buf_size += LFSR_BPTR_DSIZE;
|
|
||||||
|
|
||||||
// carve fragment?
|
// carve fragment?
|
||||||
} else {
|
} else if (tag_ == LFSR_TAG_DATA) {
|
||||||
attrs[attr_count++] = LFSR_ATTR(
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
|
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
|
||||||
-(bid+1 - pos),
|
-(bid+1 - pos),
|
||||||
left_slice_);
|
left_slice_);
|
||||||
|
|
||||||
|
// carve bptr?
|
||||||
|
} else if (tag_ == LFSR_TAG_BLOCK) {
|
||||||
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
|
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
|
||||||
|
-(bid+1 - pos),
|
||||||
|
lfsr_data_frombptr(
|
||||||
|
&(lfsr_bptr_t){
|
||||||
|
.data = left_slice_,
|
||||||
|
.cksize = bptr_.cksize,
|
||||||
|
.cksum = bptr_.cksum},
|
||||||
|
&buf[buf_size]));
|
||||||
|
buf_size += LFSR_BPTR_DSIZE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LFS_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
// completely overwriting this entry?
|
// completely overwriting this entry?
|
||||||
@@ -10185,31 +10192,27 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
if (lfsr_data_size(right_slice_) == 0) {
|
if (lfsr_data_size(right_slice_) == 0) {
|
||||||
delta += bid+1 - (pos+weight);
|
delta += bid+1 - (pos+weight);
|
||||||
|
|
||||||
|
// carve fragment?
|
||||||
|
} else if (tag_ == LFSR_TAG_DATA) {
|
||||||
|
right_tag_ = tag_;
|
||||||
|
right_weight_ = bid+1 - (pos+weight);
|
||||||
|
right_bptr_.data = right_slice_;
|
||||||
|
|
||||||
// carve bptr?
|
// carve bptr?
|
||||||
} else if (tag_ == LFSR_TAG_BLOCK) {
|
} else if (tag_ == LFSR_TAG_BLOCK) {
|
||||||
lfsr_bptr_t bptr__ = {
|
right_tag_ = tag_;
|
||||||
|
right_weight_ = bid+1 - (pos+weight);
|
||||||
|
right_bptr_ = (lfsr_bptr_t){
|
||||||
.data = right_slice_,
|
.data = right_slice_,
|
||||||
.cksize = bptr_.cksize,
|
.cksize = bptr_.cksize,
|
||||||
.cksum = bptr_.cksum,
|
.cksum = bptr_.cksum,
|
||||||
};
|
};
|
||||||
attrs[attr_count+attr_tnuoc++] = LFSR_ATTR(
|
|
||||||
LFSR_TAG_BLOCK, +(bid+1 - (pos+weight)),
|
|
||||||
lfsr_data_frombptr(&bptr__, &buf[buf_size]));
|
|
||||||
buf_size += LFSR_BPTR_DSIZE;
|
|
||||||
|
|
||||||
// copy over becksum since erase-state is still valid
|
// copy over becksum since erase-state is still valid
|
||||||
if (becksum_.cksize != -1) {
|
right_becksum_ = becksum_;
|
||||||
attrs[attr_count+attr_tnuoc++] = LFSR_ATTR(
|
|
||||||
LFSR_TAG_BECKSUM, 0,
|
|
||||||
lfsr_data_fromecksum(&becksum_, &buf[buf_size]));
|
|
||||||
buf_size += LFSR_ECKSUM_DSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// carve fragment?
|
|
||||||
} else {
|
} else {
|
||||||
attrs[attr_count+attr_tnuoc++] = LFSR_ATTR(
|
LFS_UNREACHABLE();
|
||||||
LFSR_TAG_DATA, +(bid+1 - (pos+weight)),
|
|
||||||
right_slice_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10218,37 +10221,29 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally append our data
|
// append our data
|
||||||
if (weight + delta > 0) {
|
if (weight + delta > 0) {
|
||||||
// can we coalesce a hole?
|
// can we coalesce a hole?
|
||||||
if ((!bptr || lfsr_data_size(bptr->data) == 0) && pos > 0) {
|
if ((!bptr || lfsr_data_size(bptr->data) == 0) && pos > 0) {
|
||||||
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub)-1);
|
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub)-1);
|
||||||
memmove(&attrs[attr_count+1], &attrs[attr_count],
|
|
||||||
attr_tnuoc*sizeof(lfsr_attr_t));
|
|
||||||
attrs[attr_count++] = LFSR_ATTR(
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
LFSR_TAG_GROW, +(weight + delta), LFSR_DATA_NULL());
|
LFSR_TAG_GROW, +(weight + delta), LFSR_DATA_NULL());
|
||||||
|
|
||||||
// need a new hole?
|
// need a new hole?
|
||||||
} else if (!bptr || lfsr_data_size(bptr->data) == 0) {
|
} else if (!bptr || lfsr_data_size(bptr->data) == 0) {
|
||||||
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub));
|
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub));
|
||||||
memmove(&attrs[attr_count+1], &attrs[attr_count],
|
|
||||||
attr_tnuoc*sizeof(lfsr_attr_t));
|
|
||||||
attrs[attr_count++] = LFSR_ATTR(
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
LFSR_TAG_DATA, +(weight + delta), LFSR_DATA_NULL());
|
LFSR_TAG_DATA, +(weight + delta), LFSR_DATA_NULL());
|
||||||
|
|
||||||
// append new fragment?
|
// append new fragment?
|
||||||
} else if (tag == LFSR_TAG_DATA) {
|
} else if (tag == LFSR_TAG_DATA) {
|
||||||
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub));
|
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub));
|
||||||
memmove(&attrs[attr_count+1], &attrs[attr_count],
|
|
||||||
attr_tnuoc*sizeof(lfsr_attr_t));
|
|
||||||
attrs[attr_count++] = LFSR_ATTR(
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
LFSR_TAG_DATA, +(weight + delta), bptr->data);
|
LFSR_TAG_DATA, +(weight + delta), bptr->data);
|
||||||
|
|
||||||
// append a new block?
|
// append a new block?
|
||||||
} else if (tag == LFSR_TAG_BLOCK) {
|
} else if (tag == LFSR_TAG_BLOCK) {
|
||||||
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub));
|
bid = lfs_min32(bid, lfsr_bshrub_size(&file->bshrub));
|
||||||
memmove(&attrs[attr_count+1], &attrs[attr_count],
|
|
||||||
attr_tnuoc*sizeof(lfsr_attr_t));
|
|
||||||
attrs[attr_count++] = LFSR_ATTR(
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
LFSR_TAG_BLOCK, +(weight + delta),
|
LFSR_TAG_BLOCK, +(weight + delta),
|
||||||
lfsr_data_frombptr(bptr, &buf[buf_size]));
|
lfsr_data_frombptr(bptr, &buf[buf_size]));
|
||||||
@@ -10256,8 +10251,6 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
|
|
||||||
// append becksum?
|
// append becksum?
|
||||||
if (becksum && becksum->cksize != -1) {
|
if (becksum && becksum->cksize != -1) {
|
||||||
memmove(&attrs[attr_count+1], &attrs[attr_count],
|
|
||||||
attr_tnuoc*sizeof(lfsr_attr_t));
|
|
||||||
attrs[attr_count++] = LFSR_ATTR(
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
LFSR_TAG_BECKSUM, 0,
|
LFSR_TAG_BECKSUM, 0,
|
||||||
lfsr_data_fromecksum(becksum, &buf[buf_size]));
|
lfsr_data_fromecksum(becksum, &buf[buf_size]));
|
||||||
@@ -10269,13 +10262,41 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// and don't forget the right sibling's attrs
|
||||||
|
if (right_tag_) {
|
||||||
|
// right fragment?
|
||||||
|
if (right_tag_ == LFSR_TAG_DATA) {
|
||||||
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
|
LFSR_TAG_DATA, +right_weight_,
|
||||||
|
right_bptr_.data);
|
||||||
|
|
||||||
|
// right bptr?
|
||||||
|
} else if (right_tag_ == LFSR_TAG_BLOCK) {
|
||||||
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
|
LFSR_TAG_BLOCK, +right_weight_,
|
||||||
|
lfsr_data_frombptr(&right_bptr_, &buf[buf_size]));
|
||||||
|
buf_size += LFSR_BPTR_DSIZE;
|
||||||
|
|
||||||
|
// copy over becksum since erase-state is still valid
|
||||||
|
if (right_becksum_.cksize != -1) {
|
||||||
|
attrs[attr_count++] = LFSR_ATTR(
|
||||||
|
LFSR_TAG_BECKSUM, 0,
|
||||||
|
lfsr_data_fromecksum(&right_becksum_, &buf[buf_size]));
|
||||||
|
buf_size += LFSR_ECKSUM_DSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LFS_UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// commit pending attrs
|
// commit pending attrs
|
||||||
if (attr_count+attr_tnuoc > 0) {
|
if (attr_count > 0) {
|
||||||
LFS_ASSERT(attr_count+attr_tnuoc <= sizeof(attrs)/sizeof(lfsr_attr_t));
|
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
|
||||||
LFS_ASSERT(buf_size <= sizeof(buf));
|
LFS_ASSERT(buf_size <= sizeof(buf));
|
||||||
|
|
||||||
int err = lfsr_bshrub_commit(lfs, file, bid,
|
int err = lfsr_bshrub_commit(lfs, file, bid,
|
||||||
attrs, attr_count+attr_tnuoc);
|
attrs, attr_count);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user