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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user