From 4010afeafd6f0d0eed059847fb9fdf24124cca7e Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 9 Nov 2025 00:26:55 -0600 Subject: [PATCH] trv: Reintroduced LFS3_T_EXCL With the relaxation of traversal behavior under mutation, I think it makes sense to bring back LFS3_T_EXCL. If only to allow traversals to gaurantee termination under mutation. Now that traversals no longer guarantee forward progress, it's possible to get stuck looping indefinitely if the filesystem is constantly being mutated. Non-excl traversals are probably still useful for GC work and debugging threads, but LFS3_T_EXCL now allows traversals to terminate immediately with LFS3_ERR_BUSY at the first sign of unrelated filesystem mutation: LFS3_T_EXCL 0x00000008 Error if filesystem modified Internally, we already track unrelated mutation to avoid corrupt state (LFS3_t_DIRTY), so this is a very low-cost feature: code stack ctx before: 35944 2280 660 after: 35964 (+0.1%) 2280 (+0.0%) 660 (+0.0%) code stack ctx gbmap before: 38916 2296 772 gbmap after: 38940 (+0.1%) 2296 (+0.0%) 772 (+0.0%) code stack ctx gc before: 36016 2280 768 gc after: 36036 (+0.1%) 2280 (+0.0%) 768 (+0.0%) --- lfs3.c | 11 ++ lfs3.h | 2 + scripts/dbgerr.py | 1 + scripts/dbgflags.py | 1 + tests/test_trvs.toml | 419 ++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 405 insertions(+), 29 deletions(-) diff --git a/lfs3.c b/lfs3.c index f2bd19e5..b10e1ff3 100644 --- a/lfs3.c +++ b/lfs3.c @@ -7355,6 +7355,10 @@ static inline bool lfs3_t_ismtreeonly(uint32_t flags) { return flags & LFS3_T_MTREEONLY; } +static inline bool lfs3_t_isexcl(uint32_t flags) { + return flags & LFS3_T_EXCL; +} + static inline bool lfs3_t_ismkconsistent(uint32_t flags) { (void)flags; #ifndef LFS3_RDONLY @@ -16914,6 +16918,7 @@ int lfs3_trv_open(lfs3_t *lfs3, lfs3_trv_t *trv, uint32_t flags) { LFS3_IFDEF_RDONLY(0, LFS3_T_RDWR) | LFS3_T_RDONLY | LFS3_T_MTREEONLY + | LFS3_T_EXCL | LFS3_IFDEF_RDONLY(0, LFS3_T_MKCONSISTENT) | LFS3_IFDEF_RDONLY(0, LFS3_T_RELOOKAHEAD) | LFS3_IFDEF_RDONLY(0, @@ -16959,6 +16964,12 @@ int lfs3_trv_read(lfs3_t *lfs3, lfs3_trv_t *trv, struct lfs3_tinfo *tinfo) { LFS3_ASSERT(lfs3_handle_isopen(lfs3, &trv->gc.t.h)); + // filesystem modified? excl? terminate early + if (lfs3_t_isexcl(trv->gc.t.h.flags) + && lfs3_t_isdirty(trv->gc.t.h.flags)) { + return LFS3_ERR_BUSY; + } + // check for pending grms every step, just in case some other // operation introduced new grms #ifndef LFS3_RDONLY diff --git a/lfs3.h b/lfs3.h index 236f040b..e4d9171a 100644 --- a/lfs3.h +++ b/lfs3.h @@ -77,6 +77,7 @@ enum lfs3_err { LFS3_ERR_UNKNOWN = -1, // Unknown error LFS3_ERR_INVAL = -22, // Invalid parameter LFS3_ERR_NOTSUP = -95, // Operation not supported + LFS3_ERR_BUSY = -16, // Device or resource busy LFS3_ERR_IO = -5, // Error during device operation LFS3_ERR_CORRUPT = -84, // Corrupted LFS3_ERR_NOENT = -2, // No directory entry @@ -318,6 +319,7 @@ enum lfs3_btype { #define LFS3_T_RDONLY 1 // Open traversal as read only #define LFS3_T_MTREEONLY \ 0x00000002 // Only traverse the mtree +#define LFS3_T_EXCL 0x00000008 // Error if filesystem modified #ifndef LFS3_RDONLY #define LFS3_T_MKCONSISTENT \ 0x00000100 // Make the filesystem consistent diff --git a/scripts/dbgerr.py b/scripts/dbgerr.py index 56cb4d90..8db40631 100755 --- a/scripts/dbgerr.py +++ b/scripts/dbgerr.py @@ -12,6 +12,7 @@ ERR_OK = 0 # No error ERR_UNKNOWN = -1 # Unknown error ERR_INVAL = -22 # Invalid parameter ERR_NOTSUP = -95 # Operation not supported +ERR_BUSY = -16 # Device or resource busy ERR_IO = -5 # Error during device operation ERR_CORRUPT = -84 # Corrupted ERR_NOENT = -2 # No directory entry diff --git a/scripts/dbgflags.py b/scripts/dbgflags.py index f4da8fdc..e80f3ead 100755 --- a/scripts/dbgflags.py +++ b/scripts/dbgflags.py @@ -139,6 +139,7 @@ T_MODE = 1 # -m The traversal's access mode T_RDWR = 0 # -^ Open traversal as read and write T_RDONLY = 1 # -^ Open traversal as read only T_MTREEONLY = 0x00000002 # -- Only traverse the mtree +T_EXCL = 0x00000008 # -- Error if filesystem modified T_MKCONSISTENT = 0x00000100 # -- Make the filesystem consistent T_RELOOKAHEAD = 0x00000200 # -- Repopulate lookahead buffer T_REGBMAP = 0x00000400 # -- Repopulate the gbmap diff --git a/tests/test_trvs.toml b/tests/test_trvs.toml index 4442f155..4c808015 100644 --- a/tests/test_trvs.toml +++ b/tests/test_trvs.toml @@ -1846,6 +1846,7 @@ code = ''' # test that we detect filesystem mutation during traversal [cases.test_trvs_mutation] defines.WHEN = [0, 1, 2] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -1861,6 +1862,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -1873,6 +1875,12 @@ code = ''' } struct lfs3_tinfo tinfo; + // terminate early? + if (EXCL && WHEN == 0) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); @@ -1882,7 +1890,15 @@ code = ''' lfs3_file_open(&lfs3, &file, "spider", LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_EXCL) => 0; lfs3_file_close(&lfs3, &file) => 0; - } else { + } + + // terminate early? + if (EXCL && WHEN == 1) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } + if (WHEN != 1) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); @@ -1895,6 +1911,12 @@ code = ''' lfs3_file_close(&lfs3, &file) => 0; } + // terminate early? + if (EXCL && WHEN == 2) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -1904,6 +1926,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -1919,6 +1942,7 @@ code = ''' # test that we don't get extra anything after end of traversal [cases.test_trvs_mutation_idempotent] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -1934,6 +1958,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -1948,20 +1973,32 @@ code = ''' LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_EXCL) => 0; lfs3_file_close(&lfs3, &file) => 0; - // traverse gbmap - if (GBMAP) { - lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; - assert(tinfo.btype == LFS3_BTYPE_BTREE); - assert(tinfo.block == 2); - } - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + } else { + // traverse gbmap + if (GBMAP) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; + assert(tinfo.btype == LFS3_BTYPE_BTREE); + assert(tinfo.block == 2); + } + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + } // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; @@ -1978,12 +2015,22 @@ code = ''' LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_EXCL) => 0; lfs3_file_close(&lfs3, &file) => 0; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + } else { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; + } // we should _not_ update lookahead/compact/ckmeta/ckdata lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2001,6 +2048,7 @@ code = ''' [cases.test_trvs_mutation_mkdir] defines.WHEN = [0, 1, 2] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2016,6 +2064,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2025,13 +2074,27 @@ code = ''' } struct lfs3_tinfo tinfo; + // terminate early? + if (EXCL && WHEN == 0) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); if (WHEN == 1) { lfs3_mkdir(&lfs3, "spider") => 0; - } else { + } + + // terminate early? + if (EXCL && WHEN == 1) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } + if (WHEN != 1) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); @@ -2041,6 +2104,12 @@ code = ''' lfs3_mkdir(&lfs3, "spider") => 0; } + // terminate early? + if (EXCL && WHEN == 2) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -2050,6 +2119,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2065,6 +2135,7 @@ code = ''' [cases.test_trvs_mutation_rm] defines.WHEN = [0, 1, 2] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2086,6 +2157,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2095,13 +2167,27 @@ code = ''' } struct lfs3_tinfo tinfo; + // terminate early? + if (EXCL && WHEN == 0) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); if (WHEN == 1) { lfs3_remove(&lfs3, "spider") => 0; - } else { + } + + // terminate early? + if (EXCL && WHEN == 1) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } + if (WHEN != 1) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); @@ -2111,6 +2197,12 @@ code = ''' lfs3_remove(&lfs3, "spider") => 0; } + // terminate early? + if (EXCL && WHEN == 2) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -2120,6 +2212,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2135,6 +2228,7 @@ code = ''' [cases.test_trvs_mutation_mv] defines.WHEN = [0, 1, 2] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2156,6 +2250,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2165,18 +2260,31 @@ code = ''' } struct lfs3_tinfo tinfo; + // terminate early? + if (EXCL && WHEN == 0) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); if (WHEN == 1) { lfs3_rename(&lfs3, "spider", "scorpion") => 0; - } else { + } + + // terminate early? + if (EXCL && WHEN == 1) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } + if (WHEN != 1) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); assert(tinfo.block == 0 || tinfo.block == 1); } - // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -2186,7 +2294,15 @@ code = ''' if (WHEN == 2) { lfs3_rename(&lfs3, "spider", "scorpion") => 0; + } + // terminate early? + if (EXCL && WHEN == 2) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } + if (WHEN == 2) { // traverse gbmap again if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -2194,10 +2310,10 @@ code = ''' assert(tinfo.block == 2); } } - lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2213,6 +2329,7 @@ code = ''' # some more complex mutation tests [cases.test_trvs_mutation_fwrite] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2249,6 +2366,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2267,8 +2385,11 @@ code = ''' // step traversal struct lfs3_tinfo tinfo; int err = lfs3_trv_read(&lfs3, &trv, &tinfo); - assert(!err || err == LFS3_ERR_NOENT); - if (err == LFS3_ERR_NOENT) { + assert(!err + || err == LFS3_ERR_NOENT + || (EXCL && err == LFS3_ERR_BUSY)); + if (err == LFS3_ERR_NOENT + || err == LFS3_ERR_BUSY) { break; } } @@ -2299,6 +2420,7 @@ code = ''' ''' [cases.test_trvs_mutation_fwrite_opened] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2339,6 +2461,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2358,8 +2481,11 @@ code = ''' // step traversal struct lfs3_tinfo tinfo; int err = lfs3_trv_read(&lfs3, &trv, &tinfo); - assert(!err || err == LFS3_ERR_NOENT); - if (err == LFS3_ERR_NOENT) { + assert(!err + || err == LFS3_ERR_NOENT + || (EXCL && err == LFS3_ERR_BUSY)); + if (err == LFS3_ERR_NOENT + || err == LFS3_ERR_BUSY) { break; } } @@ -2406,6 +2532,7 @@ code = ''' # these assume quite a bit more and may be a bit fragile... # [cases.test_trvs_mutation_file_bsprout] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2445,6 +2572,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2468,6 +2596,12 @@ code = ''' lfs3_file_write(&lfs3, &file, wbuf1, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -2478,6 +2612,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2504,6 +2639,7 @@ code = ''' ''' [cases.test_trvs_mutation_file_btree] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2544,6 +2680,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2579,6 +2716,12 @@ code = ''' lfs3_file_write(&lfs3, &file, wbuf1, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse btree lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_BTREE); @@ -2599,6 +2742,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2626,6 +2770,7 @@ code = ''' ''' [cases.test_trvs_mutation_file_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2665,6 +2810,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2697,6 +2843,12 @@ code = ''' lfs3_file_write(&lfs3, &file, wbuf1, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -2711,6 +2863,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2738,6 +2891,7 @@ code = ''' ''' [cases.test_trvs_mutation_uncreat_bsprout] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2777,6 +2931,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2798,6 +2953,12 @@ code = ''' lfs3_file_write(&lfs3, &file1, wbuf1, SIZE) => SIZE; lfs3_file_flush(&lfs3, &file1) => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -2808,6 +2969,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2838,6 +3000,7 @@ code = ''' ''' [cases.test_trvs_mutation_uncreat_btree] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -2878,6 +3041,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -2911,6 +3075,12 @@ code = ''' lfs3_file_write(&lfs3, &file1, wbuf1, SIZE) => SIZE; lfs3_file_flush(&lfs3, &file1) => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse btree lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_BTREE); @@ -2931,6 +3101,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -2962,6 +3133,7 @@ code = ''' ''' [cases.test_trvs_mutation_uncreat_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3001,6 +3173,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3031,6 +3204,12 @@ code = ''' lfs3_file_write(&lfs3, &file1, wbuf1, SIZE) => SIZE; lfs3_file_flush(&lfs3, &file1) => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -3045,6 +3224,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3076,6 +3256,7 @@ code = ''' ''' [cases.test_trvs_mutation_close_bsprout] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3116,6 +3297,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3143,6 +3325,12 @@ code = ''' // if not desync, traversal rewinds to mdir if (!DESYNC) { + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap again if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -3154,6 +3342,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/etc, unless we're desynced struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3192,6 +3381,7 @@ code = ''' ''' [cases.test_trvs_mutation_close_btree] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3233,6 +3423,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3266,6 +3457,12 @@ code = ''' // if not desync, traversal rewinds to mdir if (!DESYNC) { + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse btree lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_BTREE); @@ -3288,6 +3485,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/etc, unless we're desynced struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3327,6 +3525,7 @@ code = ''' ''' [cases.test_trvs_mutation_close_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3367,6 +3566,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3397,6 +3597,12 @@ code = ''' // if not desync, traversal rewinds to mdir if (!DESYNC) { + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse one data block lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -3413,6 +3619,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/etc, unless we're desynced struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3452,6 +3659,7 @@ code = ''' ''' [cases.test_trvs_mutation_rm_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3490,6 +3698,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3515,6 +3724,12 @@ code = ''' // remove the file lfs3_remove(&lfs3, "spider") => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -3524,6 +3739,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/etc, unless we're desynced struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3552,6 +3768,7 @@ code = ''' ''' [cases.test_trvs_mutation_mv_src_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3599,6 +3816,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3624,6 +3842,12 @@ code = ''' // rename one file over another lfs3_rename(&lfs3, "spider", "tarantula") => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -3638,6 +3862,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3667,6 +3892,7 @@ code = ''' ''' [cases.test_trvs_mutation_mv_dst_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3714,6 +3940,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3739,6 +3966,12 @@ code = ''' // rename one file over another lfs3_rename(&lfs3, "tarantula", "spider") => 0; + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -3753,6 +3986,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3782,6 +4016,7 @@ code = ''' ''' [cases.test_trvs_mutation_mroot_split] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3820,6 +4055,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3841,6 +4077,12 @@ code = ''' i += 1; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -3871,6 +4113,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -3898,6 +4141,7 @@ code = ''' ''' [cases.test_trvs_mutation_mroot_split_bshrub_l] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -3945,6 +4189,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -3978,6 +4223,12 @@ code = ''' i += 1; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -4002,6 +4253,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -4034,6 +4286,7 @@ code = ''' ''' [cases.test_trvs_mutation_mroot_split_bshrub_r] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -4081,6 +4334,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -4119,6 +4373,12 @@ code = ''' i += 1; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -4133,6 +4393,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -4165,6 +4426,7 @@ code = ''' ''' [cases.test_trvs_mutation_mroot_extend] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -4205,6 +4467,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -4224,6 +4487,12 @@ code = ''' lfs3_remove(&lfs3, "uloborus") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -4244,6 +4513,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -4271,6 +4541,7 @@ code = ''' ''' [cases.test_trvs_mutation_mroot_extend_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -4311,6 +4582,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -4342,6 +4614,12 @@ code = ''' lfs3_remove(&lfs3, "uloborus") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -4356,6 +4634,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -4383,6 +4662,7 @@ code = ''' ''' [cases.test_trvs_mutation_mroot_relocate] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -4432,6 +4712,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -4452,6 +4733,12 @@ code = ''' lfs3_remove(&lfs3, "uloborus") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // it's a bit unclear if clobbered mroot chain traversals should // still traverse inlined mroots, so if this breaks in the future // I wouldn't worry too much about it @@ -4481,6 +4768,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -4508,6 +4796,7 @@ code = ''' ''' [cases.test_trvs_mutation_mroot_relocate_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -4557,6 +4846,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -4593,6 +4883,12 @@ code = ''' lfs3_remove(&lfs3, "uloborus") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -4607,6 +4903,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -4634,6 +4931,7 @@ code = ''' ''' [cases.test_trvs_mutation_mtree_split] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -4712,6 +5010,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -4734,6 +5033,12 @@ code = ''' i += 1; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse mtree lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_BTREE); @@ -4787,6 +5092,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -4824,6 +5130,7 @@ code = ''' ''' [cases.test_trvs_mutation_mtree_split_bshrub_l] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -4902,6 +5209,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -4954,6 +5262,12 @@ code = ''' i += 1; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -4983,6 +5297,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -5020,6 +5335,7 @@ code = ''' ''' [cases.test_trvs_mutation_mtree_split_bshrub_r] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -5098,6 +5414,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -5154,6 +5471,13 @@ code = ''' lfs3_file_close(&lfs3, &file) => 0; i += 1; } + + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -5173,6 +5497,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -5210,6 +5535,7 @@ code = ''' ''' [cases.test_trvs_mutation_mtree_extend] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -5294,6 +5620,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -5313,6 +5640,12 @@ code = ''' lfs3_remove(&lfs3, "vulsor") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse mtree lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_BTREE); @@ -5361,6 +5694,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -5398,6 +5732,7 @@ code = ''' ''' [cases.test_trvs_mutation_mtree_extend_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -5482,6 +5817,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -5531,6 +5867,12 @@ code = ''' lfs3_remove(&lfs3, "vulsor") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -5555,6 +5897,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -5592,6 +5935,7 @@ code = ''' ''' [cases.test_trvs_mutation_mtree_relocate] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -5681,6 +6025,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -5701,6 +6046,12 @@ code = ''' lfs3_remove(&lfs3, "vulsor") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse mdir lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); @@ -5754,6 +6105,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; @@ -5791,6 +6143,7 @@ code = ''' ''' [cases.test_trvs_mutation_mtree_relocate_bshrub] +defines.EXCL = [false, true] defines.RELOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] @@ -5880,6 +6233,7 @@ code = ''' lfs3_trv_t trv; lfs3_trv_open(&lfs3, &trv, LFS3_T_RDWR + | ((EXCL) ? LFS3_T_EXCL : 0) | ((RELOOKAHEAD) ? LFS3_T_RELOOKAHEAD : 0) | ((CKMETA) ? LFS3_T_CKMETA : 0) | ((CKDATA) ? LFS3_T_CKDATA : 0)) => 0; @@ -5934,6 +6288,12 @@ code = ''' lfs3_remove(&lfs3, "vulsor") => 0; } + // terminate early? + if (EXCL) { + lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_BUSY; + lfs3_trv_close(&lfs3, &trv) => 0; + goto done; + } // traverse two data blocks lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_DATA); @@ -5958,6 +6318,7 @@ code = ''' lfs3_trv_read(&lfs3, &trv, &tinfo) => LFS3_ERR_NOENT; lfs3_trv_close(&lfs3, &trv) => 0; +done:; // we should _not_ update lookahead/compact/ckmeta/ckdata struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0;