Adopted LFSR_TAG_ORPHAN, simplified internal stickynote handling

This adds LFSR_TAG_ORPHAN, which simplifies quite a bit of the internal
stickynote handling.

Now that we don't have to worry about conflicts with future unknown
types, we can add whatever types we want internally. One useful one
is LFSR_TAG_ORPHAN, which lets us determine stickynote's orphan status
early (in lfsr_mdir_lookupnext and lfsr_mdir_namelookup):

- non-orphan stickynotes -> LFSR_TAG_STICKYNOTE
- orphan stickynotes     -> LFSR_TAG_ORPHAN

This simplifies all the places where we need to check if a stickynote
really exists, which is most of the high-level functions.

One downside is that this makes stickynote _manipulation_ a bit more
delicate. lfsr_mdir_lookup(LFSR_TAG_ORPHAN) no longer works as expected,
for example.

Fortunately we can sidestep this issue by dropping down to
lfsr_rbyd_lookup when we need to interact with stickynotes directly,
skipping the is-orphan checks.

---

Saves a nice bit of code:

           code          stack          ctx
  before: 35984           2440          640
  after:  35832 (-0.4%)   2440 (+0.0%)  640 (+0.0%)

It got a little muddy since this now include the unknown-type changes,
but here's the code diff from before we exposed LFSR_TYPE_STICKYNOTE to
users:

           code          stack          ctx
  before: 35740           2440          640
  after:  35832 (+0.3%)   2440 (+0.0%)  640 (+0.0%)
