When using _lfs_remove_ to remove a directory there is a check to see if the directory is not empty:
} else if (dir.d.size != sizeof(dir.d)+4) {
return LFS_ERR_NOTEMPTY;
}
Am I right in thinking this check is purely there to give "expected behavior" for a filesystem and if these two lines were commented out the filesystem would be still ok (not corrupted) if a directory that is not empty is deleted?
Reason why is that it would be useful if a folder contained a lot of files to be able to quickly delete them all at once rather than use _lfs_dir_open_ _lfs_dir_read_ to delete each file in the folder individually (which takes a lot of unnecessary writes).
Huh, you're absolutely right, I can't think of a good reason not to...
Deviating from the standard usually isn't a great idea, but in this case it's easy enough for the porting layer to add back the check and not possible to get the fast directory deletes otherwise. It also shouldn't be that surprising to a user.
+1 on this request.
Quickly deleting an entire directory tree would be a useful addition for my use case (and I imagine others as well).
+1: maybe having an extra lfs_remove_recursive() or lfs_remove_r() for this purpose.
@hathach that's a good idea for adding this without breaking compatibility
To make sure I'm understanding, if this change is made and a non-empty directory is deleted, are the files/directories it contained also freed, or are they just orphaned and permanently taking up space in storage?
They are also "freed".
lfs doesn't have any global idea of what blocks are in use.
If a file or directory doesn't have a "path" to the super block it simply doesn't exist and the blocks it occupied are considered free.
I didn't notice until now that this was referring to v1; is it still valid in v2? The equivalent check in v2 is:
if (dir.count > 0 || dir.split) {
return LFS_ERR_NOTEMPTY;
}
As far as I can tell from poking around, it should be fine to comment this out, but wanted to double-check.
This is still valid in v2, there were a lot of changes to the representation of directories inside a block but the block-level data structure is the same. Oh and directories are now sorted.
After looking into this more, there are some complications with the threaded linked-list. LittleFS keeps a threaded linked-list that contains all directory blocks. This is to make it possible to traverse the tree with bounded RAM (more info here).
If we delete a directory, we end up with a temporary orphan until we remove the directory from the threaded linked-list.
Since directories may contain other directories, this would mean orphans may contain other orphans. To handle this we would need to traverse the threaded linked-list multiple times until there are no more orphans.
Just a note, this is currently low priority for me (there are enough bugs that need fixing).
I _am_ looking into possibly getting rid of the threaded linked-list, but I'm not sure if it is possible yet.
Most helpful comment
This is still valid in v2, there were a lot of changes to the representation of directories inside a block but the block-level data structure is the same. Oh and directories are now sorted.
After looking into this more, there are some complications with the threaded linked-list. LittleFS keeps a threaded linked-list that contains all directory blocks. This is to make it possible to traverse the tree with bounded RAM (more info here).
If we delete a directory, we end up with a temporary orphan until we remove the directory from the threaded linked-list.
Since directories may contain other directories, this would mean orphans may contain other orphans. To handle this we would need to traverse the threaded linked-list multiple times until there are no more orphans.
Just a note, this is currently low priority for me (there are enough bugs that need fixing).
I _am_ looking into possibly getting rid of the threaded linked-list, but I'm not sure if it is possible yet.