Revert back to single typed linked-list for opened mdirs
While the multi per-type linked-lists were cool and could save RAM in
some structs (at the cost of RAM in the lfs_t struct), this is simpler,
and simpler is good.
The motivation to revert:
1. I noticed most file types have some sort of flags: files,
traversals (future), (not dirs but maybe in the future). These flags
can be merged with the type field to give us typed mdirs at almost
no RAM cost.
2. Using a single linked-list makes it cheaper to add more file types,
which may be useful for managing bookmarks (differently) and scratch
files.
This comes at a runtime cost, since all scans look at all opened
structs, but we really, _really_ don't care about a constant non-IO
runtime cost.
There are code benefits, since we don't need nested iterators to access
all opened mdirs, but also some code cost when we want to filter by
type. As expected stack took a small hit. Humorously, the struct savings
in lfs_t perfectly canceled out the struct hit to lfsr_dir_t:
code stack structs
before: 32992 2968 1080
after: 33004 (+0.0%) 2976 (+0.3%) 1080 (+0.0%)
This commit is contained in:
@@ -4705,12 +4705,12 @@ static lfs_ssize_t lfsr_sprout_estimate(lfs_t *lfs,
|
|||||||
const lfsr_data_t *sprout) {
|
const lfsr_data_t *sprout) {
|
||||||
// only include the last reference
|
// only include the last reference
|
||||||
const lfsr_data_t *last = NULL;
|
const lfsr_data_t *last = NULL;
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)
|
if (file_->type == LFS_TYPE_REG
|
||||||
|
&& lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_sprout_cmp(&file_->ftree.u.bsprout, sprout) == 0) {
|
&& lfsr_sprout_cmp(&file_->ftree.u.bsprout, sprout) == 0) {
|
||||||
last = &file_->ftree.u.bsprout;
|
last = &file_->ftree.u.bsprout;
|
||||||
}
|
}
|
||||||
@@ -4734,12 +4734,12 @@ static int lfsr_sprout_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
|||||||
|
|
||||||
// stage any opened inlined files with their new location so we
|
// stage any opened inlined files with their new location so we
|
||||||
// can update these later if our commit is a success
|
// can update these later if our commit is a success
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)
|
if (file_->type == LFS_TYPE_REG
|
||||||
|
&& lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_sprout_cmp(
|
&& lfsr_sprout_cmp(
|
||||||
&file_->ftree.u.bsprout,
|
&file_->ftree.u.bsprout,
|
||||||
sprout) == 0) {
|
sprout) == 0) {
|
||||||
@@ -4827,12 +4827,12 @@ static lfs_ssize_t lfsr_shrub_estimate(lfs_t *lfs,
|
|||||||
const lfsr_shrub_t *shrub) {
|
const lfsr_shrub_t *shrub) {
|
||||||
// only include the last reference
|
// only include the last reference
|
||||||
const lfsr_shrub_t *last = NULL;
|
const lfsr_shrub_t *last = NULL;
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)
|
if (file_->type == LFS_TYPE_REG
|
||||||
|
&& lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_shrub_cmp(&file_->ftree.u.bshrub, shrub) == 0) {
|
&& lfsr_shrub_cmp(&file_->ftree.u.bshrub, shrub) == 0) {
|
||||||
last = &file_->ftree.u.bshrub;
|
last = &file_->ftree.u.bshrub;
|
||||||
}
|
}
|
||||||
@@ -4861,12 +4861,12 @@ static int lfsr_shrub_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
|||||||
// update these later if our commit is a success
|
// update these later if our commit is a success
|
||||||
//
|
//
|
||||||
// this should include our current bshrub
|
// this should include our current bshrub
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)
|
if (file_->type == LFS_TYPE_REG
|
||||||
|
&& lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_shrub_cmp(&file_->ftree.u.bshrub, shrub) == 0) {
|
&& lfsr_shrub_cmp(&file_->ftree.u.bshrub, shrub) == 0) {
|
||||||
file_->ftree_.u.bshrub.blocks[0] = rbyd_->blocks[0];
|
file_->ftree_.u.bshrub.blocks[0] = rbyd_->blocks[0];
|
||||||
file_->ftree_.u.bshrub.trunk = rbyd_->trunk;
|
file_->ftree_.u.bshrub.trunk = rbyd_->trunk;
|
||||||
@@ -5029,39 +5029,6 @@ static inline bool lfsr_mdir_isroot(const lfsr_mdir_t *mdir) {
|
|||||||
return lfsr_mid_isroot(mdir->mid);
|
return lfsr_mid_isroot(mdir->mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// track opened mdirs that may need to by updated
|
|
||||||
static void lfsr_mdir_addopened(lfs_t *lfs, int type,
|
|
||||||
lfsr_openedmdir_t *opened) {
|
|
||||||
opened->next = lfs->opened[type-LFS_TYPE_REG];
|
|
||||||
lfs->opened[type-LFS_TYPE_REG] = opened;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lfsr_mdir_removeopened(lfs_t *lfs, int type,
|
|
||||||
lfsr_openedmdir_t *opened) {
|
|
||||||
for (lfsr_openedmdir_t **p = &lfs->opened[type-LFS_TYPE_REG];
|
|
||||||
*p;
|
|
||||||
p = &(*p)->next) {
|
|
||||||
if (*p == opened) {
|
|
||||||
*p = (*p)->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool lfsr_mdir_isopened(lfs_t *lfs, int type,
|
|
||||||
const lfsr_openedmdir_t *opened) {
|
|
||||||
for (lfsr_openedmdir_t *p = lfs->opened[type-LFS_TYPE_REG];
|
|
||||||
p;
|
|
||||||
p = p->next) {
|
|
||||||
if (p == opened) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// mdir operations
|
// mdir operations
|
||||||
static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir,
|
static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir,
|
||||||
lfsr_smid_t mid, const lfsr_mptr_t *mptr) {
|
lfsr_smid_t mid, const lfsr_mptr_t *mptr) {
|
||||||
@@ -5150,6 +5117,32 @@ static int lfsr_mdir_lookupwide(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
|||||||
tag_, data_);
|
tag_, data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// track opened mdirs to keep state in-sync
|
||||||
|
static void lfsr_addopened(lfs_t *lfs, lfsr_opened_t *opened) {
|
||||||
|
opened->next = lfs->opened;
|
||||||
|
lfs->opened = opened;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lfsr_removeopened(lfs_t *lfs, lfsr_opened_t *opened) {
|
||||||
|
for (lfsr_opened_t **p = &lfs->opened; *p; p = &(*p)->next) {
|
||||||
|
if (*p == opened) {
|
||||||
|
*p = (*p)->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lfsr_isopened(lfs_t *lfs, const lfsr_opened_t *opened) {
|
||||||
|
for (lfsr_opened_t *p = lfs->opened; p; p = p->next) {
|
||||||
|
if (p == opened) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Metadata-tree things ///
|
/// Metadata-tree things ///
|
||||||
|
|
||||||
@@ -5662,13 +5655,13 @@ static lfs_ssize_t lfsr_mdir_estimate__(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
|||||||
// this is O(n^2), but littlefs is unlikely to have many open
|
// this is O(n^2), but littlefs is unlikely to have many open
|
||||||
// files, I suppose if this becomes a problem we could sort
|
// files, I suppose if this becomes a problem we could sort
|
||||||
// opened files by mid
|
// opened files by mid
|
||||||
for (lfsr_openedmdir_t *opened = lfs->opened[
|
for (lfsr_opened_t *opened = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened;
|
opened;
|
||||||
opened = opened->next) {
|
opened = opened->next) {
|
||||||
lfsr_file_t *file = (lfsr_file_t*)opened;
|
lfsr_file_t *file = (lfsr_file_t*)opened;
|
||||||
// belongs to our mdir + rid?
|
// belongs to our mdir + rid?
|
||||||
if (lfsr_mdir_cmp(&file->mdir, mdir) != 0
|
if (file->type != LFS_TYPE_REG
|
||||||
|
|| lfsr_mdir_cmp(&file->mdir, mdir) != 0
|
||||||
|| lfsr_mdir_rid(lfs, &file->mdir) != rid) {
|
|| lfsr_mdir_rid(lfs, &file->mdir) != rid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -5804,13 +5797,13 @@ static int lfsr_mdir_compact__(lfs_t *lfs, lfsr_mdir_t *mdir_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we're not quite done! we also need to bring over any unsynced files
|
// we're not quite done! we also need to bring over any unsynced files
|
||||||
for (lfsr_openedmdir_t *opened = lfs->opened[
|
for (lfsr_opened_t *opened = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened;
|
opened;
|
||||||
opened = opened->next) {
|
opened = opened->next) {
|
||||||
lfsr_file_t *file = (lfsr_file_t*)opened;
|
lfsr_file_t *file = (lfsr_file_t*)opened;
|
||||||
// belongs to our mdir?
|
// belongs to our mdir?
|
||||||
if (lfsr_mdir_cmp(&file->mdir, mdir) != 0
|
if (file->type != LFS_TYPE_REG
|
||||||
|
|| lfsr_mdir_cmp(&file->mdir, mdir) != 0
|
||||||
|| lfsr_mdir_rid(lfs, &file->mdir) < start_rid
|
|| lfsr_mdir_rid(lfs, &file->mdir) < start_rid
|
||||||
|| (lfsr_rid_t)lfsr_mdir_rid(lfs, &file->mdir)
|
|| (lfsr_rid_t)lfsr_mdir_rid(lfs, &file->mdir)
|
||||||
>= (lfsr_rid_t)end_rid) {
|
>= (lfsr_rid_t)end_rid) {
|
||||||
@@ -5965,13 +5958,11 @@ static int lfsr_mroot_commit(lfs_t *lfs,
|
|||||||
// mark any copies of our mroot as unerased
|
// mark any copies of our mroot as unerased
|
||||||
lfs->mroot.rbyd.eoff = -1;
|
lfs->mroot.rbyd.eoff = -1;
|
||||||
|
|
||||||
for (int type = LFS_TYPE_REG; type < LFS_TYPE_REG+3; type++) {
|
for (lfsr_opened_t *opened = lfs->opened;
|
||||||
for (lfsr_openedmdir_t *opened = lfs->opened[type-LFS_TYPE_REG];
|
opened;
|
||||||
opened;
|
opened = opened->next) {
|
||||||
opened = opened->next) {
|
if (lfsr_mdir_cmp(&opened->mdir, &lfs->mroot) == 0) {
|
||||||
if (lfsr_mdir_cmp(&opened->mdir, &lfs->mroot) == 0) {
|
opened->mdir.rbyd.eoff = -1;
|
||||||
opened->mdir.rbyd.eoff = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6084,19 +6075,17 @@ static int lfsr_mroot_commit(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// success? update in-device state, we must not error at this point
|
// success? update in-device state, we must not error at this point
|
||||||
for (int type = LFS_TYPE_REG; type < LFS_TYPE_REG+3; type++) {
|
for (lfsr_opened_t *opened = lfs->opened;
|
||||||
for (lfsr_openedmdir_t *opened = lfs->opened[type-LFS_TYPE_REG];
|
opened;
|
||||||
opened;
|
opened = opened->next) {
|
||||||
opened = opened->next) {
|
if (lfsr_mdir_cmp(&opened->mdir, &lfs->mroot) == 0) {
|
||||||
if (lfsr_mdir_cmp(&opened->mdir, &lfs->mroot) == 0) {
|
// update any opened mdirs in our mroot
|
||||||
// update any opened mdirs in our mroot
|
opened->mdir.rbyd = mroot_.rbyd;
|
||||||
opened->mdir.rbyd = mroot_.rbyd;
|
|
||||||
|
|
||||||
// update staged changes
|
// update staged changes
|
||||||
if (type == LFS_TYPE_REG) {
|
if (opened->type == LFS_TYPE_REG) {
|
||||||
lfsr_file_t *file = (lfsr_file_t*)opened;
|
lfsr_file_t *file = (lfsr_file_t*)opened;
|
||||||
file->ftree = file->ftree_;
|
file->ftree = file->ftree_;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6234,21 +6223,19 @@ static int lfsr_mdir_drop(lfs_t *lfs, const lfsr_mdir_t *mdir) {
|
|||||||
// keep track of the exact encoding on-disk
|
// keep track of the exact encoding on-disk
|
||||||
lfsr_data_fromgrm(&lfs->grm, lfs->grm_g);
|
lfsr_data_fromgrm(&lfs->grm, lfs->grm_g);
|
||||||
|
|
||||||
for (int type = LFS_TYPE_REG; type < LFS_TYPE_REG+3; type++) {
|
for (lfsr_opened_t *opened = lfs->opened;
|
||||||
for (lfsr_openedmdir_t *opened = lfs->opened[type-LFS_TYPE_REG];
|
opened;
|
||||||
opened;
|
opened = opened->next) {
|
||||||
opened = opened->next) {
|
// update mids
|
||||||
// update mids
|
if (opened->mdir.mid > mdir->mid) {
|
||||||
if (opened->mdir.mid > mdir->mid) {
|
opened->mdir.mid -= lfsr_mweight(lfs);
|
||||||
opened->mdir.mid -= lfsr_mweight(lfs);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// update directory bookmarks
|
// update directory bookmarks
|
||||||
if (type == LFS_TYPE_DIR) {
|
if (opened->type == LFS_TYPE_DIR) {
|
||||||
lfsr_dir_t *dir = (lfsr_dir_t*)opened;
|
lfsr_dir_t *dir = (lfsr_dir_t*)opened;
|
||||||
if (dir->bookmark > mdir->mid) {
|
if (dir->bookmark > mdir->mid) {
|
||||||
dir->bookmark -= lfsr_mweight(lfs);
|
dir->bookmark -= lfsr_mweight(lfs);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6287,24 +6274,22 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int type = LFS_TYPE_REG; type < LFS_TYPE_REG+3; type++) {
|
for (lfsr_opened_t *opened = lfs->opened;
|
||||||
for (lfsr_openedmdir_t *opened = lfs->opened[type-LFS_TYPE_REG];
|
opened;
|
||||||
opened;
|
opened = opened->next) {
|
||||||
opened = opened->next) {
|
// mark any copies of our mdir as unerased in case we fail
|
||||||
// mark any copies of our mdir as unerased in case we fail
|
//
|
||||||
//
|
// note we need to not mark the mroot as unerased, because that
|
||||||
// note we need to not mark the mroot as unerased, because that
|
// would force the mroot to always compact
|
||||||
// would force the mroot to always compact
|
//
|
||||||
//
|
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0) {
|
||||||
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0) {
|
opened->mdir.rbyd.eoff = -1;
|
||||||
opened->mdir.rbyd.eoff = -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// stage any bsprouts/bshrubs
|
// stage any bsprouts/bshrubs
|
||||||
if (type == LFS_TYPE_REG) {
|
if (opened->type == LFS_TYPE_REG) {
|
||||||
lfsr_file_t *file = (lfsr_file_t*)opened;
|
lfsr_file_t *file = (lfsr_file_t*)opened;
|
||||||
file->ftree_ = file->ftree;
|
file->ftree_ = file->ftree;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6569,108 +6554,106 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int type = LFS_TYPE_REG; type < LFS_TYPE_REG+3; type++) {
|
for (lfsr_opened_t *opened = lfs->opened;
|
||||||
for (lfsr_openedmdir_t *opened = lfs->opened[type-LFS_TYPE_REG];
|
opened;
|
||||||
opened;
|
opened = opened->next) {
|
||||||
opened = opened->next) {
|
// update staged changes
|
||||||
// update staged changes
|
if (opened->type == LFS_TYPE_REG) {
|
||||||
if (type == LFS_TYPE_REG) {
|
lfsr_file_t *file = (lfsr_file_t*)opened;
|
||||||
lfsr_file_t *file = (lfsr_file_t*)opened;
|
file->ftree = file->ftree_;
|
||||||
file->ftree = file->ftree_;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// avoid double updating current mdir
|
// avoid double updating current mdir
|
||||||
if (&opened->mdir == mdir) {
|
if (&opened->mdir == mdir) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first play out any attrs that change our rid
|
// first play out any attrs that change our rid
|
||||||
for (lfs_size_t i = 0; i < attr_count; i++) {
|
for (lfs_size_t i = 0; i < attr_count; i++) {
|
||||||
// adjust opened mdirs?
|
// adjust opened mdirs?
|
||||||
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0
|
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0
|
||||||
&& opened->mdir.mid >= attrs[i].rid) {
|
&& opened->mdir.mid >= attrs[i].rid) {
|
||||||
// removed?
|
// removed?
|
||||||
if (opened->mdir.mid < attrs[i].rid - attrs[i].delta) {
|
if (opened->mdir.mid < attrs[i].rid - attrs[i].delta) {
|
||||||
// for dir's second mdir (the position mdir), move
|
// for dir's second mdir (the position mdir), move
|
||||||
// on to the next rid
|
// on to the next rid
|
||||||
if (type == LFS_TYPE_DIR) {
|
if (opened->type == LFS_TYPE_DIR) {
|
||||||
opened->mdir.mid = attrs[i].rid;
|
opened->mdir.mid = attrs[i].rid;
|
||||||
// for normal mdirs mark as dropped
|
// for normal mdirs mark as dropped
|
||||||
} else {
|
|
||||||
opened->mdir.mid = -1;
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
opened->mdir.mid += attrs[i].delta;
|
opened->mdir.mid = -1;
|
||||||
// adjust dir position?
|
goto next;
|
||||||
if (type == LFS_TYPE_DIR) {
|
|
||||||
((lfsr_dir_t*)opened)->pos += attrs[i].delta;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (opened->mdir.mid > mdir->mid) {
|
} else {
|
||||||
|
opened->mdir.mid += attrs[i].delta;
|
||||||
// adjust dir position?
|
// adjust dir position?
|
||||||
if (type == LFS_TYPE_DIR) {
|
if (opened->type == LFS_TYPE_DIR) {
|
||||||
((lfsr_dir_t*)opened)->pos += attrs[i].delta;
|
((lfsr_dir_t*)opened)->pos += attrs[i].delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// update any opened mdirs if we had a split or drop
|
|
||||||
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0) {
|
|
||||||
if (mdelta > 0
|
|
||||||
&& lfsr_mdir_rid(lfs, &opened->mdir)
|
|
||||||
>= mdir_.rbyd.weight) {
|
|
||||||
opened->mdir.mid += lfsr_mweight(lfs)
|
|
||||||
- mdir_.rbyd.weight;
|
|
||||||
opened->mdir.rbyd = msibling_.rbyd;
|
|
||||||
} else {
|
|
||||||
opened->mdir.rbyd = mdir_.rbyd;
|
|
||||||
}
|
|
||||||
} else if (opened->mdir.mid > mdir->mid) {
|
} else if (opened->mdir.mid > mdir->mid) {
|
||||||
opened->mdir.mid += mdelta;
|
// adjust dir position?
|
||||||
|
if (opened->type == LFS_TYPE_DIR) {
|
||||||
|
((lfsr_dir_t*)opened)->pos += attrs[i].delta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (type == LFS_TYPE_DIR) {
|
// update any opened mdirs if we had a split or drop
|
||||||
// update any changes to directory bookmarks/positions, this
|
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0) {
|
||||||
// gets a bit tricky
|
if (mdelta > 0
|
||||||
lfsr_dir_t *dir = (lfsr_dir_t*)opened;
|
&& lfsr_mdir_rid(lfs, &opened->mdir)
|
||||||
for (lfs_size_t i = 0; i < attr_count; i++) {
|
>= mdir_.rbyd.weight) {
|
||||||
// TODO clean this up a bit?
|
opened->mdir.mid += lfsr_mweight(lfs)
|
||||||
// adjust opened mdirs?
|
- mdir_.rbyd.weight;
|
||||||
if (lfsr_mid_bid(lfs, dir->bookmark)
|
opened->mdir.rbyd = msibling_.rbyd;
|
||||||
== lfsr_mid_bid(lfs, lfs_smax32(mdir->mid, 0))
|
} else {
|
||||||
&& dir->bookmark >= attrs[i].rid) {
|
opened->mdir.rbyd = mdir_.rbyd;
|
||||||
// removed?
|
}
|
||||||
if (dir->bookmark < attrs[i].rid - attrs[i].delta) {
|
} else if (opened->mdir.mid > mdir->mid) {
|
||||||
// mark dir as dropped
|
opened->mdir.mid += mdelta;
|
||||||
dir->mdir.mid = -1;
|
}
|
||||||
dir->bookmark = -1;
|
|
||||||
goto next;
|
if (opened->type == LFS_TYPE_DIR) {
|
||||||
} else {
|
// update any changes to directory bookmarks/positions, this
|
||||||
dir->bookmark += attrs[i].delta;
|
// gets a bit tricky
|
||||||
// adjust dir position?
|
lfsr_dir_t *dir = (lfsr_dir_t*)opened;
|
||||||
dir->pos -= attrs[i].delta;
|
for (lfs_size_t i = 0; i < attr_count; i++) {
|
||||||
}
|
// TODO clean this up a bit?
|
||||||
} else if (dir->bookmark > mdir->mid) {
|
// adjust opened mdirs?
|
||||||
|
if (lfsr_mid_bid(lfs, dir->bookmark)
|
||||||
|
== lfsr_mid_bid(lfs, lfs_smax32(mdir->mid, 0))
|
||||||
|
&& dir->bookmark >= attrs[i].rid) {
|
||||||
|
// removed?
|
||||||
|
if (dir->bookmark < attrs[i].rid - attrs[i].delta) {
|
||||||
|
// mark dir as dropped
|
||||||
|
dir->mdir.mid = -1;
|
||||||
|
dir->bookmark = -1;
|
||||||
|
goto next;
|
||||||
|
} else {
|
||||||
|
dir->bookmark += attrs[i].delta;
|
||||||
// adjust dir position?
|
// adjust dir position?
|
||||||
dir->pos -= attrs[i].delta;
|
dir->pos -= attrs[i].delta;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (lfsr_mid_bid(lfs, dir->bookmark)
|
|
||||||
== lfsr_mid_bid(lfs, lfs_smax32(mdir->mid, 0))) {
|
|
||||||
if (mdelta > 0
|
|
||||||
&& lfsr_mid_rid(lfs, dir->bookmark)
|
|
||||||
>= mdir_.rbyd.weight) {
|
|
||||||
dir->bookmark += lfsr_mweight(lfs)
|
|
||||||
- mdir_.rbyd.weight;
|
|
||||||
}
|
|
||||||
} else if (dir->bookmark > mdir->mid) {
|
} else if (dir->bookmark > mdir->mid) {
|
||||||
dir->bookmark += mdelta;
|
// adjust dir position?
|
||||||
|
dir->pos -= attrs[i].delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next:;
|
|
||||||
|
if (lfsr_mid_bid(lfs, dir->bookmark)
|
||||||
|
== lfsr_mid_bid(lfs, lfs_smax32(mdir->mid, 0))) {
|
||||||
|
if (mdelta > 0
|
||||||
|
&& lfsr_mid_rid(lfs, dir->bookmark)
|
||||||
|
>= mdir_.rbyd.weight) {
|
||||||
|
dir->bookmark += lfsr_mweight(lfs)
|
||||||
|
- mdir_.rbyd.weight;
|
||||||
|
}
|
||||||
|
} else if (dir->bookmark > mdir->mid) {
|
||||||
|
dir->bookmark += mdelta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
next:;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update mdir to follow requested rid
|
// update mdir to follow requested rid
|
||||||
@@ -6979,12 +6962,14 @@ typedef struct lfsr_traversal {
|
|||||||
// btree traversal state, only valid when traversing the mtree
|
// btree traversal state, only valid when traversing the mtree
|
||||||
lfsr_btraversal_t mtraversal;
|
lfsr_btraversal_t mtraversal;
|
||||||
// opened file state, only valid when traversing opened files
|
// opened file state, only valid when traversing opened files
|
||||||
const lfsr_openedmdir_t *opened;
|
const lfsr_opened_t *opened;
|
||||||
} u;
|
} u;
|
||||||
// we really don't want to pay the RAM cost for a full file,
|
// we really don't want to pay the RAM cost for a full file,
|
||||||
// so only store the relevant bits, is this a hack? yes
|
// so only store the relevant bits, is this a hack? yes
|
||||||
struct {
|
struct {
|
||||||
lfsr_openedmdir_t *next;
|
lfsr_opened_t *next;
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t flags;
|
||||||
lfsr_mdir_t mdir;
|
lfsr_mdir_t mdir;
|
||||||
lfsr_ftree_t ftree;
|
lfsr_ftree_t ftree;
|
||||||
} file;
|
} file;
|
||||||
@@ -7183,7 +7168,7 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
case LFSR_TRAVERSAL_MTREE:;
|
case LFSR_TRAVERSAL_MTREE:;
|
||||||
// no mtree? transition to traversing any opened mdirs
|
// no mtree? transition to traversing any opened mdirs
|
||||||
if (lfsr_mtree_ismptr(lfs)) {
|
if (lfsr_mtree_ismptr(lfs)) {
|
||||||
traversal->u.opened = lfs->opened[LFS_TYPE_REG-LFS_TYPE_REG];
|
traversal->u.opened = lfs->opened;
|
||||||
traversal->state = LFSR_TRAVERSAL_OPENED;
|
traversal->state = LFSR_TRAVERSAL_OPENED;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -7197,8 +7182,7 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
if (err) {
|
if (err) {
|
||||||
// end of mtree? transition to traversing any opened mdirs
|
// end of mtree? transition to traversing any opened mdirs
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
traversal->u.opened
|
traversal->u.opened = lfs->opened;
|
||||||
= lfs->opened[LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
traversal->state = LFSR_TRAVERSAL_OPENED;
|
traversal->state = LFSR_TRAVERSAL_OPENED;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -7325,7 +7309,13 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start traversing
|
// skip non-files
|
||||||
|
if (traversal->u.opened->type != LFS_TYPE_REG) {
|
||||||
|
traversal->u.opened = traversal->u.opened->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start traversing the file
|
||||||
const lfsr_file_t *file = (const lfsr_file_t*)traversal->u.opened;
|
const lfsr_file_t *file = (const lfsr_file_t*)traversal->u.opened;
|
||||||
traversal->file.mdir = file->mdir;
|
traversal->file.mdir = file->mdir;
|
||||||
traversal->file.ftree = file->ftree;
|
traversal->file.ftree = file->ftree;
|
||||||
@@ -8318,7 +8308,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
|
|||||||
|
|
||||||
// Check if we have a collision. If we do, search for the next
|
// Check if we have a collision. If we do, search for the next
|
||||||
// available did
|
// available did
|
||||||
lfsr_openedmdir_t bookmark;
|
lfsr_opened_t bookmark;
|
||||||
while (true) {
|
while (true) {
|
||||||
err = lfsr_mtree_namelookup(lfs, did_, NULL, 0,
|
err = lfsr_mtree_namelookup(lfs, did_, NULL, 0,
|
||||||
&bookmark.mdir, NULL, NULL);
|
&bookmark.mdir, NULL, NULL);
|
||||||
@@ -8349,7 +8339,8 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
|
|||||||
// the bookmark first risks inserting the bookmark before the metadata
|
// the bookmark first risks inserting the bookmark before the metadata
|
||||||
// entry, which breaks things.
|
// entry, which breaks things.
|
||||||
//
|
//
|
||||||
lfsr_mdir_addopened(lfs, LFS_TYPE_INTERNAL, &bookmark);
|
bookmark.type = 0;
|
||||||
|
lfsr_addopened(lfs, &bookmark);
|
||||||
|
|
||||||
// commit our new directory into our parent, creating a grm to self-remove
|
// commit our new directory into our parent, creating a grm to self-remove
|
||||||
// in case of powerloss
|
// in case of powerloss
|
||||||
@@ -8364,7 +8355,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
|
|||||||
goto failed_with_bookmark;
|
goto failed_with_bookmark;
|
||||||
}
|
}
|
||||||
|
|
||||||
lfsr_mdir_removeopened(lfs, LFS_TYPE_INTERNAL, &bookmark);
|
lfsr_removeopened(lfs, &bookmark);
|
||||||
|
|
||||||
// commit our bookmark and zero the grm, the bookmark tag is an empty
|
// commit our bookmark and zero the grm, the bookmark tag is an empty
|
||||||
// entry that marks our did as allocated
|
// entry that marks our did as allocated
|
||||||
@@ -8378,7 +8369,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_with_bookmark:
|
failed_with_bookmark:
|
||||||
lfsr_mdir_removeopened(lfs, LFS_TYPE_REG, &bookmark);
|
lfsr_removeopened(lfs, &bookmark);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8723,6 +8714,9 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) {
|
|||||||
return LFS_ERR_NOTDIR;
|
return LFS_ERR_NOTDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup dir state
|
||||||
|
dir->type = LFS_TYPE_DIR;
|
||||||
|
|
||||||
// read our did from the mdir, unless we're root
|
// read our did from the mdir, unless we're root
|
||||||
if (lfsr_mdir_isroot(&mdir)) {
|
if (lfsr_mdir_isroot(&mdir)) {
|
||||||
dir->did = 0;
|
dir->did = 0;
|
||||||
@@ -8748,13 +8742,13 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add to tracked mdirs
|
// add to tracked mdirs
|
||||||
lfsr_mdir_addopened(lfs, LFS_TYPE_DIR, (lfsr_openedmdir_t*)dir);
|
lfsr_addopened(lfs, (lfsr_opened_t*)dir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfsr_dir_close(lfs_t *lfs, lfsr_dir_t *dir) {
|
int lfsr_dir_close(lfs_t *lfs, lfsr_dir_t *dir) {
|
||||||
// remove from tracked mdirs
|
// remove from tracked mdirs
|
||||||
lfsr_mdir_removeopened(lfs, LFS_TYPE_DIR, (lfsr_openedmdir_t*)dir);
|
lfsr_removeopened(lfs, (lfsr_opened_t*)dir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8988,6 +8982,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup file state
|
// setup file state
|
||||||
|
file->type = LFS_TYPE_REG;
|
||||||
file->flags = flags;
|
file->flags = flags;
|
||||||
file->cfg = cfg;
|
file->cfg = cfg;
|
||||||
file->pos = 0;
|
file->pos = 0;
|
||||||
@@ -9121,8 +9116,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add to tracked mdirs
|
// add to tracked mdirs
|
||||||
lfsr_mdir_addopened(lfs, LFS_TYPE_REG, (lfsr_openedmdir_t*)file);
|
lfsr_addopened(lfs, (lfsr_opened_t*)file);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_with_buffer:;
|
failed_with_buffer:;
|
||||||
@@ -9157,7 +9151,7 @@ int lfsr_file_close(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove from tracked mdirs
|
// remove from tracked mdirs
|
||||||
lfsr_mdir_removeopened(lfs, LFS_TYPE_REG, (lfsr_openedmdir_t*)file);
|
lfsr_removeopened(lfs, (lfsr_opened_t*)file);
|
||||||
|
|
||||||
// clean up memory
|
// clean up memory
|
||||||
if (!file->cfg->buffer) {
|
if (!file->cfg->buffer) {
|
||||||
@@ -9210,12 +9204,12 @@ static lfs_ssize_t lfsr_file_estimate(lfs_t *lfs, const lfsr_file_t *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this includes our current shrub
|
// this includes our current shrub
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (file_->mdir.mid == file->mdir.mid) {
|
if (file_->type == LFS_TYPE_REG
|
||||||
|
&& file_->mdir.mid == file->mdir.mid) {
|
||||||
if (lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)) {
|
if (lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)) {
|
||||||
lfs_ssize_t dsize = lfsr_sprout_estimate(lfs,
|
lfs_ssize_t dsize = lfsr_sprout_estimate(lfs,
|
||||||
&file_->ftree.u.bsprout);
|
&file_->ftree.u.bsprout);
|
||||||
@@ -9480,12 +9474,12 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
|
|
||||||
// before we touch anything, we need to mark all other references
|
// before we touch anything, we need to mark all other references
|
||||||
// as unerased
|
// as unerased
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (file_ != file
|
if (file_->type == LFS_TYPE_REG
|
||||||
|
&& file_ != file
|
||||||
&& lfsr_ftree_isbshruborbtree(&file_->ftree)
|
&& lfsr_ftree_isbshruborbtree(&file_->ftree)
|
||||||
&& lfsr_btree_cmp(
|
&& lfsr_btree_cmp(
|
||||||
&file_->ftree.u.btree,
|
&file_->ftree.u.btree,
|
||||||
@@ -9578,15 +9572,14 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update _all_ shrubs with the new estimate
|
// update _all_ shrubs with the new estimate
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (file_->mdir.mid == file->mdir.mid) {
|
if (file_->type == LFS_TYPE_REG
|
||||||
if (lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)) {
|
&& file_->mdir.mid == file->mdir.mid
|
||||||
file_->ftree.u.bshrub.estimate = estimate;
|
&& lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)) {
|
||||||
}
|
file_->ftree.u.bshrub.estimate = estimate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LFS_ASSERT(file->ftree.u.bshrub.estimate = (lfs_size_t)estimate);
|
LFS_ASSERT(file->ftree.u.bshrub.estimate = (lfs_size_t)estimate);
|
||||||
@@ -10786,12 +10779,12 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// but do update other file handles
|
// but do update other file handles
|
||||||
for (lfsr_openedmdir_t *opened_ = lfs->opened[
|
for (lfsr_opened_t *opened_ = lfs->opened;
|
||||||
LFS_TYPE_REG-LFS_TYPE_REG];
|
|
||||||
opened_;
|
opened_;
|
||||||
opened_ = opened_->next) {
|
opened_ = opened_->next) {
|
||||||
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
|
||||||
if (file_->mdir.mid == file->mdir.mid
|
if (file_->type == LFS_TYPE_REG
|
||||||
|
&& file_->mdir.mid == file->mdir.mid
|
||||||
// don't double update
|
// don't double update
|
||||||
&& file_ != file
|
&& file_ != file
|
||||||
// don't update desynced file handles
|
// don't update desynced file handles
|
||||||
@@ -14611,10 +14604,8 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
//
|
//
|
||||||
lfs->mbits = lfs_nlog2(lfs->cfg->block_size/16);
|
lfs->mbits = lfs_nlog2(lfs->cfg->block_size/16);
|
||||||
|
|
||||||
// zero linked-lists of opened mdirs
|
// zero linked-list of opened mdirs
|
||||||
lfs->opened[LFS_TYPE_REG - LFS_TYPE_REG] = NULL;
|
lfs->opened = NULL;
|
||||||
lfs->opened[LFS_TYPE_DIR - LFS_TYPE_REG] = NULL;
|
|
||||||
lfs->opened[LFS_TYPE_INTERNAL - LFS_TYPE_REG] = NULL;
|
|
||||||
|
|
||||||
// zero gstate
|
// zero gstate
|
||||||
memset(lfs->grm_g, 0, LFSR_GRM_DSIZE);
|
memset(lfs->grm_g, 0, LFSR_GRM_DSIZE);
|
||||||
|
|||||||
@@ -116,39 +116,8 @@ enum lfs_error {
|
|||||||
// File types
|
// File types
|
||||||
enum lfs_type {
|
enum lfs_type {
|
||||||
// file types
|
// file types
|
||||||
LFS_TYPE_REG = 1,
|
LFS_TYPE_REG = 1,
|
||||||
LFS_TYPE_DIR = 2,
|
LFS_TYPE_DIR = 2,
|
||||||
|
|
||||||
// used internally, don't use this
|
|
||||||
LFS_TYPE_INTERNAL = 3,
|
|
||||||
|
|
||||||
// // internally used types
|
|
||||||
// LFS_TYPE_SPLICE = 0x400,
|
|
||||||
// LFS_TYPE_NAME = 0x000,
|
|
||||||
// LFS_TYPE_STRUCT = 0x200,
|
|
||||||
// LFS_TYPE_USERATTR = 0x300,
|
|
||||||
// LFS_TYPE_FROM = 0x100,
|
|
||||||
// LFS_TYPE_TAIL = 0x600,
|
|
||||||
// LFS_TYPE_GLOBALS = 0x700,
|
|
||||||
// LFS_TYPE_CRC = 0x500,
|
|
||||||
//
|
|
||||||
// // internally used type specializations
|
|
||||||
// LFS_TYPE_CREATE = 0x401,
|
|
||||||
// LFS_TYPE_DELETE = 0x4ff,
|
|
||||||
// LFS_TYPE_SUPERBLOCK = 0x0ff,
|
|
||||||
// LFS_TYPE_DIRSTRUCT = 0x200,
|
|
||||||
// LFS_TYPE_CTZSTRUCT = 0x202,
|
|
||||||
// LFS_TYPE_INLINESTRUCT = 0x201,
|
|
||||||
// LFS_TYPE_SOFTTAIL = 0x600,
|
|
||||||
// LFS_TYPE_HARDTAIL = 0x601,
|
|
||||||
// LFS_TYPE_MOVESTATE = 0x7ff,
|
|
||||||
// LFS_TYPE_CCRC = 0x500,
|
|
||||||
// LFS_TYPE_FCRC = 0x5ff,
|
|
||||||
//
|
|
||||||
// // internal chip sources
|
|
||||||
// LFS_FROM_NOOP = 0x000,
|
|
||||||
// LFS_FROM_MOVE = 0x101,
|
|
||||||
// LFS_FROM_USERATTRS = 0x102,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// File open flags
|
// File open flags
|
||||||
@@ -158,18 +127,18 @@ enum lfs_open_flags {
|
|||||||
#ifndef LFS_READONLY
|
#ifndef LFS_READONLY
|
||||||
LFS_O_WRONLY = 2, // Open a file as write only
|
LFS_O_WRONLY = 2, // Open a file as write only
|
||||||
LFS_O_RDWR = 3, // Open a file as read and write
|
LFS_O_RDWR = 3, // Open a file as read and write
|
||||||
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
|
LFS_O_CREAT = 0x0004, // Create a file if it does not exist
|
||||||
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
LFS_O_EXCL = 0x0008, // Fail if a file already exists
|
||||||
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
LFS_O_TRUNC = 0x0010, // Truncate the existing file to zero size
|
||||||
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
LFS_O_APPEND = 0x0020, // Move to end of file on every write
|
||||||
LFS_O_SYNC = 0x1000, // Sync metadata on every write
|
LFS_O_SYNC = 0x0040, // Sync metadata on every write
|
||||||
LFS_O_DESYNC = 0x2000, // Do not sync or recieve file updates
|
LFS_O_DESYNC = 0x0080, // Do not sync or recieve file updates
|
||||||
LFS_O_FLUSH = 0x4000, // Flush data on every write
|
LFS_O_FLUSH = 0x0100, // Flush data on every write
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// internally used flags
|
// internally used flags
|
||||||
LFS_F_UNFLUSHED = 0x010000, // File's data does not match storage
|
LFS_F_UNFLUSHED = 0x1000, // File's data does not match storage
|
||||||
LFS_F_UNSYNCED = 0x020000, // File's metadata does not match storage
|
LFS_F_UNSYNCED = 0x2000, // File's metadata does not match storage
|
||||||
};
|
};
|
||||||
|
|
||||||
// File seek flags
|
// File seek flags
|
||||||
@@ -387,10 +356,12 @@ typedef struct lfsr_mdir {
|
|||||||
lfsr_rbyd_t rbyd;
|
lfsr_rbyd_t rbyd;
|
||||||
} lfsr_mdir_t;
|
} lfsr_mdir_t;
|
||||||
|
|
||||||
typedef struct lfsr_openedmdir {
|
typedef struct lfsr_opened {
|
||||||
struct lfsr_openedmdir *next;
|
struct lfsr_opened *next;
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t flags;
|
||||||
lfsr_mdir_t mdir;
|
lfsr_mdir_t mdir;
|
||||||
} lfsr_openedmdir_t;
|
} lfsr_opened_t;
|
||||||
|
|
||||||
// space for:
|
// space for:
|
||||||
// - type - 1 leb128 - 1 byte (worst case)
|
// - type - 1 leb128 - 1 byte (worst case)
|
||||||
@@ -476,8 +447,11 @@ typedef struct lfs_dir {
|
|||||||
} lfs_dir_t;
|
} lfs_dir_t;
|
||||||
|
|
||||||
typedef struct lfsr_dir {
|
typedef struct lfsr_dir {
|
||||||
lfsr_openedmdir_t *next;
|
struct lfsr_opened *next;
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t flags; // unused
|
||||||
lfsr_mdir_t mdir;
|
lfsr_mdir_t mdir;
|
||||||
|
|
||||||
lfsr_did_t did;
|
lfsr_did_t did;
|
||||||
lfsr_smid_t bookmark;
|
lfsr_smid_t bookmark;
|
||||||
lfs_soff_t pos;
|
lfs_soff_t pos;
|
||||||
@@ -545,13 +519,15 @@ typedef struct lfsr_ftree {
|
|||||||
} lfsr_ftree_t;
|
} lfsr_ftree_t;
|
||||||
|
|
||||||
typedef struct lfsr_file {
|
typedef struct lfsr_file {
|
||||||
lfsr_openedmdir_t *next;
|
struct lfsr_opened *next;
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t flags;
|
||||||
lfsr_mdir_t mdir;
|
lfsr_mdir_t mdir;
|
||||||
|
|
||||||
// files contain both an active tree and staging tree, to allow
|
// files contain both an active tree and staging tree, to allow
|
||||||
// staging during mdir compacts
|
// staging during mdir compacts
|
||||||
lfsr_ftree_t ftree;
|
lfsr_ftree_t ftree;
|
||||||
lfsr_ftree_t ftree_;
|
lfsr_ftree_t ftree_;
|
||||||
uint32_t flags;
|
|
||||||
lfs_off_t pos;
|
lfs_off_t pos;
|
||||||
|
|
||||||
lfs_off_t buffer_pos;
|
lfs_off_t buffer_pos;
|
||||||
@@ -633,9 +609,8 @@ typedef struct lfs {
|
|||||||
lfsr_mdir_t mroot;
|
lfsr_mdir_t mroot;
|
||||||
lfsr_mtree_t mtree;
|
lfsr_mtree_t mtree;
|
||||||
|
|
||||||
// linked-lists of opened mdirs, we keep a separate linked-list
|
// linked-list of opened mdirs
|
||||||
// for each type since these need to be handled a bit differently
|
lfsr_opened_t *opened;
|
||||||
lfsr_openedmdir_t *opened[3];
|
|
||||||
|
|
||||||
#ifdef LFS_MIGRATE
|
#ifdef LFS_MIGRATE
|
||||||
struct lfs1 *lfs1;
|
struct lfs1 *lfs1;
|
||||||
|
|||||||
+76
-76
@@ -2293,12 +2293,12 @@ code = '''
|
|||||||
// this test only works if these all fit in the mroot
|
// this test only works if these all fit in the mroot
|
||||||
assert(lfsr_mtree_ismptr(&lfs));
|
assert(lfsr_mtree_ismptr(&lfs));
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=2, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=2, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// insert a new entry, this should update our neighbors
|
// insert a new entry, this should update our neighbors
|
||||||
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS(
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS(
|
||||||
@@ -2320,8 +2320,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &lfs.mroot.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &lfs.mroot.rbyd,
|
||||||
sizeof(lfs.mroot.rbyd)) == 0);
|
sizeof(lfs.mroot.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2340,12 +2340,12 @@ code = '''
|
|||||||
// this test only works if these all fit in the mroot
|
// this test only works if these all fit in the mroot
|
||||||
assert(lfsr_mtree_ismptr(&lfs));
|
assert(lfsr_mtree_ismptr(&lfs));
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=2, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=2, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// try removing our left entry
|
// try removing our left entry
|
||||||
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS(
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS(
|
||||||
@@ -2360,8 +2360,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &lfs.mroot.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &lfs.mroot.rbyd,
|
||||||
sizeof(lfs.mroot.rbyd)) == 0);
|
sizeof(lfs.mroot.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2380,12 +2380,12 @@ code = '''
|
|||||||
// this test only works if these all fit in the mroot
|
// this test only works if these all fit in the mroot
|
||||||
assert(lfsr_mtree_ismptr(&lfs));
|
assert(lfsr_mtree_ismptr(&lfs));
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=2, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=2, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// try removing our right entry
|
// try removing our right entry
|
||||||
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS(
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS(
|
||||||
@@ -2400,8 +2400,8 @@ code = '''
|
|||||||
sizeof(lfs.mroot.rbyd)) == 0);
|
sizeof(lfs.mroot.rbyd)) == 0);
|
||||||
assert(right_neighbor.mdir.mid == -1);
|
assert(right_neighbor.mdir.mid == -1);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2422,12 +2422,12 @@ code = '''
|
|||||||
// this test only works if these all fit in the mroot
|
// this test only works if these all fit in the mroot
|
||||||
assert(lfsr_mtree_ismptr(&lfs));
|
assert(lfsr_mtree_ismptr(&lfs));
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=0, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=0, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// prepare mroot with a large attr so the next entry can not fit
|
// prepare mroot with a large attr so the next entry can not fit
|
||||||
uint8_t buffer[SIZE];
|
uint8_t buffer[SIZE];
|
||||||
@@ -2477,8 +2477,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &msibling.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &msibling.rbyd,
|
||||||
sizeof(msibling.rbyd)) == 0);
|
sizeof(msibling.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2499,12 +2499,12 @@ code = '''
|
|||||||
// this test only works if these all fit in the mroot
|
// this test only works if these all fit in the mroot
|
||||||
assert(lfsr_mtree_ismptr(&lfs));
|
assert(lfsr_mtree_ismptr(&lfs));
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=0, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=0, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// create 2 large entries that needs to be uninlined and split
|
// create 2 large entries that needs to be uninlined and split
|
||||||
uint8_t buffer[SIZE];
|
uint8_t buffer[SIZE];
|
||||||
@@ -2549,8 +2549,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &msibling.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &msibling.rbyd,
|
||||||
sizeof(msibling.rbyd)) == 0);
|
sizeof(msibling.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2598,12 +2598,12 @@ code = '''
|
|||||||
assert(lfsr_mtree_weight(&lfs) == 1*lfsr_mweight(&lfs));
|
assert(lfsr_mtree_weight(&lfs) == 1*lfsr_mweight(&lfs));
|
||||||
assert(mdir.rbyd.weight == 3);
|
assert(mdir.rbyd.weight == 3);
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=mdir.mid+0, .rbyd=mdir.rbyd}};
|
.type=0, .mdir={.mid=mdir.mid+0, .rbyd=mdir.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=mdir.mid+2, .rbyd=mdir.rbyd}};
|
.type=0, .mdir={.mid=mdir.mid+2, .rbyd=mdir.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// now add another large entry to the mdir, forcing a split
|
// now add another large entry to the mdir, forcing a split
|
||||||
memset(buffer, 'e', SIZE);
|
memset(buffer, 'e', SIZE);
|
||||||
@@ -2648,8 +2648,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &msibling.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &msibling.rbyd,
|
||||||
sizeof(msibling.rbyd)) == 0);
|
sizeof(msibling.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2672,12 +2672,12 @@ code = '''
|
|||||||
// this test only works if these all fit in the mroot
|
// this test only works if these all fit in the mroot
|
||||||
assert(lfsr_mtree_ismptr(&lfs));
|
assert(lfsr_mtree_ismptr(&lfs));
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=0, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=0, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
.type=0, .mdir={.mid=1, .rbyd=lfs.mroot.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// prepare mroot with an attr
|
// prepare mroot with an attr
|
||||||
uint8_t buffer[SIZE];
|
uint8_t buffer[SIZE];
|
||||||
@@ -2711,8 +2711,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &lfs.mroot.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &lfs.mroot.rbyd,
|
||||||
sizeof(lfs.mroot.rbyd)) == 0);
|
sizeof(lfs.mroot.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2762,12 +2762,12 @@ code = '''
|
|||||||
assert(lfsr_mtree_weight(&lfs) == 1*lfsr_mweight(&lfs));
|
assert(lfsr_mtree_weight(&lfs) == 1*lfsr_mweight(&lfs));
|
||||||
assert(mdir.rbyd.weight == 3);
|
assert(mdir.rbyd.weight == 3);
|
||||||
|
|
||||||
lfsr_openedmdir_t left_neighbor = {
|
lfsr_opened_t left_neighbor = {
|
||||||
.mdir={.mid=mdir.mid+0, .rbyd=mdir.rbyd}};
|
.type=0, .mdir={.mid=mdir.mid+0, .rbyd=mdir.rbyd}};
|
||||||
lfsr_openedmdir_t right_neighbor = {
|
lfsr_opened_t right_neighbor = {
|
||||||
.mdir={.mid=mdir.mid+2, .rbyd=mdir.rbyd}};
|
.type=0, .mdir={.mid=mdir.mid+2, .rbyd=mdir.rbyd}};
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// force mdir to compact twice, this should relocate
|
// force mdir to compact twice, this should relocate
|
||||||
lfsr_mdir_t old_mdir = mdir;
|
lfsr_mdir_t old_mdir = mdir;
|
||||||
@@ -2803,8 +2803,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &mdir.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &mdir.rbyd,
|
||||||
sizeof(mdir.rbyd)) == 0);
|
sizeof(mdir.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2857,18 +2857,18 @@ code = '''
|
|||||||
//// Now test splitting updates mids correctly
|
//// Now test splitting updates mids correctly
|
||||||
|
|
||||||
// setup our neighbors
|
// setup our neighbors
|
||||||
lfsr_openedmdir_t left_neighbor;
|
lfsr_opened_t left_neighbor = {.type=0};
|
||||||
lfsr_mtree_lookup(&lfs, 0*lfsr_mweight(&lfs)+0,
|
lfsr_mtree_lookup(&lfs, 0*lfsr_mweight(&lfs)+0,
|
||||||
&left_neighbor.mdir) => 0;
|
&left_neighbor.mdir) => 0;
|
||||||
assert(left_neighbor.mdir.rbyd.weight == 1);
|
assert(left_neighbor.mdir.rbyd.weight == 1);
|
||||||
|
|
||||||
lfsr_openedmdir_t right_neighbor;
|
lfsr_opened_t right_neighbor = {.type=0};
|
||||||
lfsr_mtree_lookup(&lfs, 2*lfsr_mweight(&lfs)+0,
|
lfsr_mtree_lookup(&lfs, 2*lfsr_mweight(&lfs)+0,
|
||||||
&right_neighbor.mdir) => 0;
|
&right_neighbor.mdir) => 0;
|
||||||
assert(right_neighbor.mdir.rbyd.weight == 1);
|
assert(right_neighbor.mdir.rbyd.weight == 1);
|
||||||
|
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// cause middle mdir to split
|
// cause middle mdir to split
|
||||||
lfsr_mtree_lookup(&lfs, 1*lfsr_mweight(&lfs)+1, &mdir) => 0;
|
lfsr_mtree_lookup(&lfs, 1*lfsr_mweight(&lfs)+1, &mdir) => 0;
|
||||||
@@ -2895,8 +2895,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &mdir.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &mdir.rbyd,
|
||||||
sizeof(mdir.rbyd)) == 0);
|
sizeof(mdir.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2949,18 +2949,18 @@ code = '''
|
|||||||
//// Now test dropping updates mids correctly
|
//// Now test dropping updates mids correctly
|
||||||
|
|
||||||
// setup our neighbors
|
// setup our neighbors
|
||||||
lfsr_openedmdir_t left_neighbor;
|
lfsr_opened_t left_neighbor = {.type=0};
|
||||||
lfsr_mtree_lookup(&lfs, 0*lfsr_mweight(&lfs)+0,
|
lfsr_mtree_lookup(&lfs, 0*lfsr_mweight(&lfs)+0,
|
||||||
&left_neighbor.mdir) => 0;
|
&left_neighbor.mdir) => 0;
|
||||||
assert(left_neighbor.mdir.rbyd.weight == 1);
|
assert(left_neighbor.mdir.rbyd.weight == 1);
|
||||||
|
|
||||||
lfsr_openedmdir_t right_neighbor;
|
lfsr_opened_t right_neighbor = {.type=0};
|
||||||
lfsr_mtree_lookup(&lfs, 2*lfsr_mweight(&lfs)+0,
|
lfsr_mtree_lookup(&lfs, 2*lfsr_mweight(&lfs)+0,
|
||||||
&right_neighbor.mdir) => 0;
|
&right_neighbor.mdir) => 0;
|
||||||
assert(right_neighbor.mdir.rbyd.weight == 1);
|
assert(right_neighbor.mdir.rbyd.weight == 1);
|
||||||
|
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_addopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_addopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_addopened(&lfs, &right_neighbor);
|
||||||
|
|
||||||
// cause middle mdir to drop
|
// cause middle mdir to drop
|
||||||
lfsr_mtree_lookup(&lfs, 1*lfsr_mweight(&lfs)+0, &mdir) => 0;
|
lfsr_mtree_lookup(&lfs, 1*lfsr_mweight(&lfs)+0, &mdir) => 0;
|
||||||
@@ -2982,8 +2982,8 @@ code = '''
|
|||||||
assert(memcmp(&right_neighbor.mdir.rbyd, &mdir.rbyd,
|
assert(memcmp(&right_neighbor.mdir.rbyd, &mdir.rbyd,
|
||||||
sizeof(mdir.rbyd)) == 0);
|
sizeof(mdir.rbyd)) == 0);
|
||||||
|
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &left_neighbor);
|
lfsr_removeopened(&lfs, &left_neighbor);
|
||||||
lfsr_mdir_removeopened(&lfs, LFS_TYPE_INTERNAL, &right_neighbor);
|
lfsr_removeopened(&lfs, &right_neighbor);
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user