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:
@@ -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,10 +9332,8 @@ 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_ERR_NOENT
|
||||||
~(LFS_o_ZOMBIE | LFS_O_DESYNC)))
|
|
||||||
? 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) {
|
||||||
|
|||||||
@@ -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
@@ -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" ),
|
||||||
|
|||||||
Reference in New Issue
Block a user