This commit is contained in:
Christopher Haster
2025-04-24 15:03:00 -05:00
parent 9eac456663
commit f3cd9802b8
3 changed files with 52 additions and 69 deletions
+41 -61
View File
@@ -1117,8 +1117,9 @@ enum lfsr_tag {
LFSR_TAG_BOOKMARK = 0x0204, LFSR_TAG_BOOKMARK = 0x0204,
// in-device only name tags, these should never get written to disk // in-device only name tags, these should never get written to disk
LFSR_TAG_TRAVERSAL = 0x0205, LFSR_TAG_ORPHAN = 0x0205,
LFSR_TAG_UNKNOWN = 0x0206, LFSR_TAG_TRAVERSAL = 0x0206,
LFSR_TAG_UNKNOWN = 0x0207,
// struct tags // struct tags
LFSR_TAG_STRUCT = 0x0300, LFSR_TAG_STRUCT = 0x0300,
@@ -7528,10 +7529,17 @@ static lfsr_tag_t lfsr_mdir_nametag(const lfs_t *lfs, const lfsr_mdir_t *mdir,
// stickynotes // stickynotes
// //
// fortunately pending grms/orphaned stickynotes have roughly the // fortunately pending grms/orphaned stickynotes have roughly the
// same semantics, and it's easier to manage the implied mid gap in // same semantics, and this makes it easier to manage the implied
// higher-levels // mid gap in higher-levels
if (lfsr_grm_ismidrm(lfs, mid)) { if (lfsr_grm_ismidrm(lfs, mid)) {
return LFSR_TAG_STICKYNOTE; return LFSR_TAG_ORPHAN;
// if we find a stickynote, check to see if there are any open
// in-sync file handles to decide if it really exists
} else if (tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC))) {
return LFSR_TAG_ORPHAN;
// map unknown types -> LFSR_TAG_UNKNOWN, this simplifies higher // map unknown types -> LFSR_TAG_UNKNOWN, this simplifies higher
// levels and prevents collisions with internal types // levels and prevents collisions with internal types
@@ -9324,9 +9332,7 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char **path,
// only continue if we hit a directory // only continue if we hit a directory
if (tag != LFSR_TAG_DIR) { if (tag != LFSR_TAG_DIR) {
return (tag == LFSR_TAG_STICKYNOTE return (tag == LFSR_TAG_ORPHAN)
&& !lfsr_omdir_ismidopen(lfs, mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC)))
? LFS_ERR_NOENT ? LFS_ERR_NOENT
: LFS_ERR_NOTDIR; : LFS_ERR_NOTDIR;
} }
@@ -10189,14 +10195,9 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
if (err && !(err == LFS_ERR_NOENT && lfsr_path_islast(path))) { if (err && !(err == LFS_ERR_NOENT && lfsr_path_islast(path))) {
return err; return err;
} }
// TODO LFSR_TAG_ORPHAN maybe? // already exists? pretend orphans don't exist
// already exists? if we find a stickynote, check to see if there
// are any open in-sync file handles to decide if it really exists
bool exists = (err != LFS_ERR_NOENT); bool exists = (err != LFS_ERR_NOENT);
if (exists if (exists && tag != LFSR_TAG_ORPHAN) {
&& (tag != LFSR_TAG_STICKYNOTE
|| lfsr_omdir_ismidopen(lfs, mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC)))) {
return LFS_ERR_EXIST; return LFS_ERR_EXIST;
} }
@@ -10421,11 +10422,8 @@ int lfsr_remove(lfs_t *lfs, const char *path) {
if (err) { if (err) {
return err; return err;
} }
// if we find a stickynote, check to see if there are any open // pretend orphans don't exist
// in-sync file handles to decide if it really exists if (tag == LFSR_TAG_ORPHAN) {
if (tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC))) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
@@ -10543,11 +10541,8 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) {
if (err) { if (err) {
return err; return err;
} }
// if we find a stickynote, check to see if there are any open // pretend orphans don't exist
// in-sync file handles to decide if it really exists if (old_tag == LFSR_TAG_ORPHAN) {
if (old_tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, old_mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC))) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
@@ -10594,12 +10589,8 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) {
} }
if (old_tag == LFSR_TAG_DIR if (old_tag == LFSR_TAG_DIR
&& new_tag != LFSR_TAG_DIR && new_tag != LFSR_TAG_DIR
// if we find a stickynote, check to see if there are // pretend orphans don't exist
// any open in-sync file handles to decide if it really && new_tag != LFSR_TAG_ORPHAN) {
// exists
&& (new_tag != LFSR_TAG_STICKYNOTE
|| lfsr_omdir_ismidopen(lfs, new_mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC)))) {
return LFS_ERR_NOTDIR; return LFS_ERR_NOTDIR;
} }
@@ -10774,11 +10765,8 @@ int lfsr_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
if (err) { if (err) {
return err; return err;
} }
// if we find a stickynote, check to see if there are any open // pretend orphans don't exist
// in-sync file handles to decide if it really exists if (tag == LFSR_TAG_ORPHAN) {
if (tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC))) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
@@ -10814,11 +10802,8 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) {
if (err) { if (err) {
return err; return err;
} }
// if we find a stickynote, check to see if there are any open // pretend orphans don't exist
// in-sync file handles to decide if it really exists if (tag == LFSR_TAG_ORPHAN) {
if (tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC))) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
@@ -10921,11 +10906,8 @@ int lfsr_dir_read(lfs_t *lfs, lfsr_dir_t *dir, struct lfs_info *info) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
// if we find a stickynote, check to see if there are any open // skip orphans, we pretend these don't exist
// in-sync file handles to decide if it really exists if (tag == LFSR_TAG_ORPHAN) {
if (tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, dir->o.mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC))) {
dir->o.mdir.mid += 1; dir->o.mdir.mid += 1;
dir->pos += 1; dir->pos += 1;
continue; continue;
@@ -11037,11 +11019,8 @@ static int lfsr_lookupattr(lfs_t *lfs, const char *path, uint8_t type,
if (err) { if (err) {
return err; return err;
} }
// if we find a stickynote, check to see if there are any open // pretend orphans don't exist
// in-sync file handles to decide if it really exists if (tag == LFSR_TAG_ORPHAN) {
if (tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, mdir_->mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC))) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
@@ -11376,13 +11355,8 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
} }
bool exists = err != LFS_ERR_NOENT; bool exists = err != LFS_ERR_NOENT;
// creating a new entry? if we find a stickynote, check to see if // creating a new entry?
// there are any open in-sync file handles to decide if it really if (!exists || tag == LFSR_TAG_ORPHAN) {
// exists
if (!exists
|| (tag == LFSR_TAG_STICKYNOTE
&& !lfsr_omdir_ismidopen(lfs, file->b.o.mdir.mid,
~(LFS_o_ZOMBIE | LFS_O_DESYNC)))) {
if (!lfsr_o_iscreat(flags)) { if (!lfsr_o_iscreat(flags)) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
@@ -11437,7 +11411,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
// if stickynote, mark as uncreated and unsynced, we need to convert // if stickynote, mark as uncreated and unsynced, we need to convert
// to reg file on first sync // to reg file on first sync
if (!exists || tag == LFSR_TAG_STICKYNOTE) { if (!exists || tag == LFSR_TAG_STICKYNOTE || tag == LFSR_TAG_ORPHAN) {
file->b.o.flags |= LFS_o_UNCREAT | LFS_o_UNSYNC; file->b.o.flags |= LFS_o_UNCREAT | LFS_o_UNSYNC;
} }
@@ -12762,7 +12736,8 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
// uncreated files must be unsynced // uncreated files must be unsynced
LFS_ASSERT(lfsr_o_isunsync(file->b.o.flags)); LFS_ASSERT(lfsr_o_isunsync(file->b.o.flags));
err = lfsr_mdir_lookup(lfs, &file->b.o.mdir, LFSR_TAG_STICKYNOTE, err = lfsr_rbyd_lookup(lfs, &file->b.o.mdir.rbyd,
lfsr_mrid(lfs, file->b.o.mdir.mid), LFSR_TAG_STICKYNOTE,
NULL, &name_data); NULL, &name_data);
if (err) { if (err) {
// orphan flag but no stickynote tag? // orphan flag but no stickynote tag?
@@ -14547,13 +14522,18 @@ static int lfsr_mdir_mkconsistent(lfs_t *lfs, lfsr_mdir_t *mdir) {
int err; int err;
while (lfsr_mrid(lfs, mdir->mid) < (lfsr_srid_t)mdir->rbyd.weight) { while (lfsr_mrid(lfs, mdir->mid) < (lfsr_srid_t)mdir->rbyd.weight) {
// is this mid open? well we're not an orphan then, skip // is this mid open? well we're not an orphan then, skip
//
// note we can't rely on lfsr_mdir_lookup's internal orphan
// checks as we also need to treat desynced/zombied files as
// non-orphans
if (lfsr_omdir_ismidopen(lfs, mdir->mid, -1)) { if (lfsr_omdir_ismidopen(lfs, mdir->mid, -1)) {
mdir->mid += 1; mdir->mid += 1;
continue; continue;
} }
// is this mid marked as a stickynote? // is this mid marked as a stickynote?
err = lfsr_mdir_lookup(lfs, mdir, LFSR_TAG_STICKYNOTE, err = lfsr_rbyd_lookup(lfs, &mdir->rbyd,
lfsr_mrid(lfs, mdir->mid), LFSR_TAG_STICKYNOTE,
NULL, NULL); NULL, NULL);
if (err) { if (err) {
if (err == LFS_ERR_NOENT) { if (err == LFS_ERR_NOENT) {
+4 -3
View File
@@ -119,11 +119,12 @@ enum lfs_type {
LFS_TYPE_REG = 1, // A regular file LFS_TYPE_REG = 1, // A regular file
LFS_TYPE_DIR = 2, // A directory file LFS_TYPE_DIR = 2, // A directory file
LFS_TYPE_STICKYNOTE = 3, // An uncommitted file LFS_TYPE_STICKYNOTE = 3, // An uncommitted file
LFS_TYPE_UNKNOWN = 6, // Unknown file type LFS_TYPE_UNKNOWN = 7, // Unknown file type
// internally used types, don't use these // internally used types, don't use these
LFS_type_BOOKMARK = 4, // Directory bookmark LFS_type_ORPHAN = 4, // An orphaned stickynote
LFS_type_TRAVERSAL = 5, // An open traversal object LFS_type_BOOKMARK = 5, // Directory bookmark
LFS_type_TRAVERSAL = 6, // An open traversal object
}; };
// File open flags // File open flags
+6 -4
View File
@@ -41,8 +41,9 @@ FLAGS = [
('^', 'DIR', 0x20000000, "Type = directory" ), ('^', 'DIR', 0x20000000, "Type = directory" ),
('^', 'STICKYNOTE',0x30000000, "Type = stickynote" ), ('^', 'STICKYNOTE',0x30000000, "Type = stickynote" ),
('^', 'BOOKMARK', 0x40000000, "Type = bookmark" ), ('^', 'BOOKMARK', 0x40000000, "Type = bookmark" ),
('^', 'TRAVERSAL', 0x50000000, "Type = traversal" ), ('^', 'ORPHAN', 0x50000000, "Type = orphan" ),
('^', 'UNKNOWN', 0x60000000, "Type = unknown" ), ('^', 'TRAVERSAL', 0x60000000, "Type = traversal" ),
('^', 'UNKNOWN', 0x70000000, "Type = unknown" ),
('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" ),
@@ -133,8 +134,9 @@ FLAGS = [
('^', 'DIR', 0x20000000, "Type = directory" ), ('^', 'DIR', 0x20000000, "Type = directory" ),
('^', 'STICKYNOTE',0x30000000, "Type = stickynote" ), ('^', 'STICKYNOTE',0x30000000, "Type = stickynote" ),
('^', 'BOOKMARK', 0x40000000, "Type = bookmark" ), ('^', 'BOOKMARK', 0x40000000, "Type = bookmark" ),
('^', 'TRAVERSAL', 0x50000000, "Type = traversal" ), ('^', 'ORPHAN', 0x50000000, "Type = orphan" ),
('^', 'UNKNOWN', 0x60000000, "Type = unknown" ), ('^', 'TRAVERSAL', 0x60000000, "Type = traversal" ),
('^', 'UNKNOWN', 0x70000000, "Type = unknown" ),
('t', 'TSTATE', 0x0000000f, "The traversal's current tstate" ), ('t', 'TSTATE', 0x0000000f, "The traversal's current tstate" ),
('^', 'MROOTANCHOR', ('^', 'MROOTANCHOR',
0x00000000, "Tstate = mroot-anchor" ), 0x00000000, "Tstate = mroot-anchor" ),