Reworked crystallization to better use erased-state on rewrites

This adopts lazy crystallization in _addition_ to lazy grafting, managed
by separate LFS_o_UNCRYST and LFS_o_UNGRAFT flags:

  LFS_o_UNCRYST  0x00400000  File's leaf not fully crystallized
  LFS_o_UNGRAFT  0x00800000  File's leaf does not match bshrub/btree

This lets us graft not-fully-crystallized blocks into the tree without
needing to fully crystallize, avoiding repeated recrystallizations when
linearly rewriting a file.

Long story short, this gives file rewrites roughly the same performance
as linear file writes.

---

In theory you could also have fully crystallized but ungrafted blocks
(UNGRAFT + ~UNCRYST), but this doesn't happen with the current logic.
lfsr_file_crystallize eagerly grafts blocks once they're crystallized.

Internally, lfsr_file_crystallize replaces lfsr_file_graft for the
"don't care, gimme file->leaf" operation. This is analogous to
lfsr_file_flush for file->cache.

Note we do _not_ use LFS_o_UNCRYST to track erased-state! If we did,
erased-state wouldn't survive lfsr_file_flush!

---

Of course, this adds even more code. Fortunately not _that_ much
considering how many lines of code changed:

           code          stack          ctx
  before: 37012           2304          636
  after   37084 (+0.2%)   2304 (+0.0%)  636 (+0.0%)

There is another downside however, and that's that our benchmarked disk
usage is slightly worse during random writes.

I haven't fully investigated this, but I think it's due to more
temporary fragments/blocks in the B-tree before flushing. This can cause
B-tree inner nodes to split earlier than when eagerly recrystallizing.

This also leads to higher disk usage pre-flush since we keep both the
old and new blocks around while uncrystallized, but since most rewrites
are probably going to be CoW on top of committed files, I don't think
this will be a big deal.

