bmap: Decoding the gbmap in gstate now works

This is just a copy + edit of the grm logic, which raises the question
of if this logic can be generalized.
This commit is contained in:
Christopher Haster
2025-07-23 23:43:17 -05:00
parent 5f65b49ef8
commit 1537f6a430
+102 -1
View File
@@ -7665,16 +7665,31 @@ static int lfs3_data_readgrm(lfs3_t *lfs3, lfs3_data_t *data) {
return 0;
}
// predeclarations of other gstate, needed below
#if !defined(LFS3_RDONLY) && !defined(LFS3_2BONLY) && defined(LFS3_BMAP)
static lfs3_data_t lfs3_data_fromgbmap(const lfs3_t *lfs3,
uint8_t buffer[static LFS3_GBMAP_DSIZE]);
static int lfs3_data_readgbmap(lfs3_t *lfs3, lfs3_data_t *data);
#endif
// some mdir-related gstate things we need
// zero any pending gdeltas
static void lfs3_fs_flushgdelta(lfs3_t *lfs3) {
// TODO one cool trick would be to make these all contiguous so
// zeroing is one memset
// zero the gcksumdelta
lfs3->gcksum_d = 0;
// zero the grmdelta
lfs3_memset(lfs3->grm_d, 0, LFS3_GRM_DSIZE);
// zero the gbmapdelta
#ifdef LFS3_BMAP
lfs3_memset(lfs3->gbmap_d, 0, LFS3_GBMAP_DSIZE);
#endif
}
// commit any pending gdeltas
@@ -7685,6 +7700,11 @@ static void lfs3_fs_commitgdelta(lfs3_t *lfs3) {
// keep track of the on-disk grm
lfs3_data_fromgrm(lfs3, lfs3->grm_p);
// keep track of the on-disk gbmap
#ifdef LFS3_BMAP
lfs3_data_fromgbmap(lfs3, lfs3->gbmap_p);
#endif
}
#endif
@@ -7700,6 +7720,15 @@ static void lfs3_fs_revertgdelta(lfs3_t *lfs3) {
if (err) {
LFS3_UNREACHABLE();
}
// revert to the on-disk gbmap
#ifdef LFS3_BMAP
err = lfs3_data_readgbmap(lfs3,
&LFS3_DATA_BUF(lfs3->gbmap_p, LFS3_GBMAP_DSIZE));
if (err) {
LFS3_UNREACHABLE();
}
#endif
}
#endif
@@ -7749,6 +7778,48 @@ static int lfs3_rbyd_appendgdelta(lfs3_t *lfs3, lfs3_rbyd_t *rbyd) {
}
}
// pending gbmap state?
#ifdef LFS3_BMAP
uint8_t gbmapdelta_[LFS3_GBMAP_DSIZE];
lfs3_data_fromgbmap(lfs3, gbmapdelta_);
lfs3_memxor(gbmapdelta_, lfs3->gbmap_p, LFS3_GBMAP_DSIZE);
lfs3_memxor(gbmapdelta_, lfs3->gbmap_d, LFS3_GBMAP_DSIZE);
if (lfs3_memlen(gbmapdelta_, LFS3_GBMAP_DSIZE) != 0) {
// make sure to xor any existing delta
lfs3_data_t data;
lfs3_stag_t tag = lfs3_rbyd_lookup(lfs3, rbyd, -1, LFS3_TAG_GBMAPDELTA,
&data);
if (tag < 0 && tag != LFS3_ERR_NOENT) {
return tag;
}
uint8_t gbmapdelta[LFS3_GBMAP_DSIZE];
lfs3_memset(gbmapdelta, 0, LFS3_GBMAP_DSIZE);
if (tag != LFS3_ERR_NOENT) {
lfs3_ssize_t d = lfs3_data_read(lfs3, &data,
gbmapdelta, LFS3_GBMAP_DSIZE);
if (d < 0) {
return d;
}
}
lfs3_memxor(gbmapdelta_, gbmapdelta, LFS3_GBMAP_DSIZE);
// append to our rbyd, replacing any existing delta
lfs3_size_t size = lfs3_memlen(gbmapdelta_, LFS3_GBMAP_DSIZE);
int err = lfs3_rbyd_appendrattr(lfs3, rbyd, -1, LFS3_RATTR_BUF(
// opportunistically remove this tag if delta is all zero
(size == 0)
? LFS3_TAG_RM | LFS3_TAG_GBMAPDELTA
: LFS3_TAG_GBMAPDELTA, 0,
gbmapdelta_, size));
if (err) {
return err;
}
}
#endif
return 0;
}
#endif
@@ -7767,7 +7838,8 @@ static int lfs3_fs_consumegdelta(lfs3_t *lfs3, const lfs3_mdir_t *mdir) {
if (tag != LFS3_ERR_NOENT) {
uint8_t grmdelta[LFS3_GRM_DSIZE];
lfs3_ssize_t d = lfs3_data_read(lfs3, &data, grmdelta, LFS3_GRM_DSIZE);
lfs3_ssize_t d = lfs3_data_read(lfs3, &data,
grmdelta, LFS3_GRM_DSIZE);
if (d < 0) {
return d;
}
@@ -7775,6 +7847,22 @@ static int lfs3_fs_consumegdelta(lfs3_t *lfs3, const lfs3_mdir_t *mdir) {
lfs3_memxor(lfs3->grm_d, grmdelta, d);
}
// consume any gbmap deltas
#ifdef LFS3_BMAP
tag = lfs3_rbyd_lookup(lfs3, &mdir->r, -1, LFS3_TAG_GBMAPDELTA,
&data);
if (tag < 0 && tag != LFS3_ERR_NOENT) {
uint8_t gbmapdelta[LFS3_GBMAP_DSIZE];
lfs3_ssize_t d = lfs3_data_read(lfs3, &data,
gbmapdelta, LFS3_GBMAP_DSIZE);
if (d < 0) {
return d;
}
lfs3_memxor(lfs3->gbmap_d, gbmapdelta, d);
}
#endif
return 0;
}
@@ -15313,6 +15401,9 @@ static int lfs3_mountinited(lfs3_t *lfs3) {
// keep track of the current gstate on disk
#ifndef LFS3_RDONLY
lfs3_memcpy(lfs3->grm_p, lfs3->grm_d, LFS3_GRM_DSIZE);
#ifdef LFS3_BMAP
lfs3_memcpy(lfs3->gbmap_p, lfs3->gbmap_d, LFS3_GBMAP_DSIZE);
#endif
#endif
// decode grm so we can report any removed files as missing
@@ -15336,6 +15427,16 @@ static int lfs3_mountinited(lfs3_t *lfs3) {
lfs3_dbgmrid(lfs3, lfs3->grm.queue[0]));
}
// decode the global block-map
//
// this one is a bit less exciting
err = lfs3_data_readgbmap(lfs3,
&LFS3_DATA_BUF(lfs3->gbmap_d, LFS3_GBMAP_DSIZE));
if (err) {
// TODO switch to read-only?
return err;
}
return 0;
}