Actually made the previous commit work
The logic behind relying on pre-commit inlined state to clear any failed commits was sound, but built on the wrong assumption that file->inlined would always contain the mdir's block. This was not true for null-inlined, i.e. no inlined data, since this doesn't really live anywhere. Changed file's inlined state to track the mdir block, even when we have no inlined data. A bit redundant, but a nice invariant to rely on in lfsr_mdir_compact__. This invariant also only affects lfsr_mdir_compact__, since this is the only place inlined data can change blocks.
This commit is contained in:
@@ -4852,8 +4852,8 @@ static bool lfsr_mdir_isopened(lfs_t *lfs, int type,
|
||||
// inlined files correct
|
||||
#define LFSR_FILE_INLINED 0x80000000
|
||||
|
||||
static inline bool lfsr_inlined_isnull(const lfsr_inlined_t *inlined) {
|
||||
return inlined->u.weight == 0;
|
||||
static inline bool lfsr_inlined_hasnull(const lfsr_inlined_t *inlined) {
|
||||
return (lfs_size_t)inlined->u.weight == (LFSR_FILE_INLINED | 0);
|
||||
}
|
||||
|
||||
static inline bool lfsr_inlined_hassprout(const lfsr_inlined_t *inlined) {
|
||||
@@ -5548,8 +5548,18 @@ static int lfsr_mdir_compact__(lfs_t *lfs, lfsr_mdir_t *mdir_,
|
||||
opened;
|
||||
opened = opened->next) {
|
||||
lfsr_file_t *file = (lfsr_file_t*)opened;
|
||||
// no inlined data? we don't write a tag for these but we DO need to
|
||||
// update them, they may have been clobbered in a failed commit
|
||||
if (lfsr_inlined_hasnull(&file->inlined)
|
||||
&& lfsr_file_isunsynced(file)
|
||||
&& file->inlined.u.data.u.disk.block == mdir->u.rbyd.block
|
||||
&& (file->m.mdir.mid & lfsr_midrmask(lfs)) >= start_rid
|
||||
&& (lfs_size_t)(file->m.mdir.mid & lfsr_midrmask(lfs))
|
||||
< (lfs_size_t)end_rid) {
|
||||
file->inlined_.u.data = LFSR_DATA_DISK(mdir_->u.rbyd.block, 0, 0);
|
||||
|
||||
// inlined data?
|
||||
if (lfsr_inlined_hassprout(&file->inlined)
|
||||
} else if (lfsr_inlined_hassprout(&file->inlined)
|
||||
&& lfsr_file_isunsynced(file)
|
||||
&& file->inlined.u.data.u.disk.block == mdir->u.rbyd.block
|
||||
&& (file->m.mdir.mid & lfsr_midrmask(lfs)) >= start_rid
|
||||
@@ -8256,8 +8266,8 @@ int lfsr_dir_rewind(lfs_t *lfs, lfsr_dir_t *dir) {
|
||||
|
||||
/// File operations ///
|
||||
|
||||
static inline bool lfsr_file_isnull(const lfsr_file_t *file) {
|
||||
return lfsr_inlined_isnull(&file->inlined);
|
||||
static inline bool lfsr_file_hasnull(const lfsr_file_t *file) {
|
||||
return lfsr_inlined_hasnull(&file->inlined);
|
||||
}
|
||||
|
||||
static inline bool lfsr_file_hassprout(const lfsr_file_t *file) {
|
||||
@@ -8348,15 +8358,6 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
||||
}
|
||||
}
|
||||
|
||||
// setup file state
|
||||
file->flags = flags;
|
||||
file->cfg = cfg;
|
||||
file->pos = 0;
|
||||
// default inlined state
|
||||
file->inlined.u.data.u.disk.block = 0;
|
||||
file->inlined.u.data.u.disk.off = 0;
|
||||
file->inlined.u.data.u.disk.size = LFSR_FILE_INLINED | 0;
|
||||
|
||||
// lookup our parent
|
||||
lfsr_tag_t tag;
|
||||
lfsr_did_t did;
|
||||
@@ -8369,6 +8370,15 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
||||
return err;
|
||||
}
|
||||
|
||||
// setup file state
|
||||
file->flags = flags;
|
||||
file->cfg = cfg;
|
||||
file->pos = 0;
|
||||
// default inlined state
|
||||
// note we still keep track of the block when inlined is null, it's
|
||||
// a nice invariant to have
|
||||
file->inlined.u.data = LFSR_DATA_DISK(file->m.mdir.u.m.blocks[0], 0, 0);
|
||||
|
||||
// creating a new entry?
|
||||
if (err == LFS_ERR_NOENT) {
|
||||
if (!lfsr_flags_iscreat(flags)) {
|
||||
|
||||
Reference in New Issue
Block a user