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
+34 -38
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}}) ((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_grm_t*){_grm}})
// writing to an unrelated trunk in the rbyd // 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){ \ ((lfsr_data_t){.u.direct.buffer=(const void*)&(const lfsr_shrubattrs_t){ \
.rbyd=_rbyd, \ .file=_file, \
.attrs=(const lfsr_attr_t[]){__VA_ARGS__}, \ .attrs=(const lfsr_attr_t[]){__VA_ARGS__}, \
.attr_count=sizeof((const lfsr_attr_t[]){__VA_ARGS__}) \ .attr_count=sizeof((const lfsr_attr_t[]){__VA_ARGS__}) \
/ sizeof(lfsr_attr_t)}}) / sizeof(lfsr_attr_t)}})
// the reason for lazily encoding inlined trunks is because they can change // the reason for lazily encoding inlined trunks is because they can change
// underneath us during mdir compaction, the horror // underneath us during mdir compaction, the horror
#define LFSR_DATA_TRUNK(_rbyd) \ #define LFSR_DATA_FILE(_file) \
((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_rbyd_t*){_rbyd}}) ((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_file_t*){_file}})
static inline bool lfsr_data_ondisk(const lfsr_data_t *data) { static inline bool lfsr_data_ondisk(const lfsr_data_t *data) {
return data->u.size & LFSR_DATA_ONDISK; 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 // shrub things
typedef struct lfsr_shrubattrs { typedef struct lfsr_shrubattrs {
lfsr_rbyd_t *rbyd; lfsr_file_t *file;
const lfsr_attr_t *attrs; const lfsr_attr_t *attrs;
lfs_size_t attr_count; lfs_size_t attr_count;
} lfsr_shrubattrs_t; } lfsr_shrubattrs_t;
@@ -5248,8 +5248,8 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
// messed up // messed up
// //
// it is important that these rbyds share eoff/cksum/etc // it is important that these rbyds share eoff/cksum/etc
mdir_.u.m.trunk = shrubattrs->rbyd->trunk; mdir_.u.m.trunk = shrubattrs->file->inlined_.u.rbyd.trunk;
mdir_.u.m.weight = shrubattrs->rbyd->weight; mdir_.u.m.weight = shrubattrs->file->inlined_.u.rbyd.weight;
// if weight's sign=1, we were inlined data and need to zero // if weight's sign=1, we were inlined data and need to zero
// things, we do this here to avoid compaction clobbering // 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 // revert to mdir trunk/weight
shrubattrs->rbyd->block = mdir_.u.m.blocks[0]; shrubattrs->file->inlined_.u.rbyd.block = mdir_.u.m.blocks[0];
shrubattrs->rbyd->trunk = mdir_.u.m.trunk; shrubattrs->file->inlined_.u.rbyd.trunk = mdir_.u.m.trunk;
shrubattrs->rbyd->weight = mdir_.u.m.weight; shrubattrs->file->inlined_.u.rbyd.weight = mdir_.u.m.weight;
mdir_.u.m.trunk = mdir->u.m.trunk; mdir_.u.m.trunk = mdir->u.m.trunk;
mdir_.u.m.weight = mdir->u.m.weight; 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? // TODO should we preserve mode for all of these?
} else if (lfsr_tag_key(attrs[i].tag) == LFSR_TAG_SHRUBTRUNK) { } 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]; uint8_t trunk_buf[LFSR_TRUNK_DSIZE];
int err = lfsr_rbyd_appendattr(lfs, &mdir_.u.rbyd, int err = lfsr_rbyd_appendattr(lfs, &mdir_.u.rbyd,
rid - lfs_smax32(start_rid, 0), rid - lfs_smax32(start_rid, 0),
lfsr_tag_mode(attrs[i].tag) | LFSR_TAG_TRUNK, 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) { if (err) {
return 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 // attempt to commit/compact the mdir normally
lfsr_srid_t split_rid; lfsr_srid_t split_rid;
int err = lfsr_mdir_commit_(lfs, &mdir_, -1, -1, &split_rid, int err = lfsr_mdir_commit_(lfs, &mdir_, -1, -1, &split_rid,
@@ -6185,22 +6201,15 @@ 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? // TODO merge with above? maybe?
for (lfsr_openedmdir_t *opened = lfs->opened[LFS_TYPE_REG-LFS_TYPE_REG]; for (lfsr_openedmdir_t *opened = lfs->opened[LFS_TYPE_REG-LFS_TYPE_REG];
opened; opened;
opened = opened->next) { opened = opened->next) {
// if we compacted, update any staged changes to inlined data/trees
lfsr_file_t *file = (lfsr_file_t*)opened; 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 // update mdir to follow requested rid
if (mid != -1 if (mid != -1
@@ -8397,15 +8406,10 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
// convert to inlined tree // 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 // note that the actual conversion from inlined data to tree is
// in lfsr_mdir_commit__ to avoid compaction issues // in lfsr_mdir_commit__ to avoid compaction issues
file->inlined_ = file->inlined;
int err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS( int err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS( LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(file,
&file->inlined_.u.rbyd,
// note we always need a zero entry // note we always need a zero entry
(file->buffer_pos > 0 (file->buffer_pos > 0
? LFSR_ATTR(0, ? LFSR_ATTR(0,
@@ -8427,7 +8431,6 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
return err; return err;
} }
file->inlined = file->inlined_;
// TODO // TODO
file->inlined.u.shrub.overhead = 0; file->inlined.u.shrub.overhead = 0;
file->buffer_size = 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 // 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( err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS( LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(file,
&file->inlined_.u.rbyd,
// first remove anything in the way // first remove anything in the way
LFSR_ATTR( LFSR_ATTR(
lfs_min32( lfs_min32(
@@ -8539,7 +8537,6 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
return err; return err;
} }
file->inlined = file->inlined_;
file->buffer_size = 0; file->buffer_size = 0;
continue; 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 // make sure to use our staging rbyd so we catch in-flight updates
// caused by mdir compactions // caused by mdir compactions
file->inlined_ = file->inlined;
err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS( err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
LFSR_ATTR(file->m.mdir.mid, WIDE(SHRUBTRUNK), 0, TRUNK( LFSR_ATTR(file->m.mdir.mid,
&file->inlined_.u.rbyd)))); WIDE(SHRUBTRUNK), 0, FILE(file))));
if (err) { if (err) {
goto failed; goto failed;
} }