Dropped the HASORPHAN scan in lfsr_mount
The motivation here is to simplify lfsr_mount, but there's a number of
knock-on effects.
For one, lfsr_mount should now be faster on filesystems with large
blocks:
O(nb(log b)(log_b n)) -> O(nb(log_b n))
But we now no longer check if our filesystem contains orphaned
stickynotes or unknown filetypes:
- Orphaned stickynotes turned out to not be a big deal. If we find
orphans we'd need to do a second traversal to remove them anyways (no
mutation allowed in lfsr_mount), so this actually ends up a net
improvement in the found-orphan case.
If anything, doing a traversal on first write sets user expectations
correctly, and can be offloaded with lfsr_fs_mkconsistent or
lfsr_fs_gc.
- Unknown filetypes are a bit more annoying (I actually forgot about
this check), but unknown filetypes that require special care should
probably set WCOMPAT/RCOMPAT flags.
Allowing unknown filetypes is a bit more flexible in cases where a
filesystem image is being shared between drivers with different
features (bootloader + app for example).
Though we should probably add more checks/tests that we're handling
these correctly now that we no longer just bail during mount...
Also renamed LFS_I_HASORPHANS -> LFS_I_UNTIDY.
Not doing something is cheaper than doing something, so this saves a bit
of code:
code stack ctx
before: 38120 2624 752
after: 38020 (-0.3%) 2624 (+0.0%) 752 (+0.0%)
This commit is contained in:
@@ -7257,8 +7257,8 @@ static inline bool lfsr_m_issync(uint32_t flags) {
|
||||
}
|
||||
|
||||
// internal fs flags
|
||||
static inline bool lfsr_i_hasorphans(uint32_t flags) {
|
||||
return flags & LFS_I_HASORPHANS;
|
||||
static inline bool lfsr_i_isuntidy(uint32_t flags) {
|
||||
return flags & LFS_I_UNTIDY;
|
||||
}
|
||||
|
||||
static inline bool lfsr_i_isuncompacted(uint32_t flags) {
|
||||
@@ -7271,7 +7271,7 @@ static inline bool lfsr_i_isuncompacted(uint32_t flags) {
|
||||
static inline uint8_t lfsr_grm_count(const lfs_t *lfs);
|
||||
|
||||
static bool lfsr_fs_isinconsistent(const lfs_t *lfs) {
|
||||
return lfsr_grm_count(lfs) > 0 || lfsr_i_hasorphans(lfs->flags);
|
||||
return lfsr_grm_count(lfs) > 0 || lfsr_i_isuntidy(lfs->flags);
|
||||
}
|
||||
|
||||
static bool lfsr_fs_canlookahead(const lfs_t *lfs) {
|
||||
@@ -10048,7 +10048,7 @@ static int lfsr_mtree_traverse(lfs_t *lfs, lfsr_traversal_t *t,
|
||||
}
|
||||
|
||||
// needed in lfsr_mtree_gc
|
||||
static int lfsr_fs_fixorphans_(lfs_t *lfs, lfsr_mdir_t *mdir);
|
||||
static int lfsr_fs_mktidy_(lfs_t *lfs, lfsr_mdir_t *mdir);
|
||||
static void lfs_alloc_ckpoint(lfs_t *lfs);
|
||||
static void lfs_alloc_markfree(lfs_t *lfs);
|
||||
|
||||
@@ -10079,10 +10079,10 @@ dropped:;
|
||||
|
||||
// mkconsistencing mdirs?
|
||||
if (lfsr_t_ismkconsistent(t->o.o.flags)
|
||||
&& lfsr_i_hasorphans(lfs->flags)
|
||||
&& lfsr_i_isuntidy(lfs->flags)
|
||||
&& tag == LFSR_TAG_MDIR) {
|
||||
lfsr_mdir_t *mdir = (lfsr_mdir_t*)bptr.data.u.buffer;
|
||||
err = lfsr_fs_fixorphans_(lfs, mdir);
|
||||
err = lfsr_fs_mktidy_(lfs, mdir);
|
||||
if (err) {
|
||||
goto failed;
|
||||
}
|
||||
@@ -10156,7 +10156,7 @@ eot:;
|
||||
// was mkconsistent successful?
|
||||
if (lfsr_t_ismkconsistent(t->o.o.flags)
|
||||
&& !lfsr_t_isdirty(t->o.o.flags)) {
|
||||
lfs->flags &= ~LFS_I_HASORPHANS;
|
||||
lfs->flags &= ~LFS_I_UNTIDY;
|
||||
}
|
||||
|
||||
// was compaction successful? note we may need multiple passes if
|
||||
@@ -11685,9 +11685,9 @@ static void lfsr_file_close_(lfs_t *lfs, const lfsr_file_t *file) {
|
||||
if (lfsr_grm_count(lfs) < 2) {
|
||||
lfsr_grm_push(lfs, file->o.o.mdir.mid);
|
||||
|
||||
// fallback to just marking the filesystem as orphaned
|
||||
// fallback to just marking the filesystem as untidy
|
||||
} else {
|
||||
lfs->flags |= LFS_I_HASORPHANS;
|
||||
lfs->flags |= LFS_I_UNTIDY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13697,6 +13697,8 @@ static int lfs_init(lfs_t *lfs, uint32_t flags,
|
||||
|
||||
// setup flags
|
||||
lfs->flags = flags
|
||||
// assume we may contain orphans until proven otherwise
|
||||
| LFS_I_UNTIDY
|
||||
// default to assuming we need compaction somewhere, worst case
|
||||
// this just makes lfsr_fs_gc read more than is strictly needed
|
||||
| LFS_I_UNCOMPACTED;
|
||||
@@ -14350,43 +14352,6 @@ static int lfsr_mountinited(lfs_t *lfs) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check for any orphaned stickynotes, note we only need
|
||||
// this if filesystem will be writable
|
||||
if (!lfsr_m_isrdonly(lfs->flags)) {
|
||||
for (lfs_size_t rid = 0;
|
||||
rid < mdir->rbyd.weight;
|
||||
rid++) {
|
||||
lfsr_tag_t tag;
|
||||
err = lfsr_rbyd_sublookup(lfs, &mdir->rbyd,
|
||||
rid, LFSR_TAG_NAME,
|
||||
&tag, NULL);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||
return err;
|
||||
}
|
||||
// name 0 should be reserved
|
||||
LFS_ASSERT(tag != (LFSR_TAG_NAME + 0));
|
||||
|
||||
// found an orphaned stickynote?
|
||||
if (tag == LFSR_TAG_STICKYNOTE) {
|
||||
LFS_DEBUG("Found orphaned stickynote "
|
||||
"%"PRId32".%"PRId32,
|
||||
lfsr_mid_bid(lfs, mdir->mid) >> lfs->mdir_bits,
|
||||
rid);
|
||||
lfs->flags |= LFS_I_HASORPHANS;
|
||||
|
||||
// found an unknown file type?
|
||||
} else if (lfsr_tag_isunknown(tag)) {
|
||||
LFS_WARN("Found unknown file type "
|
||||
"%"PRId32".%"PRId32" 0x%"PRIx16,
|
||||
lfsr_mid_bid(lfs, mdir->mid) >> lfs->mdir_bits,
|
||||
rid,
|
||||
lfsr_tag_subtype(tag));
|
||||
return LFS_ERR_NOTSUP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// found an mtree inner-node?
|
||||
} else if (tag == LFSR_TAG_BRANCH) {
|
||||
lfsr_rbyd_t *rbyd = (lfsr_rbyd_t*)bptr.data.u.buffer;
|
||||
@@ -14775,7 +14740,7 @@ static int lfsr_fs_fixgrm(lfs_t *lfs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfsr_fs_fixorphans_(lfs_t *lfs, lfsr_mdir_t *mdir) {
|
||||
static int lfsr_fs_mktidy_(lfs_t *lfs, lfsr_mdir_t *mdir) {
|
||||
// save the current mid
|
||||
lfsr_mid_t mid = mdir->mid;
|
||||
|
||||
@@ -14823,7 +14788,7 @@ failed:;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int lfsr_fs_fixorphans(lfs_t *lfs) {
|
||||
static int lfsr_fs_mktidy(lfs_t *lfs) {
|
||||
// LFS_T_MKCONSISTENT really just removes orphans
|
||||
lfsr_traversal_t t = LFSR_TRAVERSAL(
|
||||
LFS_T_MTREEONLY | LFS_T_MKCONSISTENT);
|
||||
@@ -14871,10 +14836,8 @@ int lfsr_fs_mkconsistent(lfs_t *lfs) {
|
||||
// this must happen after fixgrm, since removing orphaned
|
||||
// stickynotes risks outdating the grm
|
||||
//
|
||||
if (lfsr_i_hasorphans(lfs->flags)) {
|
||||
LFS_DEBUG("Fixing orphans...");
|
||||
|
||||
int err = lfsr_fs_fixorphans(lfs);
|
||||
if (lfsr_i_isuntidy(lfs->flags)) {
|
||||
int err = lfsr_fs_mktidy(lfs);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -14951,7 +14914,7 @@ int lfsr_fs_gc(lfs_t *lfs, lfs_soff_t steps, uint32_t flags) {
|
||||
// do we have any pending work?
|
||||
uint32_t pending = flags & (
|
||||
(lfs->flags & (
|
||||
LFS_I_HASORPHANS
|
||||
LFS_I_UNTIDY
|
||||
| LFS_I_UNCOMPACTED))
|
||||
| ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0)
|
||||
| LFS_GC_CKMETA
|
||||
@@ -15016,7 +14979,7 @@ int lfsr_fs_gc(lfs_t *lfs, lfs_soff_t steps, uint32_t flags) {
|
||||
// clear any pending flags we make progress on
|
||||
pending &= (
|
||||
(lfs->flags & (
|
||||
LFS_I_HASORPHANS
|
||||
LFS_I_UNTIDY
|
||||
| LFS_I_UNCOMPACTED))
|
||||
| ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0)
|
||||
// only consider our filesystem checked if we
|
||||
|
||||
@@ -228,8 +228,7 @@ enum lfs_type {
|
||||
0x00008000 // Filesystem may have uncompacted metadata
|
||||
|
||||
// internally used flags, don't use these
|
||||
#define LFS_I_HASORPHANS \
|
||||
0x00001000 // Filesystem may have untracked orphans
|
||||
#define LFS_I_UNTIDY 0x00001000 // Filesystem may have orphaned stickynotes
|
||||
|
||||
|
||||
// Block types
|
||||
|
||||
@@ -4701,7 +4701,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
@@ -4837,7 +4837,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
@@ -4987,7 +4987,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
|
||||
+12
-53
@@ -68,6 +68,7 @@ code = '''
|
||||
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, -1) : 0)
|
||||
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_I_CKPARITY, -1) : 0)
|
||||
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_I_CKCKSUMS, -1) : 0)
|
||||
| ((!MKCONSISTENT) ? LFS_I_INCONSISTENT : 0)
|
||||
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
|
||||
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)));
|
||||
|
||||
@@ -126,7 +127,8 @@ code = '''
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.flags == (
|
||||
LFS_I_CANLOOKAHEAD
|
||||
LFS_I_INCONSISTENT
|
||||
| LFS_I_CANLOOKAHEAD
|
||||
| LFS_I_UNCOMPACTED));
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
|
||||
@@ -138,7 +140,9 @@ code = '''
|
||||
| ((CKDATA) ? LFS_M_CKDATA : 0),
|
||||
CFG) => 0;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.flags == LFS_I_UNCOMPACTED);
|
||||
assert(fsinfo.flags == (
|
||||
LFS_I_INCONSISTENT
|
||||
| LFS_I_UNCOMPACTED));
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
@@ -189,7 +193,8 @@ code = '''
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.flags == (
|
||||
LFS_I_CANLOOKAHEAD
|
||||
LFS_I_INCONSISTENT
|
||||
| LFS_I_CANLOOKAHEAD
|
||||
| LFS_I_UNCOMPACTED));
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
|
||||
@@ -202,7 +207,9 @@ code = '''
|
||||
| ((CKDATA) ? LFS_M_CKDATA : 0),
|
||||
CFG) => 0;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.flags == ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0));
|
||||
assert(fsinfo.flags == (
|
||||
LFS_I_INCONSISTENT
|
||||
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)));
|
||||
|
||||
// mdir should have been compacted
|
||||
lfsr_file_open(&lfs, &file, "jellyfish", LFS_O_RDONLY) => 0;
|
||||
@@ -280,7 +287,7 @@ code = '''
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.flags == (
|
||||
((ORPHANS > 0) ? LFS_I_INCONSISTENT : 0)
|
||||
LFS_I_INCONSISTENT
|
||||
| LFS_I_CANLOOKAHEAD
|
||||
| LFS_I_UNCOMPACTED));
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
@@ -895,51 +902,3 @@ code = '''
|
||||
lfsr_mount(&lfs, LFS_M_RDONLY, CFG) => LFS_ERR_NOTSUP;
|
||||
'''
|
||||
|
||||
# test what happens if we find an unknown file type
|
||||
[cases.test_mount_incompat_unknown_type]
|
||||
in = 'lfs.c'
|
||||
code = '''
|
||||
// create a superblock
|
||||
lfs_t lfs;
|
||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||
|
||||
// create some files
|
||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||
lfsr_file_t file;
|
||||
lfsr_file_open(&lfs, &file, "a",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
lfsr_file_write(&lfs, &file,
|
||||
"hi a!", strlen("hi a!")) => strlen("hi a!");
|
||||
lfsr_file_close(&lfs, &file) => 0;
|
||||
lfsr_file_open(&lfs, &file, "b",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
lfsr_file_write(&lfs, &file,
|
||||
"oh no!", strlen("oh no!")) => strlen("oh no!");
|
||||
lfsr_file_close(&lfs, &file) => 0;
|
||||
lfsr_file_open(&lfs, &file, "c",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
lfsr_file_write(&lfs, &file,
|
||||
"hi c!", strlen("hi c!")) => strlen("hi c!");
|
||||
lfsr_file_close(&lfs, &file) => 0;
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
|
||||
// change a file's type to something unknown
|
||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||
const char *path = "b";
|
||||
lfsr_mdir_t mdir;
|
||||
lfsr_did_t did;
|
||||
lfsr_mtree_pathlookup(&lfs, &path,
|
||||
&mdir, NULL, &did) => 0;
|
||||
lfsr_mdir_commit(&lfs, &mdir, LFSR_RATS(
|
||||
LFSR_RAT_NAME(
|
||||
LFSR_TAG_SUB | (LFSR_TAG_NAME + 0x13), 0,
|
||||
did, path, lfsr_path_namelen(path)))) => 0;
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
|
||||
// mount should now fail
|
||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP;
|
||||
|
||||
// but we _can_ mount readonly
|
||||
lfsr_mount(&lfs, LFS_M_RDONLY, CFG) => 0;
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
+12
-10
@@ -1680,7 +1680,8 @@ code = '''
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.flags == (
|
||||
LFS_I_CANLOOKAHEAD
|
||||
LFS_I_INCONSISTENT
|
||||
| LFS_I_CANLOOKAHEAD
|
||||
| LFS_I_UNCOMPACTED));
|
||||
|
||||
// try traversing
|
||||
@@ -1704,7 +1705,8 @@ code = '''
|
||||
// check flags after
|
||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.flags == (
|
||||
((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
|
||||
((!MKCONSISTENT) ? LFS_I_INCONSISTENT : 0)
|
||||
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
|
||||
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)));
|
||||
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
@@ -6327,7 +6329,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
// which means there shouldn't be that many files left
|
||||
assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits));
|
||||
@@ -6466,7 +6468,7 @@ code = '''
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
// if we introduce actual orphans, me _must not_ clear the orphan flag
|
||||
if (ORPHANS >= 3) {
|
||||
assert(lfs.flags & LFS_I_HASORPHANS);
|
||||
assert(lfs.flags & LFS_I_UNTIDY);
|
||||
}
|
||||
|
||||
// if we introduced actual orphans, we _must_ be marked as inconsistent
|
||||
@@ -6618,7 +6620,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
// which means there shouldn't be that many files left
|
||||
assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits));
|
||||
@@ -6771,7 +6773,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
// which means there shouldn't be that many files left
|
||||
assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits));
|
||||
@@ -6935,7 +6937,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
// which means there shouldn't be that many files left
|
||||
assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits));
|
||||
@@ -7097,7 +7099,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
// which means there shouldn't be that many files left
|
||||
assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits));
|
||||
@@ -7257,7 +7259,7 @@ code = '''
|
||||
// we should have cleaned up all grms/orphans
|
||||
assert(lfs.grm.mids[0] == -1);
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
assert(!(lfs.flags & LFS_I_HASORPHANS));
|
||||
assert(!(lfs.flags & LFS_I_UNTIDY));
|
||||
|
||||
// which means there shouldn't be that many files left
|
||||
assert((lfs.mtree.u.weight & 0x7fffffff) <= (2 << lfs.mdir_bits));
|
||||
@@ -7445,7 +7447,7 @@ code = '''
|
||||
assert(lfs.grm.mids[1] == -1);
|
||||
// if we introduce actual orphans, me _must not_ clear the orphan flag
|
||||
if (ORPHANS >= 3) {
|
||||
assert(lfs.flags & LFS_I_HASORPHANS);
|
||||
assert(lfs.flags & LFS_I_UNTIDY);
|
||||
}
|
||||
|
||||
// mdirs should have been compacted
|
||||
|
||||
Reference in New Issue
Block a user