Implicitly ckpoint alloc in lfsr_mdir_commit, merged prepareappend

All in-flight blocks should be tracked by at least an open file handle
when calling lfsr_mdir_commit. It's the internals of lfsr_mdir_commit
that are really protected by the lfsr_alloc_ckpoint system.

Making lfsr_mdir_commit implicitly call lfsr_alloc_ckpoint removes one
step that was easy to forget, and means we don't need to pepper every
function with lfsr_alloc_ckpoint willy-nilly.

This also merges lfsr_fs_prepareappend -> lfsr_fs_mkconsistent, which
were really two names for the same function. lfsr_fs_grow not calling
lfsr_fs_prepareappend made this name potentially confusing.

Code changes:

           code          stack
  before: 33942           2592
  after:  33922 (-0.1%)   2592 (+0.0%)
This commit is contained in:
Christopher Haster
2024-06-12 11:56:04 -05:00
parent d64cfc7eaa
commit 1e7d1f34b1
+20 -37
View File
@@ -6792,6 +6792,9 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// lfs->mroot must have mid=-1 // lfs->mroot must have mid=-1
LFS_ASSERT(lfs->mroot.mid == -1); LFS_ASSERT(lfs->mroot.mid == -1);
// checkpoint the allocator
lfs_alloc_ckpoint(lfs);
// play out any attrs that affect our grm _before_ committing to disk, // play out any attrs that affect our grm _before_ committing to disk,
// keep in mind we revert to on-disk gstate if we run into an error // keep in mind we revert to on-disk gstate if we run into an error
lfsr_smid_t mid_ = mdir->mid; lfsr_smid_t mid_ = mdir->mid;
@@ -9127,12 +9130,9 @@ static int lfsr_fs_fixorphans(lfs_t *lfs) {
} }
// prepare the filesystem for mutation // prepare the filesystem for mutation
static int lfsr_fs_preparemutation(lfs_t *lfs) { int lfsr_fs_mkconsistent(lfs_t *lfs) {
// checkpoint the allocator
lfs_alloc_ckpoint(lfs);
// fix pending grms // fix pending grms
bool inconsistent = false; bool wasinconsistent = false;
if (lfsr_grm_hasrm(&lfs->grm)) { if (lfsr_grm_hasrm(&lfs->grm)) {
if (lfsr_grm_count(&lfs->grm) == 2) { if (lfsr_grm_count(&lfs->grm) == 2) {
LFS_DEBUG("Fixing grm " LFS_DEBUG("Fixing grm "
@@ -9146,16 +9146,12 @@ static int lfsr_fs_preparemutation(lfs_t *lfs) {
lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits,
lfsr_mid_rid(lfs, lfs->grm.mids[0])); lfsr_mid_rid(lfs, lfs->grm.mids[0]));
} }
inconsistent = true; wasinconsistent = true;
int err = lfsr_fs_fixgrm(lfs); int err = lfsr_fs_fixgrm(lfs);
if (err) { if (err) {
return err; return err;
} }
// checkpoint the allocator again since fixgrm completed
// some work
lfs_alloc_ckpoint(lfs);
} }
// fix orphaned files // fix orphaned files
@@ -9165,28 +9161,20 @@ static int lfsr_fs_preparemutation(lfs_t *lfs) {
// //
if (lfs->hasorphans) { if (lfs->hasorphans) {
LFS_DEBUG("Fixing orphans..."); LFS_DEBUG("Fixing orphans...");
inconsistent = true; wasinconsistent = true;
int err = lfsr_fs_fixorphans(lfs); int err = lfsr_fs_fixorphans(lfs);
if (err) { if (err) {
return err; return err;
} }
// checkpoint the allocator again since fixorphans completed
// some work
lfs_alloc_ckpoint(lfs);
} }
if (inconsistent) { if (wasinconsistent) {
LFS_DEBUG("littlefs is now consistent"); LFS_DEBUG("littlefs is now consistent");
} }
return 0; return 0;
} }
int lfsr_fs_mkconsistent(lfs_t *lfs) {
return lfsr_fs_preparemutation(lfs);
}
int lfsr_fs_grow(lfs_t *lfs, lfs_size_t block_count_) { int lfsr_fs_grow(lfs_t *lfs, lfs_size_t block_count_) {
// shrinking the filesystem is not supported // shrinking the filesystem is not supported
@@ -9197,15 +9185,14 @@ int lfsr_fs_grow(lfs_t *lfs, lfs_size_t block_count_) {
return 0; return 0;
} }
// Note we do _not_ call lfsr_fs_preparemutation here. This is a bit // Note we do _not_ call lfsr_fs_mkconsistent here. This is a bit scary,
// scary, but we should be ok as long as we patch grms in // but we should be ok as long as we patch grms in lfsr_mdir_commit and
// lfsr_mdir_commit and only commit to the mroot. // only commit to the mroot.
// //
// Calling lfsr_fs_preparemutation risks locking our filesystem up trying // Calling lfsr_fs_mkconsistent risks locking our filesystem up trying
// to fix grms/orphans before we can commit the new filesystem size. If // to fix grms/orphans before we can commit the new filesystem size. If
// we don't, we should always be able to recover a stuck filesystem with // we don't, we should always be able to recover a stuck filesystem with
// lfsr_fs_grow. // lfsr_fs_grow.
//
LFS_DEBUG("Growing littlefs %"PRId32"x%"PRId32" -> %"PRId32"x%"PRId32, LFS_DEBUG("Growing littlefs %"PRId32"x%"PRId32" -> %"PRId32"x%"PRId32,
lfs->cfg->block_size, lfs->block_count, lfs->cfg->block_size, lfs->block_count,
@@ -9219,7 +9206,6 @@ int lfsr_fs_grow(lfs_t *lfs, lfs_size_t block_count_) {
lfs->block_count = block_count_; lfs->block_count = block_count_;
// discard stale lookahead buffer // discard stale lookahead buffer
lfs_alloc_discard(lfs); lfs_alloc_discard(lfs);
lfs_alloc_ckpoint(lfs);
// update our on-disk config // update our on-disk config
int err = lfsr_mdir_commit(lfs, &lfs->mroot, LFSR_ATTRS( int err = lfsr_mdir_commit(lfs, &lfs->mroot, LFSR_ATTRS(
@@ -9253,7 +9239,7 @@ static inline bool lfsr_f_iszombie(uint32_t flags);
int lfsr_mkdir(lfs_t *lfs, const char *path) { int lfsr_mkdir(lfs_t *lfs, const char *path) {
// prepare our filesystem for writing // prepare our filesystem for writing
int err = lfsr_fs_preparemutation(lfs); int err = lfsr_fs_mkconsistent(lfs);
if (err) { if (err) {
return err; return err;
} }
@@ -9417,7 +9403,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
int lfsr_remove(lfs_t *lfs, const char *path) { int lfsr_remove(lfs_t *lfs, const char *path) {
// prepare our filesystem for writing // prepare our filesystem for writing
int err = lfsr_fs_preparemutation(lfs); int err = lfsr_fs_mkconsistent(lfs);
if (err) { if (err) {
return err; return err;
} }
@@ -9548,7 +9534,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) {
int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) {
// prepare our filesystem for writing // prepare our filesystem for writing
int err = lfsr_fs_preparemutation(lfs); int err = lfsr_fs_mkconsistent(lfs);
if (err) { if (err) {
return err; return err;
} }
@@ -10185,7 +10171,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
if (!lfsr_o_isrdonly(flags)) { if (!lfsr_o_isrdonly(flags)) {
// prepare our filesystem for writing // prepare our filesystem for writing
int err = lfsr_fs_preparemutation(lfs); int err = lfsr_fs_mkconsistent(lfs);
if (err) { if (err) {
return err; return err;
} }
@@ -11700,7 +11686,6 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
// checkpoint the allocator // checkpoint the allocator
lfs_alloc_ckpoint(lfs); lfs_alloc_ckpoint(lfs);
int err;
// update pos if we are appending // update pos if we are appending
lfs_off_t pos = file->pos; lfs_off_t pos = file->pos;
@@ -11721,6 +11706,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
const uint8_t *buffer_ = buffer; const uint8_t *buffer_ = buffer;
lfs_size_t written = 0; lfs_size_t written = 0;
int err;
while (size > 0) { while (size > 0) {
// bypass buffer? // bypass buffer?
// //
@@ -11860,9 +11846,9 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) {
// checkpoint the allocator // checkpoint the allocator
lfs_alloc_ckpoint(lfs); lfs_alloc_ckpoint(lfs);
int err;
// flush our buffer if it contains any unwritten data // flush our buffer if it contains any unwritten data
int err;
if (lfsr_f_isunflush(file->o.flags) if (lfsr_f_isunflush(file->o.flags)
&& file->buffer.size != 0) { && file->buffer.size != 0) {
// flush // flush
@@ -11941,9 +11927,6 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
goto failed; goto failed;
} }
// checkpoint the allocator again
lfs_alloc_ckpoint(lfs);
// commit any changes to our file's metadata // commit any changes to our file's metadata
lfsr_attr_t attrs[2]; lfsr_attr_t attrs[2];
lfs_size_t attr_count = 0; lfs_size_t attr_count = 0;
@@ -12136,9 +12119,9 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
// checkpoint the allocator // checkpoint the allocator
lfs_alloc_ckpoint(lfs); lfs_alloc_ckpoint(lfs);
int err;
// does our file become small? // does our file become small?
int err;
if (size_ <= lfsr_file_inlinesize(lfs, file)) { if (size_ <= lfsr_file_inlinesize(lfs, file)) {
// 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
@@ -12243,9 +12226,9 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
// checkpoint the allocator // checkpoint the allocator
lfs_alloc_ckpoint(lfs); lfs_alloc_ckpoint(lfs);
int err;
// does our file become small? // does our file become small?
int err;
if (size_ <= lfsr_file_inlinesize(lfs, file)) { if (size_ <= lfsr_file_inlinesize(lfs, file)) {
// 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