From 4e851c2d88af7426af17ab2a0f78412e6a9fc4b5 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 6 Feb 2024 15:29:43 -0600 Subject: [PATCH] Added a couple attr-related helper functions Some relatively-annoying states to check for: - lfsr_attr_isnoop - lfsr_attr_isinsert And some accessors for marshalled pointers used by internal tags: - lfsr_attr_grm - lfsr_attr_mdir - lfsr_attr_shrubcommit - lfsr_attr_shrubtrunk --- lfs.c | 73 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/lfs.c b/lfs.c index 7b14d798..30b060d9 100644 --- a/lfs.c +++ b/lfs.c @@ -1063,6 +1063,8 @@ enum { ((lfsr_data_t){.u.buf.buffer=(const void*)(lfsr_grm_t*){_grm}}) // writing to an unrelated trunk in the rbyd +typedef struct lfsr_shrubcommit lfsr_shrubcommit_t; + #define LFSR_DATA_SHRUBCOMMIT(_shrub, _rid, _attrs, _attr_count) \ ((lfsr_data_t){.u.buf.buffer=(const void*)&(const lfsr_shrubcommit_t){ \ .shrub=_shrub, \ @@ -1438,13 +1440,37 @@ typedef struct lfsr_attr { #define LFSR_ATTR_NOOP() LFSR_ATTR(NULL, 0, NULL()) - - -// TODO make this const again eventually #define LFSR_ATTRS(...) \ (const lfsr_attr_t[]){__VA_ARGS__}, \ sizeof((const lfsr_attr_t[]){__VA_ARGS__}) / sizeof(lfsr_attr_t) +// some helpers +static inline bool lfsr_attr_isnoop(const lfsr_attr_t *attr) { + return !attr->tag && attr->delta == 0; +} + +static inline bool lfsr_attr_isinsert(const lfsr_attr_t *attr) { + return !lfsr_tag_isgrow(attr->tag) && attr->delta > 0; +} + +static inline lfsr_grm_t *lfsr_attr_grm(const lfsr_attr_t *attr) { + return (lfsr_grm_t*)attr->data.u.buf.buffer; +} + +static inline lfsr_mdir_t *lfsr_attr_mdir(const lfsr_attr_t *attr) { + return (lfsr_mdir_t*)attr->data.u.buf.buffer; +} + +static inline const lfsr_shrubcommit_t *lfsr_attr_shrubcommit( + const lfsr_attr_t *attr) { + return (const lfsr_shrubcommit_t*)attr->data.u.buf.buffer; +} + +static inline lfsr_shrub_t *lfsr_attr_shrubtrunk(const lfsr_attr_t *attr) { + return (lfsr_shrub_t*)attr->data.u.buf.buffer; +} + + // generalized info returned by traveral functions typedef struct lfsr_tinfo { @@ -2543,7 +2569,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfsr_srid_t other_rid_; lfsr_tag_t tag_; lfsr_tag_t other_tag_; - if (delta != 0 && !lfsr_tag_isgrow(tag)) { + if (!lfsr_tag_isgrow(tag) && delta != 0) { if (delta > 0) { LFS_ASSERT(rid <= rbyd->weight); @@ -2906,7 +2932,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, if (lfsr_tag_key(tag_) && (upper_rid-1 < rid-lfs_smax32(-delta, 0) || (upper_rid-1 == rid-lfs_smax32(-delta, 0) - && ((delta > 0 && !lfsr_tag_isgrow(tag)) + && ((!lfsr_tag_isgrow(tag) && delta > 0) || (!lfsr_tag_issupwide(tag) && lfsr_tag_supkey(tag_) < lfsr_tag_supkey(tag)) || (!lfsr_tag_issupwide(tag) @@ -2932,7 +2958,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, } else if (lfsr_tag_key(tag_) && (upper_rid-1 > rid || (upper_rid-1 == rid - && ((delta > 0 && !lfsr_tag_isgrow(tag)) + && ((!lfsr_tag_isgrow(tag) && delta > 0) || (!lfsr_tag_issupwide(tag) && lfsr_tag_supkey(tag_) > lfsr_tag_supkey(tag)) || (!lfsr_tag_issupwide(tag) @@ -3156,9 +3182,7 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, for (lfs_size_t i = 0; i < attr_count; i++) { // treat inserts after the first tag as though they are splits, // sequential inserts don't really make sense otherwise - if (i > 0 - && !lfsr_tag_isgrow(attrs[i].tag) - && attrs[i].delta > 0) { + if (i > 0 && lfsr_attr_isinsert(&attrs[i])) { rid += 1; } @@ -3187,7 +3211,7 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, // adjust rid rid += attrs[i].delta; - if (!lfsr_tag_isgrow(attrs[i].tag) && attrs[i].delta > 0) { + if (lfsr_attr_isinsert(&attrs[i])) { rid -= 1; } } @@ -4952,12 +4976,12 @@ static int lfsr_shrub_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_, } // this is needed to sneak shrub commits into mdir commits -typedef struct lfsr_shrubcommit_t { +struct lfsr_shrubcommit { lfsr_shrub_t *shrub; lfsr_srid_t rid; const lfsr_attr_t *attrs; lfs_size_t attr_count; -} lfsr_shrubcommit_t; +}; static int lfsr_shrub_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd_, lfsr_shrub_t *shrub, lfsr_srid_t rid, @@ -5524,9 +5548,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir, for (lfs_size_t i = 0; i < attr_count; i++) { // we just happen to never split in an mdir commit - LFS_ASSERT(!(i > 0 - && !lfsr_tag_isgrow(attrs[i].tag) - && attrs[i].delta > 0)); + LFS_ASSERT(!(i > 0 && lfsr_attr_isinsert(&attrs[i]))); // ignore any gstate tags here, these need to be handled // specially by upper-layers @@ -5539,8 +5561,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir, } else if (attrs[i].tag == LFSR_TAG_MOVE) { // weighted moves are not supported LFS_ASSERT(attrs[i].delta == 0); - const lfsr_mdir_t *mdir__ - = (const lfsr_mdir_t*)attrs[i].data.u.buf.buffer; + const lfsr_mdir_t *mdir__ = lfsr_attr_mdir(&attrs[i]); // skip the name tag, this is always replaced by upper layers lfsr_tag_t tag = LFSR_TAG_STRUCT-1; @@ -5665,7 +5686,8 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir, } else if (attrs[i].tag == LFSR_TAG_SHRUBALLOC || attrs[i].tag == LFSR_TAG_SHRUBCOMMIT) { const lfsr_shrubcommit_t *bshrubcommit - = (const lfsr_shrubcommit_t*)attrs[i].data.u.buf.buffer; + = lfsr_attr_shrubcommit(&attrs[i]); + // SHRUBALLOC is roughly the same as SHRUBCOMMIT but also // resets the shrub, we need to do this here so bshrub root // extensions are atomic @@ -5690,8 +5712,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir, // TODO should we preserve mode for all of these? // TODO should we do the same for sprouts? } else if (lfsr_tag_key(attrs[i].tag) == LFSR_TAG_SHRUBTRUNK) { - lfsr_shrub_t *shrub - = (lfsr_shrub_t*)attrs[i].data.u.buf.buffer; + lfsr_shrub_t *shrub = lfsr_attr_shrubtrunk(&attrs[i]); uint8_t shrub_buf[LFSR_SHRUB_DSIZE]; int err = lfsr_rbyd_appendattr(lfs, &rbyd_, @@ -5719,7 +5740,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir, // adjust rid rid += attrs[i].delta; - if (!lfsr_tag_isgrow(attrs[i].tag) && attrs[i].delta > 0) { + if (lfsr_attr_isinsert(&attrs[i])) { rid -= 1; } } @@ -6388,7 +6409,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // xored with on-disk gdeltas in lower-level functions if (attrs[i].tag == LFSR_TAG_GRM) { // encode to disk - lfsr_grm_t *grm = (lfsr_grm_t*)attrs[i].data.u.buf.buffer; + lfsr_grm_t *grm = lfsr_attr_grm(&attrs[i]); lfsr_data_fromgrm(grm, lfs->grm_d); // xor with our current gstate to find our initial gdelta @@ -6564,7 +6585,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // // gd' = gd xor (grm' xor grm) // - lfsr_grm_t *grm = (lfsr_grm_t*)attrs[i].data.u.buf.buffer; + lfsr_grm_t *grm = lfsr_attr_grm(&attrs[i]); uint8_t grm_buf[LFSR_GRM_DSIZE]; err = lfsr_grm_xor(lfs, lfs->grm_d, lfsr_data_fromgrm(grm, grm_buf)); @@ -6668,7 +6689,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // // gd' = gd xor (grm' xor grm) // - lfsr_grm_t *grm = (lfsr_grm_t*)attrs[i].data.u.buf.buffer; + lfsr_grm_t *grm = lfsr_attr_grm(&attrs[i]); uint8_t grm_buf[LFSR_GRM_DSIZE]; err = lfsr_grm_xor(lfs, lfs->grm_d, lfsr_data_fromgrm(grm, grm_buf)); @@ -6749,7 +6770,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, for (lfs_size_t i = 0; i < attr_count; i++) { // update any gstate if (attrs[i].tag == LFSR_TAG_GRM) { - lfs->grm = *(lfsr_grm_t*)attrs[i].data.u.buf.buffer; + lfs->grm = *lfsr_attr_grm(&attrs[i]); // keep track of the exact encoding on-disk lfsr_data_fromgrm(&lfs->grm, lfs->grm_g); @@ -6809,7 +6830,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // adjust mid mid += attrs[i].delta; - if (!lfsr_tag_isgrow(attrs[i].tag) && attrs[i].delta > 0) { + if (lfsr_attr_isinsert(&attrs[i])) { mid -= 1; } }