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:
@@ -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,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?
|
// 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]
|
file->inlined = file->inlined_;
|
||||||
&& ((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_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update mdir to follow requested rid
|
// 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
|
// 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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user