Restricted lfsr_ftree_t to ftree related things

Note, I think if we ever add file snapshots for idempotent errors again,
I don't think adding mdir/next back into the ftree is the best way to
structure this.

Instead, adding a separate linked-list for tracking bshrubs would work
without adding redundant mdir copies to the ftree struct.

Fortunately, in our current version, we don't need to track on-stack
ftrees. Actually, we don't make on-stack ftree copies at all...
This commit is contained in:
Christopher Haster
2024-01-07 19:15:29 -06:00
parent 07e9bbf5b7
commit 34d522a71e
2 changed files with 168 additions and 149 deletions
+166 -147
View File
@@ -5055,10 +5055,14 @@ static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) {
// needed in lfsr_mdir_commit/estimate/compact/etc
static inline bool lfsr_ftree_isnull(const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbsprout(const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbleaf(const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbshrub(const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbtree(const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbsprout(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbleaf(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbshrub(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbtree(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree);
static inline bool lfsr_ftree_isbshruborbtree(const lfsr_ftree_t *ftree);
static int lfsr_bshrub_commit__(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
const lfsr_bshrub_t *bshrub,
@@ -5474,26 +5478,26 @@ static lfs_ssize_t lfsr_mdir_estimate__(lfs_t *lfs, const lfsr_mdir_t *mdir,
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
lfsr_file_t *file = (lfsr_file_t*)opened;
// belongs to our mdir + rid?
if (lfsr_mdir_cmp(&ftree->mdir, mdir) != 0
|| lfsr_mdir_rid(lfs, &ftree->mdir) != rid) {
if (lfsr_mdir_cmp(&file->mdir, mdir) != 0
|| lfsr_mdir_rid(lfs, &file->mdir) != rid) {
continue;
}
// inlined sprout?
if (lfsr_ftree_isbsprout(ftree)) {
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
lfs_ssize_t dsize__ = lfsr_bsprout_estimate__(lfs,
&ftree->u.bsprout);
&file->ftree.u.bsprout);
if (dsize__ < 0) {
return dsize__;
}
dsize_ += dsize__;
// inlined shrub?
} else if (lfsr_ftree_isbshrub(ftree)) {
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
lfs_ssize_t dsize__ = lfsr_bshrub_estimate__(lfs,
&ftree->u.bshrub);
&file->ftree.u.bshrub);
if (dsize__ < 0) {
return dsize__;
}
@@ -5618,28 +5622,28 @@ static int lfsr_mdir_compact__(lfs_t *lfs, lfsr_mdir_t *mdir_,
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
lfsr_file_t *file = (lfsr_file_t*)opened;
// belongs to our mdir?
if (lfsr_mdir_cmp(&ftree->mdir, mdir) != 0
|| lfsr_mdir_rid(lfs, &ftree->mdir) < start_rid
|| (lfsr_rid_t)lfsr_mdir_rid(lfs, &ftree->mdir)
if (lfsr_mdir_cmp(&file->mdir, mdir) != 0
|| lfsr_mdir_rid(lfs, &file->mdir) < start_rid
|| (lfsr_rid_t)lfsr_mdir_rid(lfs, &file->mdir)
>= (lfsr_rid_t)end_rid) {
continue;
}
// inlined sprout?
if (lfsr_ftree_isbsprout(ftree)) {
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
err = lfsr_bsprout_compact__(lfs, &mdir_->rbyd,
&ftree->u.bsprout, true);
&file->ftree.u.bsprout, true);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
}
// inlined shrub?
} else if (lfsr_ftree_isbshrub(ftree)) {
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
err = lfsr_bshrub_compact__(lfs, &mdir_->rbyd,
&ftree->u.bshrub, true,
&file->ftree.u.bshrub, true,
NULL, NULL);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
@@ -5896,11 +5900,13 @@ static int lfsr_mroot_commit(lfs_t *lfs,
// update any bsprouts/bshrubs, note this must happen
// before we update the mdir
if (type == LFS_TYPE_REG) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (lfsr_ftree_isbsprout(ftree)) {
ftree->u.bsprout.data = ftree->u.bsprout.data_;
} else if (lfsr_ftree_isbshrub(ftree)) {
ftree->u.bshrub.rbyd = ftree->u.bshrub.rbyd_;
lfsr_file_t *file = (lfsr_file_t*)opened;
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
file->ftree.u.bsprout.data
= file->ftree.u.bsprout.data_;
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
file->ftree.u.bshrub.rbyd
= file->ftree.u.bshrub.rbyd_;
}
}
@@ -6111,11 +6117,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// stage any bsprouts/bshrubs
if (type == LFS_TYPE_REG) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (lfsr_ftree_isbsprout(ftree)) {
ftree->u.bsprout.data_ = ftree->u.bsprout.data;
} else if (lfsr_ftree_isbshrub(ftree)) {
ftree->u.bshrub.rbyd_ = ftree->u.bshrub.rbyd;
lfsr_file_t *file = (lfsr_file_t*)opened;
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
file->ftree.u.bsprout.data_ = file->ftree.u.bsprout.data;
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
file->ftree.u.bshrub.rbyd_ = file->ftree.u.bshrub.rbyd;
}
}
}
@@ -6389,11 +6395,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// update any bsprouts/bshrubs, note this must happen
// before we update the mdir
if (type == LFS_TYPE_REG) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (lfsr_ftree_isbsprout(ftree)) {
ftree->u.bsprout.data = ftree->u.bsprout.data_;
} else if (lfsr_ftree_isbshrub(ftree)) {
ftree->u.bshrub.rbyd = ftree->u.bshrub.rbyd_;
lfsr_file_t *file = (lfsr_file_t*)opened;
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
file->ftree.u.bsprout.data = file->ftree.u.bsprout.data_;
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
file->ftree.u.bshrub.rbyd = file->ftree.u.bshrub.rbyd_;
}
}
@@ -6823,10 +6829,10 @@ static lfs_ssize_t lfsr_bsprout_estimate__(lfs_t *lfs,
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (lfsr_ftree_isbsprout(ftree)
&& lfsr_bsprout_cmp(&ftree->u.bsprout, bsprout) == 0) {
last = &ftree->u.bsprout;
lfsr_file_t *file = (lfsr_file_t*)opened;
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)
&& lfsr_bsprout_cmp(&file->ftree.u.bsprout, bsprout) == 0) {
last = &file->ftree.u.bsprout;
}
}
if (last && bsprout != last) {
@@ -6857,12 +6863,12 @@ static int lfsr_bsprout_compact__(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (lfsr_ftree_isbsprout(ftree)
&& lfsr_bsprout_cmp(&ftree->u.bsprout, bsprout) == 0) {
lfsr_file_t *file = (lfsr_file_t*)opened;
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)
&& lfsr_bsprout_cmp(&file->ftree.u.bsprout, bsprout) == 0) {
// this is a bit tricky since we don't know the tag size,
// but we have just enough info
ftree->u.bsprout.data_ = LFSR_DATA_DISK(
file->ftree.u.bsprout.data_ = LFSR_DATA_DISK(
rbyd_->blocks[0],
rbyd_->eoff - lfsr_bsprout_size(bsprout),
lfsr_bsprout_size(bsprout));
@@ -6943,10 +6949,10 @@ static lfs_ssize_t lfsr_bshrub_estimate__(lfs_t *lfs,
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (lfsr_ftree_isbshrub(ftree)
&& lfsr_bshrub_cmp(&ftree->u.bshrub, bshrub) == 0) {
last = &ftree->u.bshrub;
lfsr_file_t *file = (lfsr_file_t*)opened;
if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)
&& lfsr_bshrub_cmp(&file->ftree.u.bshrub, bshrub) == 0) {
last = &file->ftree.u.bshrub;
}
}
if (last && bshrub != last) {
@@ -6984,10 +6990,10 @@ static int lfsr_bshrub_compact__(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (lfsr_ftree_isbshrub(ftree)
&& lfsr_bshrub_cmp(&ftree->u.bshrub, bshrub) == 0) {
ftree->u.bshrub.rbyd_ = *rbyd_;
lfsr_file_t *file = (lfsr_file_t*)opened;
if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)
&& lfsr_bshrub_cmp(&file->ftree.u.bshrub, bshrub) == 0) {
file->ftree.u.bshrub.rbyd_ = *rbyd_;
}
}
@@ -7078,19 +7084,19 @@ static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs, lfsr_mdir_t *mdir) {
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (ftree->mdir.mid == mdir->mid) {
if (lfsr_ftree_isbsprout(ftree)) {
lfsr_file_t *file = (lfsr_file_t*)opened;
if (file->mdir.mid == mdir->mid) {
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
lfs_ssize_t dsize = lfsr_bsprout_estimate__(lfs,
&ftree->u.bsprout);
&file->ftree.u.bsprout);
if (dsize < 0) {
return dsize;
}
estimate += dsize;
} else if (lfsr_ftree_isbshrub(ftree)) {
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
lfs_ssize_t dsize = lfsr_bshrub_estimate__(lfs,
&ftree->u.bshrub);
&file->ftree.u.bshrub);
if (dsize < 0) {
return dsize;
}
@@ -7190,10 +7196,10 @@ static int lfsr_bshrub_commit(lfs_t *lfs,
LFS_TYPE_REG-LFS_TYPE_REG];
opened;
opened = opened->next) {
lfsr_ftree_t *ftree = (lfsr_ftree_t*)opened;
if (ftree->mdir.mid == mdir->mid) {
if (lfsr_ftree_isbshrub(ftree)) {
ftree->u.bshrub.estimate = estimate;
lfsr_file_t *file = (lfsr_file_t*)opened;
if (file->mdir.mid == mdir->mid) {
if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
file->ftree.u.bshrub.estimate = estimate;
}
}
}
@@ -7618,32 +7624,32 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
continue;
}
const lfsr_ftree_t *ftree
= (const lfsr_ftree_t*)traversal->u.opened;
const lfsr_file_t *file
= (const lfsr_file_t*)traversal->u.opened;
// found a direct block?
if (lfsr_ftree_isbleaf(ftree)) {
tinfo->u.bptr = ftree->u.bptr;
if (lfsr_ftree_isbleaf(&file->mdir, &file->ftree)) {
tinfo->u.bptr = file->ftree.u.bptr;
// TODO validate?
// transition to next ftree
traversal->u.opened = ftree->next;
// transition to next file
traversal->u.opened = file->next;
tinfo->tag = LFSR_TAG_BLOCK;
return 0;
// found a bshrub/btree?
} else if (lfsr_ftree_isbshruborbtree(ftree)) {
} else if (lfsr_ftree_isbshruborbtree(&file->ftree)) {
// start traversing
traversal->mdir = ftree->mdir;
traversal->bshrub = ftree->u.bshrub;
traversal->mdir = file->mdir;
traversal->bshrub = file->ftree.u.bshrub;
traversal->btraversal = LFSR_BTRAVERSAL();
traversal->state = LFSR_TRAVERSAL_OPENEDBTREE;
continue;
// no? continue to next ftree
// no? continue to next file
} else {
traversal->u.opened = ftree->next;
traversal->u.opened = file->next;
continue;
}
@@ -9190,35 +9196,40 @@ int lfsr_dir_rewind(lfs_t *lfs, lfsr_dir_t *dir) {
#define LFSR_FTREE_ISNULLORBSPROUTORBLEAF 0x80000000
#define LFSR_FTREE_NULL (LFSR_FTREE_ISNULLORBSPROUTORBLEAF | 0)
#define LFSR_FTREE_NULL() \
((lfsr_ftree_t){.u.size=(LFSR_FTREE_ISNULLORBSPROUTORBLEAF | 0)})
static inline bool lfsr_ftree_isnull(const lfsr_ftree_t *ftree) {
return (lfs_size_t)ftree->u.bsprout.data.u.disk.size
== (LFSR_FTREE_ISNULLORBSPROUTORBLEAF | 0);
}
static inline bool lfsr_ftree_isbsprout(const lfsr_ftree_t *ftree) {
static inline bool lfsr_ftree_isbsprout(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
return (lfs_size_t)ftree->u.bsprout.data.u.disk.size
> (LFSR_FTREE_ISNULLORBSPROUTORBLEAF | 0)
&& lfsr_bsprout_isbsprout(&ftree->mdir, &ftree->u.bsprout);
&& lfsr_bsprout_isbsprout(mdir, &ftree->u.bsprout);
}
static inline bool lfsr_ftree_isbleaf(const lfsr_ftree_t *ftree) {
static inline bool lfsr_ftree_isbleaf(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
return (lfs_size_t)ftree->u.bsprout.data.u.disk.size
> (LFSR_FTREE_ISNULLORBSPROUTORBLEAF | 0)
&& lfsr_bsprout_isbleaf(&ftree->mdir, &ftree->u.bsprout);
&& lfsr_bsprout_isbleaf(mdir, &ftree->u.bsprout);
}
static inline bool lfsr_ftree_isbshrub(const lfsr_ftree_t *ftree) {
static inline bool lfsr_ftree_isbshrub(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
return !(ftree->u.bsprout.data.u.disk.size
& LFSR_FTREE_ISNULLORBSPROUTORBLEAF)
&& lfsr_bshrub_isbshrub(&ftree->mdir, &ftree->u.bshrub);
&& lfsr_bshrub_isbshrub(mdir, &ftree->u.bshrub);
}
static inline bool lfsr_ftree_isbtree(const lfsr_ftree_t *ftree) {
static inline bool lfsr_ftree_isbtree(
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
return !(ftree->u.bsprout.data.u.disk.size
& LFSR_FTREE_ISNULLORBSPROUTORBLEAF)
&& lfsr_bshrub_isbtree(&ftree->mdir, &ftree->u.bshrub);
&& lfsr_bshrub_isbtree(mdir, &ftree->u.bshrub);
}
static inline bool lfsr_ftree_isbshruborbtree(const lfsr_ftree_t *ftree) {
@@ -9286,7 +9297,8 @@ static inline lfs_off_t lfsr_file_size_(const lfsr_file_t *file) {
// file operations
// needed in lfsr_file_opencfg
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs, const lfsr_ftree_t *ftree,
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
lfs_off_t pos, uint8_t *buffer, lfs_size_t size);
int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
@@ -9305,7 +9317,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
file->cfg = cfg;
file->pos = 0;
// default data state
file->ftree.u.size = LFSR_FTREE_NULL;
file->ftree = LFSR_FTREE_NULL();
// lookup our parent
lfsr_tag_t tag;
@@ -9313,9 +9325,9 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
const char *name;
lfs_size_t name_size;
int err = lfsr_mtree_pathlookup(lfs, path,
&file->ftree.mdir, &tag,
&file->mdir, &tag,
&did, &name, &name_size);
if (err && (err != LFS_ERR_NOENT || file->ftree.mdir.mid == -1)) {
if (err && (err != LFS_ERR_NOENT || file->mdir.mid == -1)) {
return err;
}
@@ -9337,8 +9349,8 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
// but it's the only way for us to save the file name.
//
// TODO or is it? ;)
err = lfsr_mdir_commit(lfs, &file->ftree.mdir, LFSR_ATTRS(
LFSR_ATTR(file->ftree.mdir.mid,
err = lfsr_mdir_commit(lfs, &file->mdir, LFSR_ATTRS(
LFSR_ATTR(file->mdir.mid,
REG, +1, CAT(
LFSR_DATA_LEB128(did),
LFSR_DATA_BUF(name, name_size)))));
@@ -9362,8 +9374,8 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
// read any inlined state
lfsr_tag_t tag;
lfsr_data_t data;
err = lfsr_mdir_lookupnext(lfs, &file->ftree.mdir,
file->ftree.mdir.mid, LFSR_TAG_DATA,
err = lfsr_mdir_lookupnext(lfs, &file->mdir,
file->mdir.mid, LFSR_TAG_DATA,
&tag, &data);
if (err && err != LFS_ERR_NOENT) {
return err;
@@ -9388,8 +9400,8 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
file->ftree.u.bleaf.becksum.size = -1;
if (lfsr_o_iswriteable(flags)) {
lfsr_data_t data;
err = lfsr_mdir_lookupnext(lfs, &file->ftree.mdir,
file->ftree.mdir.mid, LFSR_TAG_BECKSUM,
err = lfsr_mdir_lookupnext(lfs, &file->mdir,
file->mdir.mid, LFSR_TAG_BECKSUM,
NULL, &data);
if (err && err != LFS_ERR_NOENT) {
return err;
@@ -9412,7 +9424,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
}
file->ftree.u.bshrub.rbyd.blocks[0]
= file->ftree.mdir.rbyd.blocks[0];
= file->mdir.rbyd.blocks[0];
file->ftree.u.bshrub.rbyd.trunk = trunk;
file->ftree.u.bshrub.rbyd.weight = weight;
// force estimate recalculation if we write to this shrub
@@ -9444,7 +9456,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
if (lfsr_ftree_size(&file->ftree) <= lfs->cfg->cache_size
&& lfsr_ftree_size(&file->ftree) <= lfs->cfg->inline_size
&& lfsr_ftree_size(&file->ftree) <= lfs->cfg->fragment_size) {
lfs_ssize_t d = lfsr_ftree_read(lfs, &file->ftree,
lfs_ssize_t d = lfsr_ftree_read(lfs, &file->mdir, &file->ftree,
0, file->buffer, lfsr_ftree_size(&file->ftree));
if (d < 0) {
err = d;
@@ -9455,7 +9467,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
file->flags |= LFS_F_UNFLUSHED;
file->buffer_pos = 0;
file->buffer_size = lfsr_ftree_size(&file->ftree);
file->ftree.u.size = LFSR_FTREE_NULL;
file->ftree = LFSR_FTREE_NULL();
}
// add to tracked mdirs
@@ -9507,7 +9519,8 @@ int lfsr_file_close(lfs_t *lfs, lfsr_file_t *file) {
// low-level ftree operations
static int lfsr_ftree_lookupnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
static int lfsr_ftree_lookupnext(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
lfs_off_t pos,
lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_,
lfsr_bptr_t *bptr_, lfsr_ecksum_t *becksum_) {
@@ -9518,7 +9531,7 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
LFS_ASSERT(!lfsr_ftree_isnull(ftree));
// inlined sprout?
if (lfsr_ftree_isbsprout(ftree)) {
if (lfsr_ftree_isbsprout(mdir, ftree)) {
if (bid_) {
*bid_ = lfsr_data_size(&ftree->u.bsprout.data)-1;
}
@@ -9537,7 +9550,7 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
return 0;
// block pointer?
} else if (lfsr_ftree_isbleaf(ftree)) {
} else if (lfsr_ftree_isbleaf(mdir, ftree)) {
if (bid_) {
*bid_ = lfsr_data_size(&ftree->u.bptr.data)-1;
}
@@ -9564,7 +9577,7 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
lfsr_bid_t weight;
lfsr_data_t data;
int err = lfsr_bshrub_lookupnext_(lfs,
&ftree->mdir, &ftree->u.bshrub,
mdir, &ftree->u.bshrub,
pos,
&bid, &rbyd, &rid, &tag, &weight, &data);
if (err) {
@@ -9616,7 +9629,8 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
}
}
static lfs_ssize_t lfsr_ftree_readnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
static lfs_ssize_t lfsr_ftree_readnext(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
lfs_off_t pos_ = pos;
// read one btree entry
@@ -9624,7 +9638,7 @@ static lfs_ssize_t lfsr_ftree_readnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_bptr_t bptr;
int err = lfsr_ftree_lookupnext(lfs, ftree, pos_,
int err = lfsr_ftree_lookupnext(lfs, mdir, ftree, pos_,
&bid, &tag, &weight, &bptr, NULL);
if (err) {
return err;
@@ -9663,11 +9677,12 @@ static lfs_ssize_t lfsr_ftree_readnext(lfs_t *lfs, const lfsr_ftree_t *ftree,
return pos_ - pos;
}
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs, const lfsr_ftree_t *ftree,
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
lfs_off_t pos_ = pos;
while (size > 0 && pos_ < lfsr_ftree_size(ftree)) {
lfs_ssize_t d = lfsr_ftree_readnext(lfs, ftree,
lfs_ssize_t d = lfsr_ftree_readnext(lfs, mdir, ftree,
pos_, buffer, size);
if (d < 0) {
LFS_ASSERT(d != LFS_ERR_NOENT);
@@ -9682,7 +9697,8 @@ static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs, const lfsr_ftree_t *ftree,
return pos_ - pos;
}
static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
static int lfsr_ftree_carve(lfs_t *lfs,
lfsr_mdir_t *mdir, lfsr_ftree_t *ftree,
lfs_off_t pos, lfs_off_t weight, lfs_soff_t delta,
lfsr_tag_t tag, const lfsr_bptr_t *bptr, const lfsr_ecksum_t *becksum) {
// Note! This function has some rather special constraints:
@@ -9704,19 +9720,19 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
//
// before we touch anything, if our file is a btree, we need to mark all
// other references btree as unerased
if (lfsr_ftree_isbtree(ftree)) {
if (lfsr_ftree_isbtree(mdir, ftree)) {
for (lfsr_openedmdir_t *opened_ = lfs->opened[
LFS_TYPE_REG-LFS_TYPE_REG];
opened_;
opened_ = opened_->next) {
lfsr_ftree_t *ftree_ = (lfsr_ftree_t*)opened_;
if (ftree_ != ftree
&& lfsr_ftree_isbtree(ftree_)
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
if (&file_->ftree != ftree
&& lfsr_ftree_isbtree(&file_->mdir, &file_->ftree)
&& lfsr_btree_cmp(
&ftree_->u.btree,
&file_->ftree.u.btree,
&ftree->u.btree) == 0) {
// mark as unerased
ftree_->u.btree.eoff = -1;
file_->ftree.u.btree.eoff = -1;
}
}
}
@@ -9724,7 +9740,7 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
// always convert to bshrub/btree when this function is called
if (!lfsr_ftree_isbshruborbtree(ftree)) {
lfsr_bshrub_t bshrub;
bshrub.rbyd.blocks[0] = ftree->mdir.rbyd.blocks[0];
bshrub.rbyd.blocks[0] = mdir->rbyd.blocks[0];
bshrub.rbyd.trunk = 0;
bshrub.rbyd.weight = 0;
// force estimate recalculation
@@ -9735,16 +9751,16 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
// they have no state that needs to be compacted
uint8_t bptr_buf[LFSR_BPTR_DSIZE];
uint8_t becksum_buf[LFSR_ECKSUM_DSIZE];
int err = lfsr_bshrub_commit(lfs, &ftree->mdir, &bshrub,
int err = lfsr_bshrub_commit(lfs, mdir, &bshrub,
LFSR_ATTRS(
(lfsr_ftree_isbsprout(ftree))
(lfsr_ftree_isbsprout(mdir, ftree))
? LFSR_ATTR(0,
DATA, +lfsr_ftree_size(ftree),
DATA(ftree->u.bsprout.data))
: LFSR_ATTR(0,
BLOCK, +lfsr_ftree_size(ftree),
FROMBPTR(&ftree->u.bptr, bptr_buf)),
(lfsr_ftree_isbleaf(ftree)
(lfsr_ftree_isbleaf(mdir, ftree)
&& ftree->u.bleaf.becksum.size != -1)
? LFSR_ATTR(lfsr_ftree_size(ftree)-1,
BECKSUM, 0,
@@ -9774,7 +9790,7 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
lfsr_bid_t weight_;
lfsr_bptr_t bptr_;
lfsr_ecksum_t becksum_;
int err = lfsr_ftree_lookupnext(lfs, ftree,
int err = lfsr_ftree_lookupnext(lfs, mdir, ftree,
pos,
&bid_, &tag_, &weight_, &bptr_, &becksum_);
if (err) {
@@ -9799,7 +9815,7 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
lfs->cfg->fragment_size,
-1);
err = lfsr_bshrub_commit(lfs, &ftree->mdir, &ftree->u.bshrub,
err = lfsr_bshrub_commit(lfs, mdir, &ftree->u.bshrub,
LFSR_ATTRS(
LFSR_ATTR(bid_,
GROW(WIDE(DATA)),
@@ -9827,7 +9843,7 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
bptr_.data = lfsr_data_truncate(bptr_.data,
lfsr_data_size(&bptr_.data) - lfs->cfg->fragment_size);
err = lfsr_bshrub_commit(lfs, &ftree->mdir, &ftree->u.bshrub,
err = lfsr_bshrub_commit(lfs, mdir, &ftree->u.bshrub,
LFSR_ATTRS(
LFSR_ATTR(bid_,
GROW(WIDE(BLOCK)),
@@ -9888,7 +9904,7 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
LFS_ASSERT(attr_count_ <= sizeof(attrs_)/sizeof(lfsr_attr_t));
LFS_ASSERT(buf_size <= sizeof(buf));
err = lfsr_bshrub_commit(lfs, &ftree->mdir, &ftree->u.bshrub,
err = lfsr_bshrub_commit(lfs, mdir, &ftree->u.bshrub,
attrs_, attr_count_);
if (err) {
return err;
@@ -9994,7 +10010,7 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
LFS_ASSERT(attr_count_ <= sizeof(attrs_)/sizeof(lfsr_attr_t));
LFS_ASSERT(buf_size <= sizeof(buf));
int err = lfsr_bshrub_commit(lfs, &ftree->mdir, &ftree->u.bshrub,
int err = lfsr_bshrub_commit(lfs, mdir, &ftree->u.bshrub,
attrs_, attr_count_);
if (err) {
return err;
@@ -10004,7 +10020,8 @@ static int lfsr_ftree_carve(lfs_t *lfs, lfsr_ftree_t *ftree,
return 0;
}
static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
static int lfsr_ftree_flush(lfs_t *lfs,
lfsr_mdir_t *mdir, lfsr_ftree_t *ftree,
lfs_off_t pos, const uint8_t *buffer, lfs_size_t size) {
// we can skip some btree lookups if we know we are aligned from a
// previous iteration, we already do way too many btree lookups
@@ -10036,7 +10053,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_ecksum_t becksum;
int err = lfsr_ftree_lookupnext(lfs, ftree,
int err = lfsr_ftree_lookupnext(lfs, mdir, ftree,
lfs_smax32(pos - (lfs->cfg->crystal_thresh-1), 0),
&bid, &tag, &weight, &bptr, &becksum);
if (err) {
@@ -10094,7 +10111,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
lfsr_bid_t bid;
lfsr_tag_t tag;
lfsr_bid_t weight;
int err = lfsr_ftree_lookupnext(lfs, ftree,
int err = lfsr_ftree_lookupnext(lfs, mdir, ftree,
lfs_min32(
crystal_start + (lfs->cfg->crystal_thresh-1),
lfsr_ftree_size(ftree)-1),
@@ -10140,7 +10157,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_ecksum_t becksum;
int err = lfsr_ftree_lookupnext(lfs, ftree,
int err = lfsr_ftree_lookupnext(lfs, mdir, ftree,
lfs_min32(
crystal_start-1,
lfsr_ftree_size(ftree)-1),
@@ -10259,7 +10276,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
lfsr_tag_t tag_;
lfsr_bid_t weight_;
lfsr_bptr_t bptr_;
err = lfsr_ftree_lookupnext(lfs, ftree, pos_,
err = lfsr_ftree_lookupnext(lfs, mdir, ftree, pos_,
&bid_, &tag_, &weight_, &bptr_, NULL);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -10373,7 +10390,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
}
// and write it into our tree
err = lfsr_ftree_carve(lfs, ftree,
err = lfsr_ftree_carve(lfs, mdir, ftree,
block_start, block_end - block_start, 0,
LFSR_TAG_BLOCK, &bptr, &becksum);
if (err) {
@@ -10412,7 +10429,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_bptr_t bptr;
int err = lfsr_ftree_lookupnext(lfs, ftree,
int err = lfsr_ftree_lookupnext(lfs, mdir, ftree,
fragment_start-1,
&bid, &tag, &weight, &bptr, NULL);
if (err) {
@@ -10450,7 +10467,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_bptr_t bptr;
int err = lfsr_ftree_lookupnext(lfs, ftree,
int err = lfsr_ftree_lookupnext(lfs, mdir, ftree,
fragment_end,
&bid, &tag, &weight, &bptr, NULL);
if (err) {
@@ -10477,7 +10494,7 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_ftree_t *ftree,
// once we've figured out what fragment to write, carve it into
// our tree
int err = lfsr_ftree_carve(lfs, ftree,
int err = lfsr_ftree_carve(lfs, mdir, ftree,
fragment_start, fragment_end - fragment_start, 0,
LFSR_TAG_DATA, &(const lfsr_bptr_t){.data=data}, NULL);
if (err && err != LFS_ERR_RANGE) {
@@ -10534,7 +10551,8 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
if (pos_ < lfsr_ftree_size(&file->ftree)) {
// bypass buffer?
if ((lfs_size_t)d >= lfs->cfg->cache_size) {
lfs_ssize_t d_ = lfsr_ftree_readnext(lfs, &file->ftree,
lfs_ssize_t d_ = lfsr_ftree_readnext(lfs,
&file->mdir, &file->ftree,
pos_, buffer_, d);
if (d_ < 0) {
LFS_ASSERT(d_ != LFS_ERR_NOENT);
@@ -10562,7 +10580,8 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
}
// try to fill our buffer with some data
lfs_ssize_t d_ = lfsr_ftree_readnext(lfs, &file->ftree,
lfs_ssize_t d_ = lfsr_ftree_readnext(lfs,
&file->mdir, &file->ftree,
pos_, file->buffer, d);
if (d_ < 0) {
LFS_ASSERT(d != LFS_ERR_NOENT);
@@ -10638,7 +10657,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
//
if (!lfsr_f_isunflushed(file->flags)
&& size >= lfs->cfg->cache_size) {
err = lfsr_ftree_flush(lfs, &file->ftree,
err = lfsr_ftree_flush(lfs, &file->mdir, &file->ftree,
pos, buffer_, size);
if (err) {
goto failed;
@@ -10698,7 +10717,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
}
// flush our buffer so the above can't fail
err = lfsr_ftree_flush(lfs, &file->ftree,
err = lfsr_ftree_flush(lfs, &file->mdir, &file->ftree,
file->buffer_pos, file->buffer, file->buffer_size);
if (err) {
goto failed;
@@ -10772,7 +10791,7 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) {
if (lfsr_f_isunflushed(file->flags)
&& file->buffer_size != 0) {
// flush
err = lfsr_ftree_flush(lfs, &file->ftree,
err = lfsr_ftree_flush(lfs, &file->mdir, &file->ftree,
file->buffer_pos, file->buffer, file->buffer_size);
if (err) {
goto failed;
@@ -10791,7 +10810,7 @@ failed:;
int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
// do nothing if our file has been removed
if (file->ftree.mdir.mid == -1) {
if (file->mdir.mid == -1) {
return 0;
}
@@ -10820,8 +10839,8 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
// or bptr
//
// this is convenient because bptrs are a bit annoying to commit
LFS_ASSERT(!lfsr_ftree_isbsprout(&file->ftree));
LFS_ASSERT(!lfsr_ftree_isbleaf(&file->ftree));
LFS_ASSERT(!lfsr_ftree_isbsprout(&file->mdir, &file->ftree));
LFS_ASSERT(!lfsr_ftree_isbleaf(&file->mdir, &file->ftree));
// small files should start as zero, const prop should optimize this out
LFS_ASSERT(!lfsr_f_isunflushed(file->flags)
|| file->buffer_pos == 0);
@@ -10841,20 +10860,20 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
if (lfsr_f_isunsynced(file->flags)) {
// commit our file's metadata
uint8_t buf[LFSR_BTREE_DSIZE];
int err = lfsr_mdir_commit(lfs, &file->ftree.mdir, LFSR_ATTRS(
int err = lfsr_mdir_commit(lfs, &file->mdir, LFSR_ATTRS(
(lfsr_f_isunflushed(file->flags) && file->buffer_size == 0)
? LFSR_ATTR(file->ftree.mdir.mid,
? LFSR_ATTR(file->mdir.mid,
WIDE(RM(STRUCT)), 0,
NULL())
: (lfsr_f_isunflushed(file->flags))
? LFSR_ATTR(file->ftree.mdir.mid,
? LFSR_ATTR(file->mdir.mid,
WIDE(DATA), 0,
BUF(file->buffer, file->buffer_size))
: (lfsr_ftree_isbshrub(&file->ftree))
? LFSR_ATTR(file->ftree.mdir.mid,
: (lfsr_ftree_isbshrub(&file->mdir, &file->ftree))
? LFSR_ATTR(file->mdir.mid,
WIDE(SHRUBTRUNK), 0,
SHRUBTRUNK(&file->ftree.u.bshrub))
: LFSR_ATTR(file->ftree.mdir.mid,
: LFSR_ATTR(file->mdir.mid,
WIDE(BTREE), 0,
FROMBTREE(&file->ftree.u.btree, buf))));
if (err) {
@@ -10868,7 +10887,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
opened_;
opened_ = opened_->next) {
lfsr_file_t *file_ = (lfsr_file_t*)opened_;
if (file_->ftree.mdir.mid == file->ftree.mdir.mid
if (file_->mdir.mid == file->mdir.mid
// don't double update
&& file_ != file
// don't update desynced file handles
@@ -10977,7 +10996,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
file->buffer_pos = 0;
file->buffer_size = 0;
lfs_ssize_t d = lfsr_ftree_read(lfs, &file->ftree,
lfs_ssize_t d = lfsr_ftree_read(lfs, &file->mdir, &file->ftree,
0, file->buffer, size_);
if (d < 0) {
err = d;
@@ -10998,12 +11017,12 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
file->flags |= LFS_F_UNFLUSHED;
file->buffer_pos = 0;
file->buffer_size = size_;
file->ftree.u.size = LFSR_FTREE_NULL;
file->ftree = LFSR_FTREE_NULL();
// truncate our file normally
} else {
// truncate our ftree
err = lfsr_ftree_carve(lfs, &file->ftree,
err = lfsr_ftree_carve(lfs, &file->mdir, &file->ftree,
lfs_min32(size, size_),
size - lfs_min32(size, size_),
+size_ - size,
@@ -11083,7 +11102,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
file->buffer_pos = 0;
file->buffer_size = 0;
lfs_ssize_t d = lfsr_ftree_read(lfs, &file->ftree,
lfs_ssize_t d = lfsr_ftree_read(lfs, &file->mdir, &file->ftree,
lfsr_ftree_size(&file->ftree) - lfs_min32(
size_,
lfsr_ftree_size(&file->ftree)),
@@ -11116,12 +11135,12 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
file->flags |= LFS_F_UNFLUSHED;
file->buffer_pos = 0;
file->buffer_size = size_;
file->ftree.u.size = LFSR_FTREE_NULL;
file->ftree = LFSR_FTREE_NULL();
// fruncate our file normally
} else {
// fruncate our ftree
err = lfsr_ftree_carve(lfs, &file->ftree,
err = lfsr_ftree_carve(lfs, &file->mdir, &file->ftree,
0,
lfs_smax32(size - size_, 0),
+size_ - size,
+2 -2
View File
@@ -537,8 +537,6 @@ typedef struct lfsr_bshrub {
// the lfsr_ftree_t struct is a sort of proto-file
typedef struct lfsr_ftree {
lfsr_openedmdir_t *next;
lfsr_mdir_t mdir;
union {
lfs_soff_t size;
lfsr_data_t data;
@@ -551,6 +549,8 @@ typedef struct lfsr_ftree {
} lfsr_ftree_t;
typedef struct lfsr_file {
lfsr_openedmdir_t *next;
lfsr_mdir_t mdir;
lfsr_ftree_t ftree;
uint32_t flags;
lfs_off_t pos;