From f024b35170e1218f96f3cc6ca187768c89a843ca Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 12 Jun 2024 01:00:33 -0500 Subject: [PATCH] Fixed missing mroot attrs lost during uninlining Not sure how this was missed for so long, but we completely forget about in-flight mroot attrs if we happen to uninline the mtree. I guess this was missed because only some late-stage fs ops need to commit mroot attrs (lfsr_fs_grow, lfsr_setattr, upgrades, etc), but being able to commit to the mroot is definitely an operation we need to support. Fixing this in a non-awkward way was a bit tricky. We need some way to commit both the provided attr-list and our new mtree, but all of the lower layers only accept a single attr-list. The solution here is to add a special tail-recursive LFSR_TAG_ATTRS that can be used to chain together multiple attr-lists. This solves the problem quite elegantly and may actually be useful in the future? It takes a bit of code: code stack before: 33850 2584 after: 33926 (+0.2%) 2592 (+0.3%) But this solves our final lfsr_fs_grow-related bug. No more mroot-split hacks in test_grow, and we can now grow any stuck filesystem. --- lfs.c | 51 +++-- tests/test_grow.toml | 126 +----------- tests/test_mtree.toml | 466 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 454 insertions(+), 189 deletions(-) diff --git a/lfs.c b/lfs.c index 5d33394c..b171abeb 100644 --- a/lfs.c +++ b/lfs.c @@ -837,9 +837,10 @@ enum lfsr_tag { // in-device only tags, these should never get written to disk LFSR_TAG_INTERNAL = 0x0800, - LFSR_TAG_MOVE = 0x0800, - LFSR_TAG_SHRUBCOMMIT = 0x0801, - LFSR_TAG_SHRUBTRUNK = 0x0802, + LFSR_TAG_ATTRS = 0x0800, + LFSR_TAG_MOVE = 0x0801, + LFSR_TAG_SHRUBCOMMIT = 0x0802, + LFSR_TAG_SHRUBTRUNK = 0x0803, // some in-device only tag modifiers LFSR_TAG_RM = 0x8000, @@ -1671,6 +1672,10 @@ typedef struct lfsr_data_name { // hacky attrs - these end up handled as special cases in high-level // commit layers +// chain another attr-list, only allowed as last attr +#define LFSR_ATTR_ATTRS(_tag, _weight, _attrs, _attr_count) \ + LFSR_ATTR_(_tag, _weight, (const lfsr_attr_t*){_attrs}, _attr_count) + // a move of all attrs from an mdir entry #define LFSR_ATTR_MOVE(_tag, _weight, _mdir) \ LFSR_ATTR_(_tag, _weight, (const lfsr_mdir_t*){_mdir}, 0) @@ -6106,10 +6111,25 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir, // we just happen to never split in an mdir commit LFS_ASSERT(!(i > 0 && lfsr_attr_isinsert(attrs[i]))); + // attr lists can be chained, but only tail-recursively + if (attrs[i].tag == LFSR_TAG_ATTRS) { + // must be the last tag + LFS_ASSERT(i == attr_count-1); + // how would weight make sense here? + LFS_ASSERT(attrs[i].weight == 0); + const lfsr_attr_t *attrs_ = attrs[i].cat; + lfs_size_t attr_count_ = attrs[i].count; + + // switch to chained attr-list + attrs = attrs_; + attr_count = attr_count_; + i = -1; + continue; + // move tags copy over any tags associated with the source's rid // TODO can this be deduplicated with lfsr_mdir_compact__ more? // it _really_ wants to be deduplicated - if (attrs[i].tag == LFSR_TAG_MOVE) { + } else if (attrs[i].tag == LFSR_TAG_MOVE) { // weighted moves are not supported LFS_ASSERT(attrs[i].weight == 0); const lfsr_mdir_t *mdir__ = attrs[i].cat; @@ -7135,14 +7155,21 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // note end_rid=0 here will delete any files leftover from a split // in our mroot uint8_t mtree_buf[LFS_MAX(LFSR_MPTR_DSIZE, LFSR_BTREE_DSIZE)]; - err = lfsr_mdir_commit_(lfs, &mroot_, -1, 0, NULL, -1, LFSR_ATTRS( - (lfsr_mtree_ismptr(&mtree_)) - ? LFSR_ATTR( - LFSR_TAG_SUB | LFSR_TAG_MDIR, 0, - LFSR_DATA_MPTR_(&mtree_.u.mptr.mptr, mtree_buf)) - : LFSR_ATTR( - LFSR_TAG_SUB | LFSR_TAG_MTREE, 0, - LFSR_DATA_BTREE_(&mtree_.u.btree, mtree_buf)))); + err = lfsr_mdir_commit_(lfs, &mroot_, -1, 0, NULL, + -1, LFSR_ATTRS( + (lfsr_mtree_ismptr(&mtree_)) + ? LFSR_ATTR( + LFSR_TAG_SUB | LFSR_TAG_MDIR, 0, + LFSR_DATA_MPTR_(&mtree_.u.mptr.mptr, mtree_buf)) + : LFSR_ATTR( + LFSR_TAG_SUB | LFSR_TAG_MTREE, 0, + LFSR_DATA_BTREE_(&mtree_.u.btree, mtree_buf)), + // were we committing to the mroot? include any -1 attrs + (mdir->mid == -1) + ? LFSR_ATTR_ATTRS( + LFSR_TAG_ATTRS, 0, + attrs, attr_count) + : LFSR_ATTR_NOOP())); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); goto failed; diff --git a/tests/test_grow.toml b/tests/test_grow.toml index 7b1e92fe..a2cee7ec 100644 --- a/tests/test_grow.toml +++ b/tests/test_grow.toml @@ -442,7 +442,7 @@ code = ''' # [cases.test_grow_incr_dir_many] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] code = ''' @@ -584,7 +584,7 @@ code = ''' ''' [cases.test_grow_incr_dir_fuzz] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] defines.OPS = 1024 @@ -608,18 +608,6 @@ code = ''' assert(fsinfo.name_limit == LFS_NAME_MAX); assert(fsinfo.file_limit == LFS_FILE_MAX); - // make mroot split, TODO fix this - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_mkdir(&lfs, name) => 0; - } - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_remove(&lfs, name) => 0; - } - // set up a simulation to compare against lfs_size_t *sim = malloc(N*sizeof(lfs_size_t)); lfs_size_t sim_size = 0; @@ -822,7 +810,7 @@ code = ''' ''' [cases.test_grow_incr_file_many] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ @@ -853,18 +841,6 @@ code = ''' assert(fsinfo.name_limit == LFS_NAME_MAX); assert(fsinfo.file_limit == LFS_FILE_MAX); - // make mroot split, TODO fix this - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_mkdir(&lfs, name) => 0; - } - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_remove(&lfs, name) => 0; - } - uint32_t prng = 42; for (lfs_size_t i = 0; i < N; i++) { again:; @@ -982,7 +958,7 @@ code = ''' ''' [cases.test_grow_incr_file_fuzz] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 1024 @@ -1016,18 +992,6 @@ code = ''' assert(fsinfo.name_limit == LFS_NAME_MAX); assert(fsinfo.file_limit == LFS_FILE_MAX); - // make mroot split, TODO fix this - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_mkdir(&lfs, name) => 0; - } - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_remove(&lfs, name) => 0; - } - // set up a simulation to compare against lfs_size_t *sim = malloc(N*sizeof(lfs_size_t)); uint32_t *sim_prngs = malloc(N*sizeof(uint32_t)); @@ -1291,7 +1255,7 @@ code = ''' ''' [cases.test_grow_incr_orphanzombie_fuzz] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 1024 defines.SIZE = [ @@ -1324,18 +1288,6 @@ code = ''' assert(fsinfo.name_limit == LFS_NAME_MAX); assert(fsinfo.file_limit == LFS_FILE_MAX); - // make mroot split, TODO fix this - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_mkdir(&lfs, name) => 0; - } - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_remove(&lfs, name) => 0; - } - // set up a simulation to compare against lfs_size_t *sim = malloc(N*sizeof(lfs_size_t)); uint32_t *sim_prngs = malloc(N*sizeof(uint32_t)); @@ -1729,7 +1681,7 @@ code = ''' ''' [cases.test_grow_incr_orphanzombiedir_fuzz] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 1024 defines.SIZE = [ @@ -1762,18 +1714,6 @@ code = ''' assert(fsinfo.name_limit == LFS_NAME_MAX); assert(fsinfo.file_limit == LFS_FILE_MAX); - // make mroot split, TODO fix this - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_mkdir(&lfs, name) => 0; - } - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - lfsr_remove(&lfs, name) => 0; - } - // set up a simulation to compare against lfs_size_t *sim = malloc(N*sizeof(lfs_size_t)); uint32_t *sim_prngs = malloc(N*sizeof(uint32_t)); @@ -2271,7 +2211,7 @@ code = ''' # wrong. # [cases.test_grow_incr_file_pl_fuzz] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 256 defines.SIZE = [ @@ -2309,31 +2249,6 @@ code = ''' assert(fsinfo.file_limit == LFS_FILE_MAX); } - // make mroot split, TODO fix this - struct lfs_info info; - err = lfsr_stat(&lfs, "split", &info); - assert(!err || err == LFS_ERR_NOENT); - if (err == LFS_ERR_NOENT) { - if (lfs.mtree.u.weight == 0x80000000) { - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - err = lfsr_mkdir(&lfs, name); - assert(!err || err == LFS_ERR_EXIST); - } - } - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - err = lfsr_remove(&lfs, name); - assert(!err || err == LFS_ERR_NOENT); - } - lfsr_file_t file; - lfsr_file_open(&lfs, &file, "split", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfsr_file_close(&lfs, &file) => 0; - } - // keep some test state on disk to survive powerloss typedef struct fuzz_state { lfs_size_t i; @@ -2609,7 +2524,7 @@ code = ''' # wrong. # [cases.test_grow_incr_filedir_pl_fuzz] -defines.INIT_BLOCK_COUNT = 7 # TODO need to fix mroot split issue +defines.INIT_BLOCK_COUNT = 2 # note dirs x files grows O(n^2) defines.N = [1, 2, 4, 8] defines.M = 'N' @@ -2649,31 +2564,6 @@ code = ''' assert(fsinfo.file_limit == LFS_FILE_MAX); } - // make mroot split, TODO fix this - struct lfs_info info; - err = lfsr_stat(&lfs, "split", &info); - assert(!err || err == LFS_ERR_NOENT); - if (err == LFS_ERR_NOENT) { - if (lfs.mtree.u.weight == 0x80000000) { - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - err = lfsr_mkdir(&lfs, name); - assert(!err || err == LFS_ERR_EXIST); - } - } - for (lfs_size_t i = 0; i < 24; i++) { - char name[256]; - sprintf(name, "splitme%03x", i); - err = lfsr_remove(&lfs, name); - assert(!err || err == LFS_ERR_NOENT); - } - lfsr_file_t file; - lfsr_file_open(&lfs, &file, "split", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfsr_file_close(&lfs, &file) => 0; - } - // keep some test state on disk to survive powerloss typedef struct fuzz_state { lfs_size_t i; diff --git a/tests/test_mtree.toml b/tests/test_mtree.toml index 024147e1..4ecee658 100644 --- a/tests/test_mtree.toml +++ b/tests/test_mtree.toml @@ -168,11 +168,12 @@ code = ''' lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined assert(lfsr_mtree_weight(&lfs.mtree) == (1 << lfs.mdir_bits)); @@ -186,10 +187,14 @@ code = ''' lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; assert(mdir.rbyd.weight == 1); - lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[0] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -206,10 +211,14 @@ code = ''' lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; assert(mdir.rbyd.weight == 1); - lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[0] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -244,7 +253,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -264,6 +274,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -286,6 +300,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -320,7 +338,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -328,7 +347,7 @@ code = ''' assert(lfs.mroot.rbyd.weight == 0); // now add another large entry to an mdir, forcing a split - memset(buffer+1, 'c', SIZE-1); + memset(buffer+1, 'd', SIZE-1); lfsr_mtree_namelookup(&lfs, &lfs.mtree, 0, (const char*)buffer+1, SIZE-1, &mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -337,7 +356,8 @@ code = ''' // force mdir to compact mdir.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("e", 1)))) => 0; // assert mdir was split correctly assert(lfsr_mtree_weight(&lfs.mtree) == (3 << lfs.mdir_bits)); @@ -357,11 +377,19 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_mtree_lookup(&lfs, &lfs.mtree, (2 << lfs.mdir_bits)+0, &mdir) => 0; assert(mdir.rbyd.weight == 1); lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_REG, &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; - assert(buffer[1] == 'c'); + assert(buffer[1] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); // check things stay sane after remount lfsr_unmount(&lfs) => 0; @@ -385,11 +413,19 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_mtree_lookup(&lfs, &lfs.mtree, (2 << lfs.mdir_bits)+0, &mdir) => 0; assert(mdir.rbyd.weight == 1); lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_REG, &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; - assert(buffer[1] == 'c'); + assert(buffer[1] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); lfsr_unmount(&lfs) => 0; ''' @@ -606,7 +642,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -633,6 +670,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -649,6 +690,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -683,7 +728,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -712,6 +758,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -728,6 +778,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -833,7 +887,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -841,7 +896,7 @@ code = ''' assert(lfs.mroot.rbyd.weight == 0); // now add another large entry to an mdir, forcing a split - memset(buffer+1, 'c', SIZE-1); + memset(buffer+1, 'd', SIZE-1); lfsr_mtree_namelookup(&lfs, &lfs.mtree, 0, (const char*)buffer+1, SIZE-1, &mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -870,11 +925,15 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_mtree_lookup(&lfs, &lfs.mtree, (1 << lfs.mdir_bits)+0, &mdir) => 0; assert(mdir.rbyd.weight == 1); lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_REG, &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; - assert(buffer[1] == 'c'); + assert(buffer[1] == 'd'); // check things stay sane after remount lfsr_unmount(&lfs) => 0; @@ -892,11 +951,15 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_mtree_lookup(&lfs, &lfs.mtree, (1 << lfs.mdir_bits)+0, &mdir) => 0; assert(mdir.rbyd.weight == 1); lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_REG, &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; - assert(buffer[1] == 'c'); + assert(buffer[1] == 'd'); lfsr_unmount(&lfs) => 0; ''' @@ -932,7 +995,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -940,7 +1004,7 @@ code = ''' assert(lfs.mroot.rbyd.weight == 0); // now add another large entry to an mdir, forcing a split - memset(buffer+1, 'c', SIZE-1); + memset(buffer+1, 'd', SIZE-1); lfsr_mtree_namelookup(&lfs, &lfs.mtree, 0, (const char*)buffer+1, SIZE-1, &mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -948,7 +1012,7 @@ code = ''' assert(mdir.rbyd.weight == 2); // remove an entry, forcing the mdir to be dropped - memset(buffer+1, 'c', SIZE-1); + memset(buffer+1, 'd', SIZE-1); lfsr_mtree_namelookup(&lfs, &lfs.mtree, 0, (const char*)buffer+1, SIZE-1, &mdir, NULL, NULL) => 0; // force mdir to compact while we're removing @@ -975,6 +1039,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -997,6 +1065,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -1157,11 +1229,12 @@ code = ''' lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined assert(lfsr_mtree_weight(&lfs.mtree) == (1 << lfs.mdir_bits)); @@ -1173,10 +1246,10 @@ code = ''' lfsr_mdir_t old_mdir = mdir; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(4), 0, LFSR_DATA_BUF("d", 1)))) => 0; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(5), 0, LFSR_DATA_BUF("e", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); @@ -1192,10 +1265,24 @@ code = ''' lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; assert(mdir.rbyd.weight == 1); - lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[0] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; + assert(mdir.rbyd.weight == 1); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1212,10 +1299,24 @@ code = ''' lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; assert(mdir.rbyd.weight == 1); - lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[0] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; + assert(mdir.rbyd.weight == 1); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + lfsr_unmount(&lfs) => 0; ''' @@ -1252,7 +1353,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -1266,10 +1368,10 @@ code = ''' lfsr_mdir_t old_mdir = mdir; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("d", 1)))) => 0; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("e", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); @@ -1291,6 +1393,20 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, (0 << lfs.mdir_bits)+1, &mdir) => 0; + assert(mdir.rbyd.weight == 2); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1313,6 +1429,20 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, (0 << lfs.mdir_bits)+1, &mdir) => 0; + assert(mdir.rbyd.weight == 2); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + lfsr_unmount(&lfs) => 0; ''' @@ -1349,7 +1479,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -1363,10 +1494,10 @@ code = ''' lfsr_mdir_t old_mdir = mdir; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("d", 1)))) => 0; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("e", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); @@ -1388,6 +1519,20 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, (1 << lfs.mdir_bits)+0, &mdir) => 0; + assert(mdir.rbyd.weight == 1); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1410,6 +1555,20 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, (1 << lfs.mdir_bits)+0, &mdir) => 0; + assert(mdir.rbyd.weight == 1); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + lfsr_unmount(&lfs) => 0; ''' @@ -1440,9 +1599,11 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("b", 1)))) => 0; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); @@ -1453,6 +1614,14 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'b'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1464,6 +1633,14 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'b'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -1497,9 +1674,11 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("b", 1)))) => 0; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); @@ -1507,13 +1686,17 @@ code = ''' // twice, forcing a second mroot extension old_mroot = lfs.mroot; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("d", 1)))) => 0; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(4), 0, LFSR_DATA_BUF("e", 1)))) => 0; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(5), 0, LFSR_DATA_BUF("f", 1)))) => 0; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(6), 0, LFSR_DATA_BUF("g", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); @@ -1524,6 +1707,30 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'b'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'f'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'g'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1535,6 +1742,30 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'b'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'f'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'g'); + lfsr_unmount(&lfs) => 0; ''' @@ -1565,18 +1796,22 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("b", 1)))) => 0; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); // force mroot to compact twice again, this should relocate the mroot old_mroot = lfs.mroot; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("d", 1)))) => 0; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(4), 0, LFSR_DATA_BUF("e", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); @@ -1587,6 +1822,22 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'b'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1598,6 +1849,22 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'b'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + lfsr_unmount(&lfs) => 0; ''' @@ -1634,7 +1901,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -1651,10 +1919,10 @@ code = ''' lfsr_mdir_t old_mdir = mdir; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("d", 1)))) => 0; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("e", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); // assert mroot relocated @@ -1678,6 +1946,20 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, (1 << lfs.mdir_bits)+0, &mdir) => 0; + assert(mdir.rbyd.weight == 1); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1700,6 +1982,20 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + + lfsr_mtree_lookup(&lfs, &lfs.mtree, (1 << lfs.mdir_bits)+0, &mdir) => 0; + assert(mdir.rbyd.weight == 1); + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + lfsr_unmount(&lfs) => 0; ''' @@ -1736,7 +2032,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -1744,7 +2041,7 @@ code = ''' assert(lfs.mroot.rbyd.weight == 0); // now add another large entry to an mdir, forcing a split - memset(buffer+1, 'c', SIZE-1); + memset(buffer+1, 'd', SIZE-1); lfsr_mtree_namelookup(&lfs, &lfs.mtree, 0, (const char*)buffer+1, SIZE-1, &mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -1758,10 +2055,10 @@ code = ''' lfsr_mdir_t old_mdir = mdir; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("e", 1)))) => 0; mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("f", 1)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); // assert mroot relocated @@ -1785,11 +2082,23 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_mtree_lookup(&lfs, &lfs.mtree, (2 << lfs.mdir_bits)+0, &mdir) => 0; assert(mdir.rbyd.weight == 1); lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_REG, &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; - assert(buffer[1] == 'c'); + assert(buffer[1] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'f'); // check things stay sane after remount lfsr_unmount(&lfs) => 0; @@ -1813,11 +2122,23 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_mtree_lookup(&lfs, &lfs.mtree, (2 << lfs.mdir_bits)+0, &mdir) => 0; assert(mdir.rbyd.weight == 1); lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_REG, &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; - assert(buffer[1] == 'c'); + assert(buffer[1] == 'd'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'e'); + + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'f'); lfsr_unmount(&lfs) => 0; ''' @@ -1855,7 +2176,8 @@ code = ''' // force mroot to compact lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs.mtree) == (2 << lfs.mdir_bits)); @@ -1872,7 +2194,7 @@ code = ''' // force mdir to compact twice, this should relocate mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_REG, 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF("d", 1)))) => 0; // force mdir to compact while we're removing mdir.rbyd.eoff = -1; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -1893,6 +2215,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1909,6 +2235,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'a'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -1940,12 +2270,13 @@ code = ''' lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(LFSR_TAG_UATTR(2), 0, LFSR_DATA_BUF(buffer, SIZE)))) => 0; // force mroot to compact, this should both uninline and relocate lfsr_mdir_t old_mroot = lfs.mroot; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(3), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mroot relocated assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); @@ -1961,10 +2292,14 @@ code = ''' lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; assert(mdir.rbyd.weight == 1); - lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[0] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -1981,10 +2316,14 @@ code = ''' lfsr_mtree_lookup(&lfs, &lfs.mtree, 0, &mdir) => 0; assert(mdir.rbyd.weight == 1); - lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_mdir_lookup(&lfs, &mdir, LFSR_TAG_UATTR(2), &data) => 0; lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[0] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; ''' @@ -2027,7 +2366,8 @@ code = ''' // force mroot to compact, this should both split and relocate lfsr_mdir_t old_mroot = lfs.mroot; lfs.mroot.rbyd.eoff = -1; - lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_UATTR(1), 0, LFSR_DATA_BUF("c", 1)))) => 0; // assert mroot relocated assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); @@ -2049,6 +2389,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + // check things stay sane after remount lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; @@ -2071,6 +2415,10 @@ code = ''' lfsr_data_read(&lfs, &data, buffer, SIZE) => SIZE; assert(buffer[1] == 'b'); + lfsr_mdir_lookup(&lfs, &lfs.mroot, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 1) => 1; + assert(buffer[0] == 'c'); + lfsr_unmount(&lfs) => 0; '''