Note the disk usage ends up the same after lfsr_file_flush.
This commit is contained in:
Christopher Haster
2025-05-23 01:10:23 -05:00
parent f4c1753075
commit 9c3a866508
3 changed files with 104 additions and 83 deletions
+100 -81
View File
@@ -6686,7 +6686,7 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_bshrub_t *bshrub,
if (lfsr_bshrub_isbtree(bshrub)) { if (lfsr_bshrub_isbtree(bshrub)) {
for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) {
if (lfsr_o_isbshrub(o->flags) if (lfsr_o_isbshrub(o->flags)
&& (lfsr_bshrub_t*)o != bshrub && o != &bshrub->o
&& lfsr_bshrub_cmp((lfsr_bshrub_t*)o, bshrub) == 0) { && lfsr_bshrub_cmp((lfsr_bshrub_t*)o, bshrub) == 0) {
// mark as unerased // mark as unerased
((lfsr_bshrub_t*)o)->shrub.eoff = -1; ((lfsr_bshrub_t*)o)->shrub.eoff = -1;
@@ -7003,6 +7003,10 @@ static inline bool lfsr_o_isbshrub(uint32_t flags) {
|| lfsr_o_type(flags) == LFS_type_TRAVERSAL; || lfsr_o_type(flags) == LFS_type_TRAVERSAL;
} }
static inline bool lfsr_o_isuncryst(uint32_t flags) {
return flags & LFS_o_UNCRYST;
}
static inline bool lfsr_o_isungraft(uint32_t flags) { static inline bool lfsr_o_isungraft(uint32_t flags) {
return flags & LFS_o_UNGRAFT; return flags & LFS_o_UNGRAFT;
} }
@@ -11251,11 +11255,13 @@ int lfsr_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
// file helpers // file helpers
static inline void lfsr_file_discardcache(lfsr_file_t *file) { static inline void lfsr_file_discardcache(lfsr_file_t *file) {
file->b.o.flags &= ~LFS_o_UNFLUSH;
file->cache.pos = 0; file->cache.pos = 0;
file->cache.size = 0; file->cache.size = 0;
} }
static inline void lfsr_file_discardleaf(lfsr_file_t *file) { static inline void lfsr_file_discardleaf(lfsr_file_t *file) {
file->b.o.flags &= ~LFS_o_UNCRYST & ~LFS_o_UNGRAFT;
file->leaf.pos = 0; file->leaf.pos = 0;
file->leaf.weight = 0; file->leaf.weight = 0;
lfsr_bptr_discard(&file->leaf.bptr); lfsr_bptr_discard(&file->leaf.bptr);
@@ -11295,8 +11301,6 @@ static int lfsr_file_fetch(lfs_t *lfs, lfsr_file_t *file, bool trunc) {
lfsr_file_discardcache(file); lfsr_file_discardcache(file);
// discard the current leaf // discard the current leaf
lfsr_file_discardleaf(file); lfsr_file_discardleaf(file);
// mark as flushed
file->b.o.flags &= ~LFS_o_UNFLUSH & ~LFS_o_UNGRAFT;
// don't bother reading disk if we're not created or truncating // don't bother reading disk if we're not created or truncating
if (!lfsr_o_isuncreat(file->b.o.flags) && !trunc) { if (!lfsr_o_isuncreat(file->b.o.flags) && !trunc) {
@@ -11726,7 +11730,8 @@ static lfs_ssize_t lfsr_file_read_(lfs_t *lfs, lfsr_file_t *file,
if (!(pos >= file->leaf.pos if (!(pos >= file->leaf.pos
&& pos < file->leaf.pos + file->leaf.weight)) { && pos < file->leaf.pos + file->leaf.weight)) {
// leaf in use? we need to flush it // leaf in use? we need to flush it
if (lfsr_o_isungraft(file->b.o.flags)) { if (lfsr_o_isungraft(file->b.o.flags)
|| lfsr_o_isuncryst(file->b.o.flags)) {
int err = lfsr_file_flush(lfs, file); int err = lfsr_file_flush(lfs, file);
if (err) { if (err) {
return err; return err;
@@ -11897,7 +11902,7 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
} }
// graft bptr/fragments into our bshrub/btree // graft bptr/fragments into our bshrub/btree
static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file, static int lfsr_file_graft(lfs_t *lfs, lfsr_file_t *file,
lfs_off_t pos, lfs_off_t weight, lfs_soff_t delta, lfs_off_t pos, lfs_off_t weight, lfs_soff_t delta,
// data_count=-1 => single bptr // data_count=-1 => single bptr
// data_count>=0 => list of concatenated fragments // data_count>=0 => list of concatenated fragments
@@ -12165,35 +12170,16 @@ static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file,
return 0; return 0;
} }
static int lfsr_file_graft(lfs_t *lfs, lfsr_file_t *file) { static int lfsr_file_crystallize_(lfs_t *lfs, lfsr_file_t *file,
// do nothing if already grafted
if (!lfsr_o_isungraft(file->b.o.flags)) {
return 0;
}
// ungrafted files must be unsynced
LFS_ASSERT(lfsr_o_isunsync(file->b.o.flags));
// only blocks can be ungrafted
LFS_ASSERT(lfsr_bptr_isbptr(&file->leaf.bptr));
// graft our crystal
int err = lfsr_file_graft_(lfs, file,
file->leaf.pos, file->leaf.weight, 0,
&file->leaf.bptr.data, -1);
if (err) {
return err;
}
// mark as grafted
file->b.o.flags &= ~LFS_o_UNGRAFT;
return 0;
}
static int lfsr_file_crystallize(lfs_t *lfs, lfsr_file_t *file,
lfs_off_t block_pos, lfs_soff_t crystal_size, lfs_off_t block_pos, lfs_soff_t crystal_size,
lfs_off_t pos, const uint8_t *buffer, lfs_size_t size) { lfs_off_t pos, const uint8_t *buffer, lfs_size_t size) {
// limit to block_size and theoretical file size // align to prog_size, limit to block_size and theoretical file size
lfs_off_t crystal_limit = lfs_min( lfs_off_t crystal_limit = lfs_min(
block_pos + lfs->cfg->block_size, block_pos + lfs_min(
lfs_aligndown(
(lfs_off_t)crystal_size,
lfs->cfg->prog_size),
lfs->cfg->block_size),
lfs_max( lfs_max(
pos + size, pos + size,
lfsr_file_weight(file))); lfsr_file_weight(file)));
@@ -12217,9 +12203,9 @@ static int lfsr_file_crystallize(lfs_t *lfs, lfsr_file_t *file,
// before we write, claim the erased state! // before we write, claim the erased state!
for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) {
if (lfsr_o_type(o->flags) == LFS_TYPE_REG if (lfsr_o_type(o->flags) == LFS_TYPE_REG
&& o != &file->b.o
&& lfsr_bptr_block(&((lfsr_file_t*)o)->leaf.bptr) && lfsr_bptr_block(&((lfsr_file_t*)o)->leaf.bptr)
== lfsr_bptr_block(&file->leaf.bptr) == lfsr_bptr_block(&file->leaf.bptr)) {
&& (lfsr_file_t*)o != file) {
lfsr_bptr_claim(&((lfsr_file_t*)o)->leaf.bptr); lfsr_bptr_claim(&((lfsr_file_t*)o)->leaf.bptr);
} }
} }
@@ -12389,8 +12375,8 @@ static int lfsr_file_crystallize(lfs_t *lfs, lfsr_file_t *file,
(pos_ - block_pos) | LFSR_BPTR_ISERASED, (pos_ - block_pos) | LFSR_BPTR_ISERASED,
cksum_); cksum_);
// mark as ungrafted // mark as uncrystallized and ungrafted
file->b.o.flags |= LFS_o_UNGRAFT; file->b.o.flags |= LFS_o_UNCRYST | LFS_o_UNGRAFT;
return 0; return 0;
relocate:; relocate:;
@@ -12411,6 +12397,44 @@ static int lfsr_file_crystallize(lfs_t *lfs, lfsr_file_t *file,
} }
} }
static int lfsr_file_crystallize(lfs_t *lfs, lfsr_file_t *file) {
// finish crystallizing
if (lfsr_o_isuncryst(file->b.o.flags)) {
// uncrystallized files must be unsynced
LFS_ASSERT(lfsr_o_isunsync(file->b.o.flags));
// only blocks can be uncrystallized
LFS_ASSERT(lfsr_bptr_isbptr(&file->leaf.bptr));
LFS_ASSERT(lfsr_bptr_iserased(&file->leaf.bptr));
// finish crystallizing the block
int err = lfsr_file_crystallize_(lfs, file,
file->leaf.pos - lfsr_bptr_off(&file->leaf.bptr),
-1,
file->cache.pos, file->cache.buffer, file->cache.size);
if (err) {
return err;
}
// mark as crystallized
file->b.o.flags &= ~LFS_o_UNCRYST;
}
// and graft into tree
if (lfsr_o_isungraft(file->b.o.flags)) {
int err = lfsr_file_graft(lfs, file,
file->leaf.pos, file->leaf.weight, 0,
&file->leaf.bptr.data, -1);
if (err) {
return err;
}
// mark as grafted
file->b.o.flags &= ~LFS_o_UNGRAFT;
}
return 0;
}
static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
lfs_off_t pos, const uint8_t *buffer, lfs_size_t size) { lfs_off_t pos, const uint8_t *buffer, lfs_size_t size) {
// we can skip some btree lookups if we know we are aligned from a // we can skip some btree lookups if we know we are aligned from a
@@ -12440,7 +12464,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
&& pos - block_end < lfs->cfg->crystal_thresh && pos - block_end < lfs->cfg->crystal_thresh
// need to bail if we can't meet prog alignment // need to bail if we can't meet prog alignment
&& (pos + size) - block_end >= lfs->cfg->prog_size) { && (pos + size) - block_end >= lfs->cfg->prog_size) {
int err = lfsr_file_crystallize(lfs, file, int err = lfsr_file_crystallize_(lfs, file,
file->leaf.pos - lfsr_bptr_off(&file->leaf.bptr), file->leaf.pos - lfsr_bptr_off(&file->leaf.bptr),
(pos + size) (pos + size)
- (file->leaf.pos - lfsr_bptr_off(&file->leaf.bptr)), - (file->leaf.pos - lfsr_bptr_off(&file->leaf.bptr)),
@@ -12561,27 +12585,15 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
// if we're mid-crystallization, finish crystallizing the block // if we're mid-crystallization, finish crystallizing the block
// and graft it into our bshrub/btree // and graft it into our bshrub/btree
if (lfsr_bptr_isbptr(&file->leaf.bptr) int err = lfsr_file_crystallize(lfs, file);
&& lfsr_bptr_iserased(&file->leaf.bptr)) { if (err) {
int err = lfsr_file_crystallize(lfs, file, return err;
file->leaf.pos - lfsr_bptr_off(&file->leaf.bptr),
-1,
pos, buffer, size);
if (err) {
return err;
}
// and graft the crystal into our tree
err = lfsr_file_graft(lfs, file);
if (err) {
return err;
}
// mark as unerased so lfsr_file_crystallize doesn't try to
// continue crystallizing this block
lfsr_bptr_claim(&file->leaf.bptr);
} }
// mark as unerased so lfsr_file_crystallize doesn't try to
// resume crystallizing this block
lfsr_bptr_claim(&file->leaf.bptr);
// before we can crystallize we need to figure out the best // before we can crystallize we need to figure out the best
// block alignment, we use the entry immediately to the left of // block alignment, we use the entry immediately to the left of
// our crystal for this // our crystal for this
@@ -12619,8 +12631,8 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
// start crystallizing! // start crystallizing!
// //
// lfsr_file_crystallize handles block allocation/relocation // lfsr_file_crystallize_ handles block allocation/relocation
int err = lfsr_file_crystallize(lfs, file, err = lfsr_file_crystallize_(lfs, file,
crystal_start, crystal_end - crystal_start, crystal_start, crystal_end - crystal_start,
pos, buffer, size); pos, buffer, size);
if (err) { if (err) {
@@ -12647,9 +12659,17 @@ fragment:;
// //
// but note we're still tracking its erased state for future // but note we're still tracking its erased state for future
// writes! // writes!
int err = lfsr_file_graft(lfs, file); if (lfsr_o_isungraft(file->b.o.flags)) {
if (err) { // graft our crystal
return err; int err = lfsr_file_graft(lfs, file,
file->leaf.pos, file->leaf.weight, 0,
&file->leaf.bptr.data, -1);
if (err) {
return err;
}
// mark as grafted
file->b.o.flags &= ~LFS_o_UNGRAFT;
} }
// do we need to discard our leaf? we need to discard fragments // do we need to discard our leaf? we need to discard fragments
@@ -12687,7 +12707,7 @@ fragment:;
lfsr_bid_t bid; lfsr_bid_t bid;
lfsr_bid_t weight; lfsr_bid_t weight;
lfsr_bptr_t bptr; lfsr_bptr_t bptr;
err = lfsr_file_lookup(lfs, file, int err = lfsr_file_lookup(lfs, file,
fragment_start-1, fragment_start-1,
&bid, &weight, &bptr); &bid, &weight, &bptr);
if (err) { if (err) {
@@ -12734,7 +12754,7 @@ fragment:;
lfsr_bid_t bid; lfsr_bid_t bid;
lfsr_bid_t weight; lfsr_bid_t weight;
lfsr_bptr_t bptr; lfsr_bptr_t bptr;
err = lfsr_file_lookup(lfs, file, int err = lfsr_file_lookup(lfs, file,
fragment_end, fragment_end,
&bid, &weight, &bptr); &bid, &weight, &bptr);
if (err) { if (err) {
@@ -12774,7 +12794,7 @@ fragment:;
// once we've figured out what fragment to write, graft it into // once we've figured out what fragment to write, graft it into
// our tree // our tree
err = lfsr_file_graft_(lfs, file, int err = lfsr_file_graft(lfs, file,
fragment_start, fragment_end - fragment_start, 0, fragment_start, fragment_end - fragment_start, 0,
datas, data_count); datas, data_count);
if (err) { if (err) {
@@ -12794,6 +12814,7 @@ fragment:;
return 0; return 0;
} }
// high-level file writing // high-level file writing
lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
@@ -12950,8 +12971,10 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) {
// can't write to readonly files // can't write to readonly files
LFS_ASSERT(!lfsr_o_isrdonly(file->b.o.flags)); LFS_ASSERT(!lfsr_o_isrdonly(file->b.o.flags));
// do nothing if our file is already flushed and grafted // do nothing if our file is already flushed, crystallized,
// and grafted
if (!lfsr_o_isunflush(file->b.o.flags) if (!lfsr_o_isunflush(file->b.o.flags)
&& !lfsr_o_isuncryst(file->b.o.flags)
&& !lfsr_o_isungraft(file->b.o.flags)) { && !lfsr_o_isungraft(file->b.o.flags)) {
return 0; return 0;
} }
@@ -12976,17 +12999,10 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) {
file->b.o.flags &= ~LFS_o_UNFLUSH; file->b.o.flags &= ~LFS_o_UNFLUSH;
} }
// graft any ungrafted leaves // and crystallize/graft our leaf
if (lfsr_o_isungraft(file->b.o.flags)) { err = lfsr_file_crystallize(lfs, file);
err = lfsr_file_graft_(lfs, file, if (err) {
file->leaf.pos, file->leaf.weight, 0, goto failed;
&file->leaf.bptr.data, -1);
if (err) {
goto failed;
}
// mark as grafted
file->b.o.flags &= ~LFS_o_UNGRAFT;
} }
return 0; return 0;
@@ -13174,9 +13190,8 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
&& file->cache.size < lfs->cfg->crystal_thresh) { && file->cache.size < lfs->cfg->crystal_thresh) {
if (lfsr_o_isungraft(file->b.o.flags)) { if (lfsr_o_isungraft(file->b.o.flags)) {
file->b.o.flags |= LFS_o_UNFLUSH; file->b.o.flags |= LFS_o_UNFLUSH;
file->b.o.flags &= ~LFS_o_UNGRAFT;
lfsr_file_discardleaf(file);
} }
lfsr_file_discardleaf(file);
} else { } else {
err = lfsr_file_flush(lfs, file); err = lfsr_file_flush(lfs, file);
if (err) { if (err) {
@@ -13213,6 +13228,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
// update flags // update flags
file_->b.o.flags &= ~LFS_o_UNSYNC file_->b.o.flags &= ~LFS_o_UNSYNC
& ~LFS_o_UNFLUSH & ~LFS_o_UNFLUSH
& ~LFS_o_UNCRYST
& ~LFS_o_UNGRAFT; & ~LFS_o_UNGRAFT;
// update shrubs // update shrubs
file_->b.shrub = file->b.shrub; file_->b.shrub = file->b.shrub;
@@ -13271,6 +13287,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
// mark as synced // mark as synced
file->b.o.flags &= ~LFS_o_UNSYNC file->b.o.flags &= ~LFS_o_UNSYNC
& ~LFS_o_UNFLUSH & ~LFS_o_UNFLUSH
& ~LFS_o_UNCRYST
& ~LFS_o_UNGRAFT & ~LFS_o_UNGRAFT
& ~LFS_o_UNCREAT & ~LFS_o_UNCREAT
& ~LFS_O_DESYNC; & ~LFS_O_DESYNC;
@@ -13405,7 +13422,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
< lfs_min( < lfs_min(
lfs->cfg->fragment_thresh, lfs->cfg->fragment_thresh,
lfs->cfg->crystal_thresh)) { lfs->cfg->crystal_thresh)) {
err = lfsr_file_graft(lfs, file); err = lfsr_file_crystallize(lfs, file);
if (err) { if (err) {
goto failed; goto failed;
} }
@@ -13414,7 +13431,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
} }
// truncate our btree // truncate our btree
err = lfsr_file_graft_(lfs, file, err = lfsr_file_graft(lfs, file,
lfs_min(size, size_), size - lfs_min(size, size_), lfs_min(size, size_), size - lfs_min(size, size_),
+size_ - size, +size_ - size,
NULL, 0); NULL, 0);
@@ -13425,6 +13442,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
// truncate our leaf // truncate our leaf
if (size_ < file->leaf.pos + lfsr_bptr_size(&file->leaf.bptr)) { if (size_ < file->leaf.pos + lfsr_bptr_size(&file->leaf.bptr)) {
lfsr_bptr_claim(&file->leaf.bptr); lfsr_bptr_claim(&file->leaf.bptr);
file->b.o.flags &= ~LFS_o_UNCRYST;
} }
file->leaf.bptr.data = LFSR_DATA_TRUNCATE( file->leaf.bptr.data = LFSR_DATA_TRUNCATE(
file->leaf.bptr.data, file->leaf.bptr.data,
@@ -13487,7 +13505,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
< lfs_min( < lfs_min(
lfs->cfg->fragment_thresh, lfs->cfg->fragment_thresh,
lfs->cfg->crystal_thresh)) { lfs->cfg->crystal_thresh)) {
err = lfsr_file_graft(lfs, file); err = lfsr_file_crystallize(lfs, file);
if (err) { if (err) {
goto failed; goto failed;
} }
@@ -13496,7 +13514,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
} }
// fruncate our btree // fruncate our btree
err = lfsr_file_graft_(lfs, file, err = lfsr_file_graft(lfs, file,
0, lfs_smax(size - size_, 0), 0, lfs_smax(size - size_, 0),
+size_ - size, +size_ - size,
NULL, 0); NULL, 0);
@@ -13509,6 +13527,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
> (lfs_soff_t)(file->leaf.pos > (lfs_soff_t)(file->leaf.pos
+ lfsr_bptr_size(&file->leaf.bptr))) { + lfsr_bptr_size(&file->leaf.bptr))) {
lfsr_bptr_claim(&file->leaf.bptr); lfsr_bptr_claim(&file->leaf.bptr);
file->b.o.flags &= ~LFS_o_UNCRYST;
} }
file->leaf.bptr.data = LFSR_DATA_FRUNCATE( file->leaf.bptr.data = LFSR_DATA_FRUNCATE(
file->leaf.bptr.data, file->leaf.bptr.data,
+2 -1
View File
@@ -144,7 +144,8 @@ enum lfs_type {
// internally used flags, don't use these // internally used flags, don't use these
#define LFS_o_TYPE 0xf0000000 // The file's type #define LFS_o_TYPE 0xf0000000 // The file's type
#define LFS_o_UNGRAFT 0x00800000 // File's leaf does not match btree #define LFS_o_UNCRYST 0x00400000 // File's leaf not fully crystallized
#define LFS_o_UNGRAFT 0x00800000 // File's leaf does not match bshrub/btree
#define LFS_o_UNFLUSH 0x01000000 // File's data does not match disk #define LFS_o_UNFLUSH 0x01000000 // File's data does not match disk
#define LFS_o_UNSYNC 0x02000000 // File's metadata does not match disk #define LFS_o_UNSYNC 0x02000000 // File's metadata does not match disk
#define LFS_o_UNCREAT 0x04000000 // File does not exist yet #define LFS_o_UNCREAT 0x04000000 // File does not exist yet
+2 -1
View File
@@ -44,7 +44,8 @@ FLAGS = [
('^', 'ORPHAN', 0x50000000, "Type = orphan" ), ('^', 'ORPHAN', 0x50000000, "Type = orphan" ),
('^', 'TRAVERSAL', 0x60000000, "Type = traversal" ), ('^', 'TRAVERSAL', 0x60000000, "Type = traversal" ),
('^', 'UNKNOWN', 0x70000000, "Type = unknown" ), ('^', 'UNKNOWN', 0x70000000, "Type = unknown" ),
('o', 'UNGRAFT', 0x00800000, "File's leaf does not match btree" ), ('o', 'UNCRYST', 0x00400000, "File's leaf not fully crystallized" ),
('o', 'UNGRAFT', 0x00800000, "File's leaf does not match bshrub/btree" ),
('o', 'UNFLUSH', 0x01000000, "File's data does not match disk" ), ('o', 'UNFLUSH', 0x01000000, "File's data does not match disk" ),
('o', 'UNSYNC', 0x02000000, "File's metadata does not match disk" ), ('o', 'UNSYNC', 0x02000000, "File's metadata does not match disk" ),
('o', 'UNCREAT', 0x04000000, "File does not exist yet" ), ('o', 'UNCREAT', 0x04000000, "File does not exist yet" ),