Brought back lfsr_ftree_t just for naming a couple things
This readds lfsr_ftree_t, however this time its not involved in the file
staging, has no operations of its own, and really just acts as a
namespace for the file's bnull/bsprout/bptr/bshrub/btree struct.
I think this is a good way to organize things.
Code impact is also minimal:
code stack
before: 32874 2952
after: 32984 (+0.3%) 2968 (+0.5%)
This commit is contained in:
@@ -1844,13 +1844,19 @@ static int lfsr_data_readgrm(lfs_t *lfs, lfsr_data_t *data,
|
|||||||
|
|
||||||
|
|
||||||
// needed in sprout/shrub operations
|
// needed in sprout/shrub operations
|
||||||
static inline bool lfsr_file_isbnull(const lfsr_file_t *file);
|
static inline bool lfsr_ftree_isbnull(const lfsr_ftree_t *ftree);
|
||||||
static inline bool lfsr_file_isbsprout(const lfsr_file_t *file);
|
static inline bool lfsr_ftree_isbsprout(
|
||||||
static inline bool lfsr_file_isbptr(const lfsr_file_t *file);
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree);
|
||||||
static inline bool lfsr_file_isbshrub(const lfsr_file_t *file);
|
static inline bool lfsr_ftree_isbptr(
|
||||||
static inline bool lfsr_file_isbtree(const lfsr_file_t *file);
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree);
|
||||||
static inline bool lfsr_file_isbnullorbsproutorbptr(const lfsr_file_t *file);
|
static inline bool lfsr_ftree_isbshrub(
|
||||||
static inline bool lfsr_file_isbshruborbtree(const lfsr_file_t *file);
|
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_isbnullorbsproutorbptr(
|
||||||
|
const lfsr_ftree_t *ftree);
|
||||||
|
static inline bool lfsr_ftree_isbshruborbtree(
|
||||||
|
const lfsr_ftree_t *ftree);
|
||||||
|
|
||||||
// sprout things
|
// sprout things
|
||||||
static inline int lfsr_sprout_cmp(
|
static inline int lfsr_sprout_cmp(
|
||||||
@@ -1879,9 +1885,9 @@ static lfs_ssize_t lfsr_sprout_estimate(lfs_t *lfs,
|
|||||||
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_file_isbsprout(file_)
|
if (lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_sprout_cmp(&file_->u.bsprout, sprout) == 0) {
|
&& lfsr_sprout_cmp(&file_->ftree.u.bsprout, sprout) == 0) {
|
||||||
last = &file_->u.bsprout;
|
last = &file_->ftree.u.bsprout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (last && sprout != last) {
|
if (last && sprout != last) {
|
||||||
@@ -1912,13 +1918,13 @@ static int lfsr_sprout_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
|||||||
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_file_isbsprout(file_)
|
if (lfsr_ftree_isbsprout(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_sprout_cmp(
|
&& lfsr_sprout_cmp(
|
||||||
&file_->u.bsprout,
|
&file_->ftree.u.bsprout,
|
||||||
sprout) == 0) {
|
sprout) == 0) {
|
||||||
// this is a bit tricky since we don't know the tag size,
|
// this is a bit tricky since we don't know the tag size,
|
||||||
// but we have just enough info
|
// but we have just enough info
|
||||||
file_->u_.bsprout = LFSR_DATA_DISK(
|
file_->ftree_.u.bsprout = LFSR_DATA_DISK(
|
||||||
rbyd_->blocks[0],
|
rbyd_->blocks[0],
|
||||||
rbyd_->eoff - lfsr_data_size(sprout),
|
rbyd_->eoff - lfsr_data_size(sprout),
|
||||||
lfsr_data_size(sprout));
|
lfsr_data_size(sprout));
|
||||||
@@ -2017,9 +2023,9 @@ static lfs_ssize_t lfsr_shrub_estimate(lfs_t *lfs,
|
|||||||
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_file_isbshrub(file_)
|
if (lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_shrub_cmp(&file_->u.bshrub, shrub) == 0) {
|
&& lfsr_shrub_cmp(&file_->ftree.u.bshrub, shrub) == 0) {
|
||||||
last = &file_->u.bshrub;
|
last = &file_->ftree.u.bshrub;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (last && shrub != last) {
|
if (last && shrub != last) {
|
||||||
@@ -2051,11 +2057,11 @@ static int lfsr_shrub_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
|||||||
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_file_isbshrub(file_)
|
if (lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)
|
||||||
&& lfsr_shrub_cmp(&file_->u.bshrub, shrub) == 0) {
|
&& lfsr_shrub_cmp(&file_->ftree.u.bshrub, shrub) == 0) {
|
||||||
file_->u_.bshrub.blocks[0] = rbyd_->blocks[0];
|
file_->ftree_.u.bshrub.blocks[0] = rbyd_->blocks[0];
|
||||||
file_->u_.bshrub.trunk = rbyd_->trunk;
|
file_->ftree_.u.bshrub.trunk = rbyd_->trunk;
|
||||||
file_->u_.bshrub.weight = rbyd_->weight;
|
file_->ftree_.u.bshrub.weight = rbyd_->weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5679,18 +5685,18 @@ static lfs_ssize_t lfsr_mdir_estimate__(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// inlined sprout?
|
// inlined sprout?
|
||||||
if (lfsr_file_isbsprout(file)) {
|
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->u.bsprout);
|
&file->ftree.u.bsprout);
|
||||||
if (dsize__ < 0) {
|
if (dsize__ < 0) {
|
||||||
return dsize__;
|
return dsize__;
|
||||||
}
|
}
|
||||||
dsize_ += dsize__;
|
dsize_ += dsize__;
|
||||||
|
|
||||||
// inlined shrub?
|
// inlined shrub?
|
||||||
} else if (lfsr_file_isbshrub(file)) {
|
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)) {
|
||||||
lfs_ssize_t dsize__ = lfsr_shrub_estimate(lfs,
|
lfs_ssize_t dsize__ = lfsr_shrub_estimate(lfs,
|
||||||
&file->u.bshrub);
|
&file->ftree.u.bshrub);
|
||||||
if (dsize__ < 0) {
|
if (dsize__ < 0) {
|
||||||
return dsize__;
|
return dsize__;
|
||||||
}
|
}
|
||||||
@@ -5823,25 +5829,25 @@ static int lfsr_mdir_compact__(lfs_t *lfs, lfsr_mdir_t *mdir_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// inlined sprout?
|
// inlined sprout?
|
||||||
if (lfsr_file_isbsprout(file)
|
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)
|
||||||
// only compact once, first compact should stage the new block
|
// only compact once, first compact should stage the new block
|
||||||
&& file->u_.bsprout.u.disk.block
|
&& file->ftree_.u.bsprout.u.disk.block
|
||||||
!= mdir_->rbyd.blocks[0]) {
|
!= mdir_->rbyd.blocks[0]) {
|
||||||
err = lfsr_sprout_compact(lfs, &mdir_->rbyd,
|
err = lfsr_sprout_compact(lfs, &mdir_->rbyd,
|
||||||
&file->u_.bsprout,
|
&file->ftree_.u.bsprout,
|
||||||
&file->u.bsprout, true);
|
&file->ftree.u.bsprout, true);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// inlined shrub?
|
// inlined shrub?
|
||||||
} else if (lfsr_file_isbshrub(file)
|
} else if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)
|
||||||
// only compact once, first compact should stage the new block
|
// only compact once, first compact should stage the new block
|
||||||
&& file->u.bshrub.blocks[0]
|
&& file->ftree.u.bshrub.blocks[0]
|
||||||
!= mdir_->rbyd.blocks[0]) {
|
!= mdir_->rbyd.blocks[0]) {
|
||||||
err = lfsr_shrub_compact(lfs, &mdir_->rbyd,
|
err = lfsr_shrub_compact(lfs, &mdir_->rbyd,
|
||||||
&file->u_.bshrub, &file->u.bshrub);
|
&file->ftree_.u.bshrub, &file->ftree.u.bshrub);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
return err;
|
return err;
|
||||||
@@ -6100,7 +6106,7 @@ static int lfsr_mroot_commit(lfs_t *lfs,
|
|||||||
// update staged changes
|
// update staged changes
|
||||||
if (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->u = file->u_;
|
file->ftree = file->ftree_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6308,7 +6314,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
// stage any bsprouts/bshrubs
|
// stage any bsprouts/bshrubs
|
||||||
if (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->u_ = file->u;
|
file->ftree_ = file->ftree;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6581,7 +6587,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
// update staged changes
|
// update staged changes
|
||||||
if (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->u = file->u_;
|
file->ftree = file->ftree_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid double updating current mdir
|
// avoid double updating current mdir
|
||||||
@@ -6991,13 +6997,7 @@ typedef struct lfsr_traversal {
|
|||||||
struct {
|
struct {
|
||||||
lfsr_openedmdir_t *next;
|
lfsr_openedmdir_t *next;
|
||||||
lfsr_mdir_t mdir;
|
lfsr_mdir_t mdir;
|
||||||
union {
|
lfsr_ftree_t ftree;
|
||||||
lfs_soff_t size;
|
|
||||||
lfsr_data_t bsprout;
|
|
||||||
lfsr_bptr_t bptr;
|
|
||||||
lfsr_shrub_t bshrub;
|
|
||||||
lfsr_btree_t btree;
|
|
||||||
} u;
|
|
||||||
} file;
|
} file;
|
||||||
lfsr_btraversal_t btraversal;
|
lfsr_btraversal_t btraversal;
|
||||||
} lfsr_traversal_t;
|
} lfsr_traversal_t;
|
||||||
@@ -7296,7 +7296,7 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
// found a direct block?
|
// found a direct block?
|
||||||
if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BLOCK) {
|
if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BLOCK) {
|
||||||
err = lfsr_data_readbptr(lfs, &data,
|
err = lfsr_data_readbptr(lfs, &data,
|
||||||
&traversal->file.u.bptr);
|
&traversal->file.ftree.u.bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -7304,7 +7304,7 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
// found a bshrub (inlined btree)?
|
// found a bshrub (inlined btree)?
|
||||||
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
|
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
|
||||||
err = lfsr_data_readshrub(lfs, &data, &traversal->file.mdir,
|
err = lfsr_data_readshrub(lfs, &data, &traversal->file.mdir,
|
||||||
&traversal->file.u.bshrub);
|
&traversal->file.ftree.u.bshrub);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -7312,7 +7312,7 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
// found a btree?
|
// found a btree?
|
||||||
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
|
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
|
||||||
err = lfsr_data_readbtree(lfs, &data,
|
err = lfsr_data_readbtree(lfs, &data,
|
||||||
&traversal->file.u.btree);
|
&traversal->file.ftree.u.btree);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -7338,7 +7338,8 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
|
|
||||||
// start traversing
|
// start traversing
|
||||||
const lfsr_file_t *file = (const lfsr_file_t*)traversal->u.opened;
|
const lfsr_file_t *file = (const lfsr_file_t*)traversal->u.opened;
|
||||||
memcpy(&traversal->file, file, sizeof(traversal->file));
|
traversal->file.mdir = file->mdir;
|
||||||
|
traversal->file.ftree = file->ftree;
|
||||||
traversal->btraversal = LFSR_BTRAVERSAL();
|
traversal->btraversal = LFSR_BTRAVERSAL();
|
||||||
traversal->state = LFSR_TRAVERSAL_OPENEDBTREE;
|
traversal->state = LFSR_TRAVERSAL_OPENEDBTREE;
|
||||||
continue;
|
continue;
|
||||||
@@ -8873,50 +8874,60 @@ int lfsr_dir_rewind(lfs_t *lfs, lfsr_dir_t *dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// File operations ///
|
/// File operations ///
|
||||||
|
|
||||||
#define LFSR_FILE_ISBNULLORBSPROUTORBPTR 0x80000000
|
#define LFSR_FTREE_ISBNULLORBSPROUTORBPTR 0x80000000
|
||||||
|
|
||||||
#define LFSR_FILE_BNULL (LFSR_FILE_ISBNULLORBSPROUTORBPTR | 0)
|
#define LFSR_FTREE_BNULL() \
|
||||||
|
((lfsr_ftree_t){.u.size=(LFSR_FTREE_ISBNULLORBSPROUTORBPTR | 0)})
|
||||||
|
|
||||||
static inline bool lfsr_file_isbnull(const lfsr_file_t *file) {
|
static inline bool lfsr_ftree_isbnull(const lfsr_ftree_t *ftree) {
|
||||||
return (lfs_size_t)file->u.bsize
|
return (lfs_size_t)ftree->u.size
|
||||||
== (LFSR_FILE_ISBNULLORBSPROUTORBPTR | 0);
|
== (LFSR_FTREE_ISBNULLORBSPROUTORBPTR | 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_file_isbsprout(const lfsr_file_t *file) {
|
static inline bool lfsr_ftree_isbsprout(
|
||||||
return (lfs_size_t)file->u.bsize
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
|
||||||
> (LFSR_FILE_ISBNULLORBSPROUTORBPTR | 0)
|
return (lfs_size_t)ftree->u.size
|
||||||
&& file->u.bsprout.u.disk.block == file->mdir.rbyd.blocks[0];
|
> (LFSR_FTREE_ISBNULLORBSPROUTORBPTR | 0)
|
||||||
|
&& ftree->u.bsprout.u.disk.block == mdir->rbyd.blocks[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_file_isbptr(const lfsr_file_t *file) {
|
static inline bool lfsr_ftree_isbptr(
|
||||||
return (lfs_size_t)file->u.bsize
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
|
||||||
> (LFSR_FILE_ISBNULLORBSPROUTORBPTR | 0)
|
return (lfs_size_t)ftree->u.size
|
||||||
&& file->u.bsprout.u.disk.block != file->mdir.rbyd.blocks[0];
|
> (LFSR_FTREE_ISBNULLORBSPROUTORBPTR | 0)
|
||||||
|
&& ftree->u.bsprout.u.disk.block != mdir->rbyd.blocks[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_file_isbshrub(const lfsr_file_t *file) {
|
static inline bool lfsr_ftree_isbshrub(
|
||||||
return !(file->u.bsize & LFSR_FILE_ISBNULLORBSPROUTORBPTR)
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
|
||||||
&& file->u.bshrub.blocks[0] == file->mdir.rbyd.blocks[0];
|
return !(ftree->u.size & LFSR_FTREE_ISBNULLORBSPROUTORBPTR)
|
||||||
|
&& ftree->u.bshrub.blocks[0] == mdir->rbyd.blocks[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_file_isbtree(const lfsr_file_t *file) {
|
static inline bool lfsr_ftree_isbtree(
|
||||||
return !(file->u.bsize & LFSR_FILE_ISBNULLORBSPROUTORBPTR)
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree) {
|
||||||
&& file->u.bshrub.blocks[0] != file->mdir.rbyd.blocks[0];
|
return !(ftree->u.size & LFSR_FTREE_ISBNULLORBSPROUTORBPTR)
|
||||||
|
&& ftree->u.bshrub.blocks[0] != mdir->rbyd.blocks[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_file_isbnullorbsproutorbptr(const lfsr_file_t *file) {
|
static inline bool lfsr_ftree_isbnullorbsproutorbptr(
|
||||||
return file->u.bsize & LFSR_FILE_ISBNULLORBSPROUTORBPTR;
|
const lfsr_ftree_t *ftree) {
|
||||||
|
return ftree->u.size & LFSR_FTREE_ISBNULLORBSPROUTORBPTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_file_isbshruborbtree(const lfsr_file_t *file) {
|
static inline bool lfsr_ftree_isbshruborbtree(
|
||||||
return !(file->u.bsize & LFSR_FILE_ISBNULLORBSPROUTORBPTR);
|
const lfsr_ftree_t *ftree) {
|
||||||
|
return !(ftree->u.size & LFSR_FTREE_ISBNULLORBSPROUTORBPTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the on-disk size/weight lines up to the same word across all unions
|
// the on-disk size/weight lines up to the same word across all unions
|
||||||
static inline lfs_off_t lfsr_file_bsize(const lfsr_file_t *file) {
|
static inline lfs_off_t lfsr_ftree_size(const lfsr_ftree_t *ftree) {
|
||||||
return file->u.bsize & ~LFSR_FILE_ISBNULLORBSPROUTORBPTR;
|
return ftree->u.size & ~LFSR_FTREE_ISBNULLORBSPROUTORBPTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// flag things
|
// flag things
|
||||||
@@ -8967,7 +8978,7 @@ static inline bool lfsr_f_isunsynced(uint32_t flags) {
|
|||||||
static inline lfs_off_t lfsr_file_size_(const lfsr_file_t *file) {
|
static inline lfs_off_t lfsr_file_size_(const lfsr_file_t *file) {
|
||||||
return lfs_max32(
|
return lfs_max32(
|
||||||
file->buffer_pos + file->buffer_size,
|
file->buffer_pos + file->buffer_size,
|
||||||
lfsr_file_bsize(file));
|
lfsr_ftree_size(&file->ftree));
|
||||||
}
|
}
|
||||||
|
|
||||||
// file operations
|
// file operations
|
||||||
@@ -8992,7 +9003,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
file->cfg = cfg;
|
file->cfg = cfg;
|
||||||
file->pos = 0;
|
file->pos = 0;
|
||||||
// default data state
|
// default data state
|
||||||
file->u.bsize = LFSR_FILE_BNULL;
|
file->ftree = LFSR_FTREE_BNULL();
|
||||||
|
|
||||||
// lookup our parent
|
// lookup our parent
|
||||||
lfsr_tag_t tag;
|
lfsr_tag_t tag;
|
||||||
@@ -9062,12 +9073,12 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
|
|
||||||
// may be a sprout (simple inlined data)
|
// may be a sprout (simple inlined data)
|
||||||
if (err != LFS_ERR_NOENT && tag == LFSR_TAG_DATA) {
|
if (err != LFS_ERR_NOENT && tag == LFSR_TAG_DATA) {
|
||||||
file->u.bsprout = data;
|
file->ftree.u.bsprout = data;
|
||||||
|
|
||||||
// or a direct block
|
// or a direct block
|
||||||
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BLOCK) {
|
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BLOCK) {
|
||||||
err = lfsr_data_readbptr(lfs, &data,
|
err = lfsr_data_readbptr(lfs, &data,
|
||||||
&file->u.bptr);
|
&file->ftree.u.bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -9075,14 +9086,14 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
// or a bshrub (inlined btree)
|
// or a bshrub (inlined btree)
|
||||||
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
|
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
|
||||||
err = lfsr_data_readshrub(lfs, &data, &file->mdir,
|
err = lfsr_data_readshrub(lfs, &data, &file->mdir,
|
||||||
&file->u.bshrub);
|
&file->ftree.u.bshrub);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// or a btree
|
// or a btree
|
||||||
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
|
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
|
||||||
err = lfsr_data_readbtree(lfs, &data, &file->u.btree);
|
err = lfsr_data_readbtree(lfs, &data, &file->ftree.u.btree);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -9103,11 +9114,11 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
file->buffer_size = 0;
|
file->buffer_size = 0;
|
||||||
|
|
||||||
// if our file is small, try to keep the whole thing in our buffer
|
// if our file is small, try to keep the whole thing in our buffer
|
||||||
if (lfsr_file_bsize(file) <= lfs->cfg->cache_size
|
if (lfsr_ftree_size(&file->ftree) <= lfs->cfg->cache_size
|
||||||
&& lfsr_file_bsize(file) <= lfs->cfg->inline_size
|
&& lfsr_ftree_size(&file->ftree) <= lfs->cfg->inline_size
|
||||||
&& lfsr_file_bsize(file) <= lfs->cfg->fragment_size) {
|
&& lfsr_ftree_size(&file->ftree) <= lfs->cfg->fragment_size) {
|
||||||
lfs_ssize_t d = lfsr_file_read_(lfs, file,
|
lfs_ssize_t d = lfsr_file_read_(lfs, file,
|
||||||
0, file->buffer, lfsr_file_bsize(file));
|
0, file->buffer, lfsr_ftree_size(&file->ftree));
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
err = d;
|
err = d;
|
||||||
goto failed_with_buffer;
|
goto failed_with_buffer;
|
||||||
@@ -9116,8 +9127,8 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
// small files remain perpetually unflushed
|
// small files remain perpetually unflushed
|
||||||
file->flags |= LFS_F_UNFLUSHED;
|
file->flags |= LFS_F_UNFLUSHED;
|
||||||
file->buffer_pos = 0;
|
file->buffer_pos = 0;
|
||||||
file->buffer_size = lfsr_file_bsize(file);
|
file->buffer_size = lfsr_ftree_size(&file->ftree);
|
||||||
file->u.bsize = LFSR_FILE_BNULL;
|
file->ftree = LFSR_FTREE_BNULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to tracked mdirs
|
// add to tracked mdirs
|
||||||
@@ -9216,17 +9227,17 @@ static lfs_ssize_t lfsr_file_estimate(lfs_t *lfs, const lfsr_file_t *file) {
|
|||||||
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_->mdir.mid == file->mdir.mid) {
|
||||||
if (lfsr_file_isbsprout(file_)) {
|
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_->u.bsprout);
|
&file_->ftree.u.bsprout);
|
||||||
if (dsize < 0) {
|
if (dsize < 0) {
|
||||||
return dsize;
|
return dsize;
|
||||||
}
|
}
|
||||||
estimate += dsize;
|
estimate += dsize;
|
||||||
|
|
||||||
} else if (lfsr_file_isbshrub(file_)) {
|
} else if (lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)) {
|
||||||
lfs_ssize_t dsize = lfsr_shrub_estimate(lfs,
|
lfs_ssize_t dsize = lfsr_shrub_estimate(lfs,
|
||||||
&file_->u.bshrub);
|
&file_->ftree.u.bshrub);
|
||||||
if (dsize < 0) {
|
if (dsize < 0) {
|
||||||
return dsize;
|
return dsize;
|
||||||
}
|
}
|
||||||
@@ -9242,25 +9253,25 @@ static int lfsr_file_lookupnext(lfs_t *lfs, const lfsr_file_t *file,
|
|||||||
lfs_off_t pos,
|
lfs_off_t pos,
|
||||||
lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_,
|
lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_,
|
||||||
lfsr_bptr_t *bptr_, lfsr_ecksum_t *becksum_) {
|
lfsr_bptr_t *bptr_, lfsr_ecksum_t *becksum_) {
|
||||||
if (pos >= lfsr_file_bsize(file)) {
|
if (pos >= lfsr_ftree_size(&file->ftree)) {
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
// the above size check should make this impossible
|
// the above size check should make this impossible
|
||||||
LFS_ASSERT(!lfsr_file_isbnull(file));
|
LFS_ASSERT(!lfsr_ftree_isbnull(&file->ftree));
|
||||||
|
|
||||||
// inlined sprout?
|
// inlined sprout?
|
||||||
if (lfsr_file_isbsprout(file)) {
|
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
|
||||||
if (bid_) {
|
if (bid_) {
|
||||||
*bid_ = lfsr_data_size(&file->u.bsprout)-1;
|
*bid_ = lfsr_data_size(&file->ftree.u.bsprout)-1;
|
||||||
}
|
}
|
||||||
if (tag_) {
|
if (tag_) {
|
||||||
*tag_ = LFSR_TAG_DATA;
|
*tag_ = LFSR_TAG_DATA;
|
||||||
}
|
}
|
||||||
if (weight_) {
|
if (weight_) {
|
||||||
*weight_ = lfsr_data_size(&file->u.bsprout);
|
*weight_ = lfsr_data_size(&file->ftree.u.bsprout);
|
||||||
}
|
}
|
||||||
if (bptr_) {
|
if (bptr_) {
|
||||||
bptr_->data = file->u.bsprout;
|
bptr_->data = file->ftree.u.bsprout;
|
||||||
}
|
}
|
||||||
if (becksum_) {
|
if (becksum_) {
|
||||||
becksum_->size = -1;
|
becksum_->size = -1;
|
||||||
@@ -9268,18 +9279,18 @@ static int lfsr_file_lookupnext(lfs_t *lfs, const lfsr_file_t *file,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// block pointer?
|
// block pointer?
|
||||||
} else if (lfsr_file_isbptr(file)) {
|
} else if (lfsr_ftree_isbptr(&file->mdir, &file->ftree)) {
|
||||||
if (bid_) {
|
if (bid_) {
|
||||||
*bid_ = lfsr_data_size(&file->u.bptr.data)-1;
|
*bid_ = lfsr_data_size(&file->ftree.u.bptr.data)-1;
|
||||||
}
|
}
|
||||||
if (tag_) {
|
if (tag_) {
|
||||||
*tag_ = LFSR_TAG_BLOCK;
|
*tag_ = LFSR_TAG_BLOCK;
|
||||||
}
|
}
|
||||||
if (weight_) {
|
if (weight_) {
|
||||||
*weight_ = lfsr_data_size(&file->u.bptr.data);
|
*weight_ = lfsr_data_size(&file->ftree.u.bptr.data);
|
||||||
}
|
}
|
||||||
if (bptr_) {
|
if (bptr_) {
|
||||||
*bptr_ = file->u.bptr;
|
*bptr_ = file->ftree.u.bptr;
|
||||||
}
|
}
|
||||||
if (becksum_) {
|
if (becksum_) {
|
||||||
becksum_->size = -1;
|
becksum_->size = -1;
|
||||||
@@ -9287,14 +9298,14 @@ static int lfsr_file_lookupnext(lfs_t *lfs, const lfsr_file_t *file,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// bshrub/btree?
|
// bshrub/btree?
|
||||||
} else if (lfsr_file_isbshruborbtree(file)) {
|
} else if (lfsr_ftree_isbshruborbtree(&file->ftree)) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_rbyd_t rbyd;
|
lfsr_rbyd_t rbyd;
|
||||||
lfsr_srid_t rid;
|
lfsr_srid_t rid;
|
||||||
lfsr_tag_t tag;
|
lfsr_tag_t tag;
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
lfsr_data_t data;
|
lfsr_data_t data;
|
||||||
int err = lfsr_btree_lookupnext_(lfs, &file->u.btree, pos,
|
int err = lfsr_btree_lookupnext_(lfs, &file->ftree.u.btree, pos,
|
||||||
&bid, &rbyd, &rid, &tag, &weight, &data);
|
&bid, &rbyd, &rid, &tag, &weight, &data);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
@@ -9352,36 +9363,37 @@ static int lfsr_file_traverse(lfs_t *lfs, const lfsr_file_t *file,
|
|||||||
lfsr_btraversal_t *btraversal,
|
lfsr_btraversal_t *btraversal,
|
||||||
lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) {
|
lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) {
|
||||||
// bnull/bsprout do nothing
|
// bnull/bsprout do nothing
|
||||||
if (lfsr_file_isbnull(file) || lfsr_file_isbsprout(file)) {
|
if (lfsr_ftree_isbnull(&file->ftree)
|
||||||
|
|| lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// block pointer?
|
// block pointer?
|
||||||
if (lfsr_file_isbptr(file)) {
|
if (lfsr_ftree_isbptr(&file->mdir, &file->ftree)) {
|
||||||
if (btraversal->bid > 0) {
|
if (btraversal->bid > 0) {
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bid_) {
|
if (bid_) {
|
||||||
*bid_ = lfsr_data_size(&file->u.bptr.data)-1;
|
*bid_ = lfsr_data_size(&file->ftree.u.bptr.data)-1;
|
||||||
}
|
}
|
||||||
if (tinfo_) {
|
if (tinfo_) {
|
||||||
tinfo_->tag = LFSR_TAG_BLOCK;
|
tinfo_->tag = LFSR_TAG_BLOCK;
|
||||||
tinfo_->u.bptr = file->u.bptr;
|
tinfo_->u.bptr = file->ftree.u.bptr;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// bshrub/btree?
|
// bshrub/btree?
|
||||||
} else if (lfsr_file_isbshruborbtree(file)) {
|
} else if (lfsr_ftree_isbshruborbtree(&file->ftree)) {
|
||||||
// prevent bshrub root from being traversed, since this is
|
// prevent bshrub root from being traversed, since this is
|
||||||
// just our mdir
|
// just our mdir
|
||||||
if (lfsr_file_isbshrub(file)
|
if (lfsr_ftree_isbshrub(&file->mdir, &file->ftree)
|
||||||
&& btraversal->branch.trunk == 0) {
|
&& btraversal->branch.trunk == 0) {
|
||||||
btraversal->branch = *lfsr_shrub_rbyd(&file->u.bshrub);
|
btraversal->branch = *lfsr_shrub_rbyd(&file->ftree.u.bshrub);
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = lfsr_btree_traverse(lfs,
|
int err = lfsr_btree_traverse(lfs,
|
||||||
lfsr_shrub_rbyd(&file->u.bshrub),
|
lfsr_shrub_rbyd(&file->ftree.u.bshrub),
|
||||||
btraversal,
|
btraversal,
|
||||||
bid_, tinfo_);
|
bid_, tinfo_);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -9455,7 +9467,7 @@ static lfs_ssize_t lfsr_file_readnext(lfs_t *lfs, const lfsr_file_t *file,
|
|||||||
static lfs_ssize_t lfsr_file_read_(lfs_t *lfs, const lfsr_file_t *file,
|
static lfs_ssize_t lfsr_file_read_(lfs_t *lfs, const lfsr_file_t *file,
|
||||||
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
|
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
|
||||||
lfs_off_t pos_ = pos;
|
lfs_off_t pos_ = pos;
|
||||||
while (size > 0 && pos_ < lfsr_file_bsize(file)) {
|
while (size > 0 && pos_ < lfsr_ftree_size(&file->ftree)) {
|
||||||
lfs_ssize_t d = lfsr_file_readnext(lfs, file,
|
lfs_ssize_t d = lfsr_file_readnext(lfs, file,
|
||||||
pos_, buffer, size);
|
pos_, buffer, size);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
@@ -9475,7 +9487,7 @@ static lfs_ssize_t lfsr_file_read_(lfs_t *lfs, const lfsr_file_t *file,
|
|||||||
static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
||||||
const lfsr_attr_t *attrs, lfs_size_t attr_count) {
|
const lfsr_attr_t *attrs, lfs_size_t attr_count) {
|
||||||
// file must be a bshrub/btree here
|
// file must be a bshrub/btree here
|
||||||
LFS_ASSERT(lfsr_file_isbshruborbtree(file));
|
LFS_ASSERT(lfsr_ftree_isbshruborbtree(&file->ftree));
|
||||||
|
|
||||||
// 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
|
||||||
@@ -9485,12 +9497,12 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
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_ != file
|
||||||
&& lfsr_file_isbshruborbtree(file_)
|
&& lfsr_ftree_isbshruborbtree(&file_->ftree)
|
||||||
&& lfsr_btree_cmp(
|
&& lfsr_btree_cmp(
|
||||||
&file_->u.btree,
|
&file_->ftree.u.btree,
|
||||||
&file->u.btree) == 0) {
|
&file->ftree.u.btree) == 0) {
|
||||||
// mark as unerased
|
// mark as unerased
|
||||||
file_->u.btree.eoff = -1;
|
file_->ftree.u.btree.eoff = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9500,8 +9512,8 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
uint8_t scratch_buf[2*LFSR_BRANCH_DSIZE];
|
uint8_t scratch_buf[2*LFSR_BRANCH_DSIZE];
|
||||||
|
|
||||||
// try to commit to the btree
|
// try to commit to the btree
|
||||||
int err = lfsr_btree_commit_(lfs, &file->u.btree,
|
int err = lfsr_btree_commit_(lfs, &file->ftree.u.btree,
|
||||||
lfsr_file_isbshrub(file),
|
lfsr_ftree_isbshrub(&file->mdir, &file->ftree),
|
||||||
scratch_attrs, scratch_buf,
|
scratch_attrs, scratch_buf,
|
||||||
attrs, attr_count,
|
attrs, attr_count,
|
||||||
&attrs, &attr_count);
|
&attrs, &attr_count);
|
||||||
@@ -9537,7 +9549,7 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
// avoid some overflow issues here
|
// avoid some overflow issues here
|
||||||
lfs_ssize_t estimate = (alloc)
|
lfs_ssize_t estimate = (alloc)
|
||||||
? (lfs_size_t)-1
|
? (lfs_size_t)-1
|
||||||
: file->u.bshrub.estimate;
|
: file->ftree.u.bshrub.estimate;
|
||||||
if ((lfs_size_t)estimate <= lfs->cfg->shrub_size) {
|
if ((lfs_size_t)estimate <= lfs->cfg->shrub_size) {
|
||||||
estimate += commit_estimate;
|
estimate += commit_estimate;
|
||||||
}
|
}
|
||||||
@@ -9567,7 +9579,7 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
TAG((alloc)
|
TAG((alloc)
|
||||||
? LFSR_TAG_SHRUBALLOC
|
? LFSR_TAG_SHRUBALLOC
|
||||||
: LFSR_TAG_SHRUBCOMMIT), 0,
|
: LFSR_TAG_SHRUBCOMMIT), 0,
|
||||||
SHRUBCOMMIT(&file->u_.bshrub, attrs, attr_count))));
|
SHRUBCOMMIT(&file->ftree_.u.bshrub, attrs, attr_count))));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -9579,17 +9591,17 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
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_->mdir.mid == file->mdir.mid) {
|
||||||
if (lfsr_file_isbshrub(file_)) {
|
if (lfsr_ftree_isbshrub(&file_->mdir, &file_->ftree)) {
|
||||||
file_->u.bshrub.estimate = estimate;
|
file_->ftree.u.bshrub.estimate = estimate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LFS_ASSERT(file->u.bshrub.estimate = (lfs_size_t)estimate);
|
LFS_ASSERT(file->ftree.u.bshrub.estimate = (lfs_size_t)estimate);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LFS_ASSERT(file->u.bshrub.trunk != 0);
|
LFS_ASSERT(file->ftree.u.bshrub.trunk != 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
evict:;
|
evict:;
|
||||||
@@ -9603,7 +9615,7 @@ evict:;
|
|||||||
// note this may be a new root
|
// note this may be a new root
|
||||||
if (!alloc) {
|
if (!alloc) {
|
||||||
err = lfsr_rbyd_compact(lfs, &rbyd, -1, -1,
|
err = lfsr_rbyd_compact(lfs, &rbyd, -1, -1,
|
||||||
lfsr_shrub_rbyd(&file->u.bshrub));
|
lfsr_shrub_rbyd(&file->ftree.u.bshrub));
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
return err;
|
return err;
|
||||||
@@ -9621,7 +9633,7 @@ evict:;
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
file->u.btree = rbyd;
|
file->ftree.u.btree = rbyd;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9652,26 +9664,26 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
lfs_size_t buf_size = 0;
|
lfs_size_t buf_size = 0;
|
||||||
|
|
||||||
// always convert to bshrub/btree when this function is called
|
// always convert to bshrub/btree when this function is called
|
||||||
if (!lfsr_file_isbshruborbtree(file)) {
|
if (!lfsr_ftree_isbshruborbtree(&file->ftree)) {
|
||||||
// this does risk losing our sprout/leaf if there is an error,
|
// this does risk losing our sprout/leaf if there is an error,
|
||||||
// but note that's already a risk with how file carve deletes
|
// but note that's already a risk with how file carve deletes
|
||||||
// data before insertion
|
// data before insertion
|
||||||
if (lfsr_file_isbsprout(file)) {
|
if (lfsr_ftree_isbsprout(&file->mdir, &file->ftree)) {
|
||||||
attrs_[attr_count_++] = LFSR_ATTR(0,
|
attrs_[attr_count_++] = LFSR_ATTR(0,
|
||||||
DATA, +lfsr_file_bsize(file),
|
DATA, +lfsr_ftree_size(&file->ftree),
|
||||||
DATA(file->u.bsprout));
|
DATA(file->ftree.u.bsprout));
|
||||||
} else if (lfsr_file_isbptr(file)) {
|
} else if (lfsr_ftree_isbptr(&file->mdir, &file->ftree)) {
|
||||||
attrs_[attr_count_++] = LFSR_ATTR(0,
|
attrs_[attr_count_++] = LFSR_ATTR(0,
|
||||||
BLOCK, +lfsr_file_bsize(file),
|
BLOCK, +lfsr_ftree_size(&file->ftree),
|
||||||
FROMBPTR(&file->u.bptr, &buf[buf_size]));
|
FROMBPTR(&file->ftree.u.bptr, &buf[buf_size]));
|
||||||
buf_size += LFSR_BPTR_DSIZE;
|
buf_size += LFSR_BPTR_DSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
file->u.bshrub.blocks[0] = file->mdir.rbyd.blocks[0];
|
file->ftree.u.bshrub.blocks[0] = file->mdir.rbyd.blocks[0];
|
||||||
file->u.bshrub.trunk = 0;
|
file->ftree.u.bshrub.trunk = 0;
|
||||||
file->u.bshrub.weight = 0;
|
file->ftree.u.bshrub.weight = 0;
|
||||||
// force estimate recalculation
|
// force estimate recalculation
|
||||||
file->u.bshrub.estimate = -1;
|
file->ftree.u.bshrub.estimate = -1;
|
||||||
|
|
||||||
if (attr_count_ > 0) {
|
if (attr_count_ > 0) {
|
||||||
LFS_ASSERT(attr_count_ <= sizeof(attrs_)/sizeof(lfsr_attr_t));
|
LFS_ASSERT(attr_count_ <= sizeof(attrs_)/sizeof(lfsr_attr_t));
|
||||||
@@ -9689,7 +9701,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to carve any existing data
|
// try to carve any existing data
|
||||||
while (pos < lfsr_file_bsize(file)) {
|
while (pos < lfsr_ftree_size(&file->ftree)) {
|
||||||
lfsr_bid_t bid_;
|
lfsr_bid_t bid_;
|
||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
lfsr_bid_t weight_;
|
lfsr_bid_t weight_;
|
||||||
@@ -9860,16 +9872,16 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// need a hole?
|
// need a hole?
|
||||||
if (pos > lfsr_file_bsize(file)) {
|
if (pos > lfsr_ftree_size(&file->ftree)) {
|
||||||
// can we coalesce?
|
// can we coalesce?
|
||||||
if (lfsr_file_bsize(file) > 0) {
|
if (lfsr_ftree_size(&file->ftree) > 0) {
|
||||||
attrs_[attr_count_++] = LFSR_ATTR(lfsr_file_bsize(file)-1,
|
attrs_[attr_count_++] = LFSR_ATTR(lfsr_ftree_size(&file->ftree)-1,
|
||||||
GROW, +(pos - lfsr_file_bsize(file)), NULL());
|
GROW, +(pos - lfsr_ftree_size(&file->ftree)), NULL());
|
||||||
|
|
||||||
// new hole
|
// new hole
|
||||||
} else {
|
} else {
|
||||||
attrs_[attr_count_++] = LFSR_ATTR(lfsr_file_bsize(file),
|
attrs_[attr_count_++] = LFSR_ATTR(lfsr_ftree_size(&file->ftree),
|
||||||
DATA, +(pos - lfsr_file_bsize(file)), NULL());
|
DATA, +(pos - lfsr_ftree_size(&file->ftree)), NULL());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9946,8 +9958,8 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
if (pos > 0
|
if (pos > 0
|
||||||
&& lfs->cfg->crystal_thresh > 0
|
&& lfs->cfg->crystal_thresh > 0
|
||||||
&& (lfs_soff_t)(pos - (lfs->cfg->crystal_thresh-1))
|
&& (lfs_soff_t)(pos - (lfs->cfg->crystal_thresh-1))
|
||||||
< (lfs_soff_t)lfsr_file_bsize(file)
|
< (lfs_soff_t)lfsr_ftree_size(&file->ftree)
|
||||||
&& lfsr_file_bsize(file) > 0
|
&& lfsr_ftree_size(&file->ftree) > 0
|
||||||
// don't bother to lookup left after the first block
|
// don't bother to lookup left after the first block
|
||||||
&& !aligned) {
|
&& !aligned) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
@@ -10008,14 +10020,14 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
// if we haven't already exceeded our crystallization threshold,
|
// if we haven't already exceeded our crystallization threshold,
|
||||||
// find right crystal neighbor
|
// find right crystal neighbor
|
||||||
if (crystal_end - crystal_start < lfs->cfg->crystal_thresh
|
if (crystal_end - crystal_start < lfs->cfg->crystal_thresh
|
||||||
&& lfsr_file_bsize(file) > 0) {
|
&& lfsr_ftree_size(&file->ftree) > 0) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
lfsr_tag_t tag;
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
int err = lfsr_file_lookupnext(lfs, file,
|
int err = lfsr_file_lookupnext(lfs, file,
|
||||||
lfs_min32(
|
lfs_min32(
|
||||||
crystal_start + (lfs->cfg->crystal_thresh-1),
|
crystal_start + (lfs->cfg->crystal_thresh-1),
|
||||||
lfsr_file_bsize(file)-1),
|
lfsr_ftree_size(&file->ftree)-1),
|
||||||
&bid, &tag, &weight, &bptr, NULL);
|
&bid, &tag, &weight, &bptr, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
@@ -10051,7 +10063,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
// crystal for this
|
// crystal for this
|
||||||
block_start = crystal_start;
|
block_start = crystal_start;
|
||||||
if (crystal_start > 0
|
if (crystal_start > 0
|
||||||
&& lfsr_file_bsize(file) > 0
|
&& lfsr_ftree_size(&file->ftree) > 0
|
||||||
// don't bother to lookup left after the first block
|
// don't bother to lookup left after the first block
|
||||||
&& !aligned) {
|
&& !aligned) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
@@ -10061,7 +10073,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
int err = lfsr_file_lookupnext(lfs, file,
|
int err = lfsr_file_lookupnext(lfs, file,
|
||||||
lfs_min32(
|
lfs_min32(
|
||||||
crystal_start-1,
|
crystal_start-1,
|
||||||
lfsr_file_bsize(file)-1),
|
lfsr_ftree_size(&file->ftree)-1),
|
||||||
&bid, &tag, &weight, &bptr, &becksum);
|
&bid, &tag, &weight, &bptr, &becksum);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
@@ -10138,14 +10150,14 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
+ (lfs->cfg->block_size - bptr.data.u.disk.off),
|
+ (lfs->cfg->block_size - bptr.data.u.disk.off),
|
||||||
lfs_max32(
|
lfs_max32(
|
||||||
pos + size,
|
pos + size,
|
||||||
lfsr_file_bsize(file)))) {
|
lfsr_ftree_size(&file->ftree)))) {
|
||||||
// keep track of the next highest priority data offset
|
// keep track of the next highest priority data offset
|
||||||
lfs_ssize_t d = lfs_min32(
|
lfs_ssize_t d = lfs_min32(
|
||||||
block_start
|
block_start
|
||||||
+ (lfs->cfg->block_size - bptr.data.u.disk.off),
|
+ (lfs->cfg->block_size - bptr.data.u.disk.off),
|
||||||
lfs_max32(
|
lfs_max32(
|
||||||
pos + size,
|
pos + size,
|
||||||
lfsr_file_bsize(file))) - pos_;
|
lfsr_ftree_size(&file->ftree))) - pos_;
|
||||||
|
|
||||||
// any data in our buffer?
|
// any data in our buffer?
|
||||||
if (pos_ < pos + size && size > 0) {
|
if (pos_ < pos + size && size > 0) {
|
||||||
@@ -10172,7 +10184,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// any data on disk?
|
// any data on disk?
|
||||||
if (pos_ < lfsr_file_bsize(file)) {
|
if (pos_ < lfsr_ftree_size(&file->ftree)) {
|
||||||
lfsr_bid_t bid_;
|
lfsr_bid_t bid_;
|
||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
lfsr_bid_t weight_;
|
lfsr_bid_t weight_;
|
||||||
@@ -10323,7 +10335,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
|
|
||||||
// do we have a left sibling?
|
// do we have a left sibling?
|
||||||
if (fragment_start > 0
|
if (fragment_start > 0
|
||||||
&& lfsr_file_bsize(file) >= fragment_start
|
&& lfsr_ftree_size(&file->ftree) >= fragment_start
|
||||||
// don't bother to lookup left after first fragment
|
// don't bother to lookup left after first fragment
|
||||||
&& !aligned) {
|
&& !aligned) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
@@ -10361,7 +10373,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
// do we have a right sibling?
|
// do we have a right sibling?
|
||||||
//
|
//
|
||||||
// note this may the same as our left sibling
|
// note this may the same as our left sibling
|
||||||
if (fragment_end < lfsr_file_bsize(file)
|
if (fragment_end < lfsr_ftree_size(&file->ftree)
|
||||||
// don't bother to lookup right if fragment is already full
|
// don't bother to lookup right if fragment is already full
|
||||||
&& fragment_end - fragment_start < lfs->cfg->fragment_size) {
|
&& fragment_end - fragment_start < lfs->cfg->fragment_size) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
@@ -10449,7 +10461,7 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// any data in our btree?
|
// any data in our btree?
|
||||||
if (pos_ < lfsr_file_bsize(file)) {
|
if (pos_ < lfsr_ftree_size(&file->ftree)) {
|
||||||
// bypass buffer?
|
// bypass buffer?
|
||||||
if ((lfs_size_t)d >= lfs->cfg->cache_size) {
|
if ((lfs_size_t)d >= lfs->cfg->cache_size) {
|
||||||
lfs_ssize_t d_ = lfsr_file_readnext(lfs, file,
|
lfs_ssize_t d_ = lfsr_file_readnext(lfs, file,
|
||||||
@@ -10738,14 +10750,14 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
// or bptr
|
// or bptr
|
||||||
//
|
//
|
||||||
// this is convenient because bptrs are a bit annoying to commit
|
// this is convenient because bptrs are a bit annoying to commit
|
||||||
LFS_ASSERT(!lfsr_file_isbsprout(file));
|
LFS_ASSERT(!lfsr_ftree_isbsprout(&file->mdir, &file->ftree));
|
||||||
LFS_ASSERT(!lfsr_file_isbptr(file));
|
LFS_ASSERT(!lfsr_ftree_isbptr(&file->mdir, &file->ftree));
|
||||||
// small files should start as zero, const prop should optimize this out
|
// small files should start as zero, const prop should optimize this out
|
||||||
LFS_ASSERT(!lfsr_f_isunflushed(file->flags)
|
LFS_ASSERT(!lfsr_f_isunflushed(file->flags)
|
||||||
|| file->buffer_pos == 0);
|
|| file->buffer_pos == 0);
|
||||||
// small files/btree should be exclusive here
|
// small files/btree should be exclusive here
|
||||||
LFS_ASSERT(!lfsr_f_isunflushed(file->flags)
|
LFS_ASSERT(!lfsr_f_isunflushed(file->flags)
|
||||||
|| lfsr_file_bsize(file) == 0);
|
|| lfsr_ftree_size(&file->ftree) == 0);
|
||||||
// small files must be inlined entirely in our buffer
|
// small files must be inlined entirely in our buffer
|
||||||
LFS_ASSERT(!lfsr_f_isunflushed(file->flags)
|
LFS_ASSERT(!lfsr_f_isunflushed(file->flags)
|
||||||
|| (file->buffer_size <= lfs->cfg->cache_size
|
|| (file->buffer_size <= lfs->cfg->cache_size
|
||||||
@@ -10768,13 +10780,13 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
? LFSR_ATTR(file->mdir.mid,
|
? LFSR_ATTR(file->mdir.mid,
|
||||||
WIDE(DATA), 0,
|
WIDE(DATA), 0,
|
||||||
BUF(file->buffer, file->buffer_size))
|
BUF(file->buffer, file->buffer_size))
|
||||||
: (lfsr_file_isbshrub(file))
|
: (lfsr_ftree_isbshrub(&file->mdir, &file->ftree))
|
||||||
? LFSR_ATTR(file->mdir.mid,
|
? LFSR_ATTR(file->mdir.mid,
|
||||||
WIDE(SHRUBTRUNK), 0,
|
WIDE(SHRUBTRUNK), 0,
|
||||||
SHRUBTRUNK(&file->u_.bshrub))
|
SHRUBTRUNK(&file->ftree_.u.bshrub))
|
||||||
: LFSR_ATTR(file->mdir.mid,
|
: LFSR_ATTR(file->mdir.mid,
|
||||||
WIDE(BTREE), 0,
|
WIDE(BTREE), 0,
|
||||||
FROMBTREE(&file->u.btree, buf))));
|
FROMBTREE(&file->ftree.u.btree, buf))));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -10797,7 +10809,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
} else {
|
} else {
|
||||||
file_->flags &= ~LFS_F_UNFLUSHED;
|
file_->flags &= ~LFS_F_UNFLUSHED;
|
||||||
}
|
}
|
||||||
file_->u = file->u;
|
file_->ftree = file->ftree;
|
||||||
file_->buffer_pos = file->buffer_pos;
|
file_->buffer_pos = file->buffer_pos;
|
||||||
LFS_ASSERT(file->buffer_size <= lfs->cfg->cache_size);
|
LFS_ASSERT(file->buffer_size <= lfs->cfg->cache_size);
|
||||||
memcpy(file_->buffer, file->buffer, file->buffer_size);
|
memcpy(file_->buffer, file->buffer, file->buffer_size);
|
||||||
@@ -10887,7 +10899,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
|||||||
if (file->buffer_pos > 0
|
if (file->buffer_pos > 0
|
||||||
|| file->buffer_size < lfs_min32(
|
|| file->buffer_size < lfs_min32(
|
||||||
size_,
|
size_,
|
||||||
lfsr_file_bsize(file))) {
|
lfsr_ftree_size(&file->ftree))) {
|
||||||
err = lfsr_file_flush(lfs, file);
|
err = lfsr_file_flush(lfs, file);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto failed;
|
goto failed;
|
||||||
@@ -10916,7 +10928,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
|||||||
file->flags |= LFS_F_UNFLUSHED;
|
file->flags |= LFS_F_UNFLUSHED;
|
||||||
file->buffer_pos = 0;
|
file->buffer_pos = 0;
|
||||||
file->buffer_size = size_;
|
file->buffer_size = size_;
|
||||||
file->u.bsize = LFSR_FILE_BNULL;
|
file->ftree = LFSR_FTREE_BNULL();
|
||||||
|
|
||||||
// truncate our file normally
|
// truncate our file normally
|
||||||
} else {
|
} else {
|
||||||
@@ -10990,10 +11002,10 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
|||||||
// if our data is not already in our buffer we unfortunately
|
// if our data is not already in our buffer we unfortunately
|
||||||
// need to flush so our buffer is available to hold everything
|
// need to flush so our buffer is available to hold everything
|
||||||
if (file->buffer_pos + file->buffer_size
|
if (file->buffer_pos + file->buffer_size
|
||||||
< lfsr_file_bsize(file)
|
< lfsr_ftree_size(&file->ftree)
|
||||||
|| file->buffer_size < lfs_min32(
|
|| file->buffer_size < lfs_min32(
|
||||||
size_,
|
size_,
|
||||||
lfsr_file_bsize(file))) {
|
lfsr_ftree_size(&file->ftree))) {
|
||||||
err = lfsr_file_flush(lfs, file);
|
err = lfsr_file_flush(lfs, file);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto failed;
|
goto failed;
|
||||||
@@ -11002,9 +11014,9 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
|||||||
file->buffer_size = 0;
|
file->buffer_size = 0;
|
||||||
|
|
||||||
lfs_ssize_t d = lfsr_file_read_(lfs, file,
|
lfs_ssize_t d = lfsr_file_read_(lfs, file,
|
||||||
lfsr_file_bsize(file) - lfs_min32(
|
lfsr_ftree_size(&file->ftree) - lfs_min32(
|
||||||
size_,
|
size_,
|
||||||
lfsr_file_bsize(file)),
|
lfsr_ftree_size(&file->ftree)),
|
||||||
file->buffer, size_);
|
file->buffer, size_);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
err = d;
|
err = d;
|
||||||
@@ -11034,7 +11046,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
|||||||
file->flags |= LFS_F_UNFLUSHED;
|
file->flags |= LFS_F_UNFLUSHED;
|
||||||
file->buffer_pos = 0;
|
file->buffer_pos = 0;
|
||||||
file->buffer_size = size_;
|
file->buffer_size = size_;
|
||||||
file->u.bsize = LFSR_FILE_BNULL;
|
file->ftree = LFSR_FTREE_BNULL();
|
||||||
|
|
||||||
// fruncate our file normally
|
// fruncate our file normally
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -524,12 +524,8 @@ typedef struct lfsr_shrub {
|
|||||||
lfs_size_t estimate;
|
lfs_size_t estimate;
|
||||||
} lfsr_shrub_t;
|
} lfsr_shrub_t;
|
||||||
|
|
||||||
typedef struct lfsr_file {
|
// the lfsr_ftree_t struct is a sort of proto-file
|
||||||
lfsr_openedmdir_t *next;
|
typedef struct lfsr_ftree {
|
||||||
|
|
||||||
// files contain both an active tree and staging tree, to allow
|
|
||||||
// staging during mdir compacts
|
|
||||||
//
|
|
||||||
// navigating this union is a bit tricky, and relies on the related
|
// navigating this union is a bit tricky, and relies on the related
|
||||||
// mdir's block:
|
// mdir's block:
|
||||||
//
|
//
|
||||||
@@ -539,15 +535,22 @@ typedef struct lfsr_file {
|
|||||||
// sign(size)=0, data.block==mdir.block => bshrub
|
// sign(size)=0, data.block==mdir.block => bshrub
|
||||||
// sign(size)=0, data.block!=mdir.block => btree
|
// sign(size)=0, data.block!=mdir.block => btree
|
||||||
//
|
//
|
||||||
lfsr_mdir_t mdir;
|
|
||||||
union {
|
union {
|
||||||
lfs_soff_t bsize;
|
lfs_soff_t size;
|
||||||
lfsr_data_t bsprout;
|
lfsr_data_t bsprout;
|
||||||
lfsr_bptr_t bptr;
|
lfsr_bptr_t bptr;
|
||||||
lfsr_shrub_t bshrub;
|
lfsr_shrub_t bshrub;
|
||||||
lfsr_btree_t btree;
|
lfsr_btree_t btree;
|
||||||
} u, u_;
|
} u;
|
||||||
|
} lfsr_ftree_t;
|
||||||
|
|
||||||
|
typedef struct lfsr_file {
|
||||||
|
lfsr_openedmdir_t *next;
|
||||||
|
lfsr_mdir_t mdir;
|
||||||
|
// files contain both an active tree and staging tree, to allow
|
||||||
|
// staging during mdir compacts
|
||||||
|
lfsr_ftree_t ftree;
|
||||||
|
lfsr_ftree_t ftree_;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
lfs_off_t pos;
|
lfs_off_t pos;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user