Tweaked mdir commit so it handles all inlined file staging

This saves a bit of code:

            code          stack
  before:  25552           1920
  after:   25448 (-0.4%)   1920 (+0.0%)

But more importantly, this simplifies things and moves all of the
staging/updating logic into lfsr_mdir_commit, where most of the
subtle post-compaction interactions play out.
This commit is contained in:
Christopher Haster
2023-09-22 23:23:23 -05:00
parent 02ae6050de
commit 4334a848a3
+35 -39
View File
@@ -1024,17 +1024,17 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs,
((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_grm_t*){_grm}})
// writing to an unrelated trunk in the rbyd
#define LFSR_DATA_SHRUBATTRS(_rbyd, ...) \
#define LFSR_DATA_SHRUBATTRS(_file, ...) \
((lfsr_data_t){.u.direct.buffer=(const void*)&(const lfsr_shrubattrs_t){ \
.rbyd=_rbyd, \
.file=_file, \
.attrs=(const lfsr_attr_t[]){__VA_ARGS__}, \
.attr_count=sizeof((const lfsr_attr_t[]){__VA_ARGS__}) \
/ sizeof(lfsr_attr_t)}})
// the reason for lazily encoding inlined trunks is because they can change
// underneath us during mdir compaction, the horror
#define LFSR_DATA_TRUNK(_rbyd) \
((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_rbyd_t*){_rbyd}})
#define LFSR_DATA_FILE(_file) \
((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_file_t*){_file}})
static inline bool lfsr_data_ondisk(const lfsr_data_t *data) {
return data->u.size & LFSR_DATA_ONDISK;
@@ -1882,7 +1882,7 @@ static int lfsr_data_readgrm(lfs_t *lfs, lfsr_data_t *data,
// shrub things
typedef struct lfsr_shrubattrs {
lfsr_rbyd_t *rbyd;
lfsr_file_t *file;
const lfsr_attr_t *attrs;
lfs_size_t attr_count;
} lfsr_shrubattrs_t;
@@ -5248,8 +5248,8 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
// messed up
//
// it is important that these rbyds share eoff/cksum/etc
mdir_.u.m.trunk = shrubattrs->rbyd->trunk;
mdir_.u.m.weight = shrubattrs->rbyd->weight;
mdir_.u.m.trunk = shrubattrs->file->inlined_.u.rbyd.trunk;
mdir_.u.m.weight = shrubattrs->file->inlined_.u.rbyd.weight;
// if weight's sign=1, we were inlined data and need to zero
// things, we do this here to avoid compaction clobbering
@@ -5267,9 +5267,9 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
}
// revert to mdir trunk/weight
shrubattrs->rbyd->block = mdir_.u.m.blocks[0];
shrubattrs->rbyd->trunk = mdir_.u.m.trunk;
shrubattrs->rbyd->weight = mdir_.u.m.weight;
shrubattrs->file->inlined_.u.rbyd.block = mdir_.u.m.blocks[0];
shrubattrs->file->inlined_.u.rbyd.trunk = mdir_.u.m.trunk;
shrubattrs->file->inlined_.u.rbyd.weight = mdir_.u.m.weight;
mdir_.u.m.trunk = mdir->u.m.trunk;
mdir_.u.m.weight = mdir->u.m.weight;
@@ -5278,13 +5278,18 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
//
// TODO should we preserve mode for all of these?
} else if (lfsr_tag_key(attrs[i].tag) == LFSR_TAG_SHRUBTRUNK) {
lfsr_rbyd_t *rbyd = (lfsr_rbyd_t*)attrs[i].data.u.direct.buffer;
lfsr_file_t *file = (lfsr_file_t*)attrs[i].data.u.direct.buffer;
uint8_t trunk_buf[LFSR_TRUNK_DSIZE];
int err = lfsr_rbyd_appendattr(lfs, &mdir_.u.rbyd,
rid - lfs_smax32(start_rid, 0),
lfsr_tag_mode(attrs[i].tag) | LFSR_TAG_TRUNK,
attrs[i].delta, lfsr_data_fromtrunk(rbyd, trunk_buf));
attrs[i].delta,
lfsr_data_fromtrunk(
// note we use the pending trunk here, our inlined
// data may have been updated for compacts
&file->inlined_.u.rbyd,
trunk_buf));
if (err) {
return err;
}
@@ -5672,6 +5677,17 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
}
}
// stage all inlined files, these may be need updating if we compact
// an mdir
//
// TODO merge with above?
for (lfsr_openedmdir_t *opened = lfs->opened[LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_file_t *file = (lfsr_file_t*)opened;
file->inlined_ = file->inlined;
}
// attempt to commit/compact the mdir normally
lfsr_srid_t split_rid;
int err = lfsr_mdir_commit_(lfs, &mdir_, -1, -1, &split_rid,
@@ -6185,21 +6201,14 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
}
}
// update any staged changes to inlined data/trees
//
// TODO merge with above? maybe?
for (lfsr_openedmdir_t *opened = lfs->opened[LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
// if we compacted, update any staged changes to inlined data/trees
lfsr_file_t *file = (lfsr_file_t*)opened;
if (mdir_.u.m.blocks[0] != mdir->u.m.blocks[0]
&& ((lfsr_file_hasinlined(file)
&& file->inlined.u.data.u.disk.block
== mdir->u.m.blocks[0])
|| (lfsr_file_hasshrub(file)
&& file->inlined.u.rbyd.block
== mdir->u.m.blocks[0]))) {
file->inlined = file->inlined_;
}
file->inlined = file->inlined_;
}
// update mdir to follow requested rid
@@ -8397,15 +8406,10 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
// convert to inlined tree
//
// make sure to use our staging rbyd so we catch in-flight updates
// caused by mdir compactions
//
// note that the actual conversion from inlined data to tree is
// in lfsr_mdir_commit__ to avoid compaction issues
file->inlined_ = file->inlined;
int err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(
&file->inlined_.u.rbyd,
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(file,
// note we always need a zero entry
(file->buffer_pos > 0
? LFSR_ATTR(0,
@@ -8427,7 +8431,6 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
return err;
}
file->inlined = file->inlined_;
// TODO
file->inlined.u.shrub.overhead = 0;
file->buffer_size = 0;
@@ -8501,13 +8504,8 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
}
// write out our buffer and any carved data
//
// make sure to use our staging rbyd so we catch in-flight updates
// caused by mdir compactions
file->inlined_ = file->inlined;
err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(
&file->inlined_.u.rbyd,
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(file,
// first remove anything in the way
LFSR_ATTR(
lfs_min32(
@@ -8539,7 +8537,6 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
return err;
}
file->inlined = file->inlined_;
file->buffer_size = 0;
continue;
@@ -8679,10 +8676,9 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
//
// make sure to use our staging rbyd so we catch in-flight updates
// caused by mdir compactions
file->inlined_ = file->inlined;
err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
LFSR_ATTR(file->m.mdir.mid, WIDE(SHRUBTRUNK), 0, TRUNK(
&file->inlined_.u.rbyd))));
LFSR_ATTR(file->m.mdir.mid,
WIDE(SHRUBTRUNK), 0, FILE(file))));
if (err) {
goto failed;
}