Implemented dir seek/tell (untested) and tweaked recursive removes

Recursive removes is proving more challenging to implement than I
expected. The problem with the previous approach is that it moved the
mid into a potentially non-sensical position with the expectation it
would be updated in lfsr_dir_read because the rid overflows the current
weight (since dropping mdirs always set the weight to zero).

But if an unrelated mdir commit followed that happened to touch that
nonsense mid, the mdir would incorrectly be updated to the previous
block, causing problems for the dir's read state.

---

The solution here is to toss all of that out and rely solely on directory
position updates, which are a bit simpler.

So in lfsr_dir_read, if our mid/rid is deleted, we perform a full
rewind+seek to the new position. This can be more costly, but since the
most common case, recursive removal, leaves us with all mid/rids < pos
deleted, it should only add a single mtree lookup per lfsr_dir_read.

Also added prototypes for dir seek/tell/rewind, since we're using
they're logic for this. Though these aren't yet tested. These are built
on the new function lfsr_mtree_seek which captures the common logic of
seek over multiple mdirs in the mtree efficiently, and skips unnecessary
rid lookups where possible.
This commit is contained in:
Christopher Haster
2023-07-20 23:28:01 -05:00
parent b1187595d6
commit d6e6ecdc2a
2 changed files with 136 additions and 84 deletions
+4
View File
@@ -420,6 +420,7 @@ typedef struct lfs_dir {
typedef struct lfsr_dir {
lfsr_openedmdir_t mdir;
lfs_size_t did;
lfs_off_t pos;
} lfsr_dir_t;
@@ -741,6 +742,7 @@ int lfsr_dir_read(lfs_t *lfs, lfsr_dir_t *dir, struct lfs_info *info);
//
// Returns a negative error code on failure.
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
int lfsr_dir_seek(lfs_t *lfs, lfsr_dir_t *dir, lfs_off_t off);
// Return the position of the directory
//
@@ -749,11 +751,13 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
//
// Returns the position of the directory, or a negative error code on failure.
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
lfs_soff_t lfsr_dir_tell(lfs_t *lfs, lfsr_dir_t *dir);
// Change the position of the directory to the beginning of the directory
//
// Returns a negative error code on failure.
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
int lfsr_dir_rewind(lfs_t *lfs, lfsr_dir_t *dir);
/// Filesystem-level filesystem operations