Tweaked lfsr_file_open control flow, fixed a few things

The above-mentioned few things:

- We weren't cleaning up orphans correctly if lfsr_file_open errored.

  I think at some point we relied on having no falible operations after
  the orphan creation, but various refactoring since moved buffer
  allocation after orphan creation.

  We could rearrange things so orphan creation is last, but I think it's
  safter to just deduplicate file cleanup into the new lfsr_file_close_
  function.

- LFS_O_TRUNC prevented attrs from being fetched.

  It's easy to see where this went wrong. LFS_O_TRUNC prevents data from
  being fetched, but we should still fetch attrs.

  This is a bit annoying to fix, for now just added a trunc flag to
  lfsr_file_fetch.

  Also added a couple tests to catch this if it regresses in the future.

- We tried to fetch attrs on orphans.

  This doesn't really hurt anything, but it's a waste of read cycles.

Moving all this stuff around added some code, but lfsr_file_fetch is a
bit easier to read now, which is a good thing:

           code          stack
  before: 38084           2624
  after:  38100 (+0.0%)   2624 (+0.0%)
This commit is contained in:
Christopher Haster
2024-08-23 00:40:39 -05:00
parent 9980323e3f
commit b4da78993b
2 changed files with 198 additions and 46 deletions
+143
View File
@@ -1611,6 +1611,148 @@ code = '''
lfsr_unmount(&lfs) => 0;
'''
# catch LFS_O_TRUNC mistakes, this has created issues before
[cases.test_attrs_fattr_otrunc]
defines.MODE = ['LFS_A_RDWR']
defines.MUTSIZE = [false, true]
code = '''
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// create a file
lfsr_file_t file;
lfsr_file_open(&lfs, &file, "cat", LFS_O_WRONLY | LFS_O_CREAT) => 0;
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
lfsr_file_close(&lfs, &file) => 0;
// create some attrs
const char *a = "One 18.25 ounce package chocolate cake mix.";
lfsr_setattr(&lfs, "cat", 'a', a, strlen(a)) => 0;
const char *b = "One can prepared coconut pecan frosting.";
lfsr_setattr(&lfs, "cat", 'b', b, strlen(b)) => 0;
const char *c = "Three slash four cup vegetable oil.";
lfsr_setattr(&lfs, "cat", 'c', c, strlen(c)) => 0;
// try opening a file with these attrs
uint8_t a_buf[256];
lfs_ssize_t a_size = -1;
uint8_t b_buf[256];
lfs_ssize_t b_size = -1;
uint8_t c_buf[256];
lfs_ssize_t c_size = -1;
struct lfs_attr attrs[] = {
{
.type = 'a',
.flags = MODE,
.buffer = a_buf,
.buffer_size = sizeof(a_buf),
.size = (MUTSIZE) ? &a_size : NULL,
},
{
.type = 'b',
.flags = MODE,
.buffer = b_buf,
.buffer_size = sizeof(b_buf),
.size = (MUTSIZE) ? &b_size : NULL,
},
{
.type = 'c',
.flags = MODE,
.buffer = c_buf,
.buffer_size = sizeof(c_buf),
.size = (MUTSIZE) ? &c_size : NULL,
}
};
struct lfs_file_config filecfg = {
.attrs = attrs,
.attr_count = 3,
};
lfsr_file_opencfg(&lfs, &file, "cat",
MODE | LFS_O_TRUNC, &filecfg) => 0;
// did we read the attrs correctly?
if (MUTSIZE) {
assert(a_size == strlen(a));
}
assert(memcmp(a_buf, a, strlen(a)) == 0);
if (MUTSIZE) {
assert(b_size == strlen(b));
}
assert(memcmp(b_buf, b, strlen(b)) == 0);
if (MUTSIZE) {
assert(c_size == strlen(c));
}
assert(memcmp(c_buf, c, strlen(c)) == 0);
lfsr_file_close(&lfs, &file) => 0;
lfsr_unmount(&lfs) => 0;
'''
# orphan files should zero attributes
[cases.test_attrs_fattr_orphan]
defines.MODE = ['LFS_A_RDWR']
defines.MUTSIZE = [false, true]
code = '''
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// _don't_ create a file
// try opening a file with these attrs
uint8_t a_buf[256];
lfs_ssize_t a_size = -1;
uint8_t b_buf[256];
lfs_ssize_t b_size = -1;
uint8_t c_buf[256];
lfs_ssize_t c_size = -1;
struct lfs_attr attrs[] = {
{
.type = 'a',
.flags = MODE,
.buffer = a_buf,
.buffer_size = sizeof(a_buf),
.size = (MUTSIZE) ? &a_size : NULL,
},
{
.type = 'b',
.flags = MODE,
.buffer = b_buf,
.buffer_size = sizeof(b_buf),
.size = (MUTSIZE) ? &b_size : NULL,
},
{
.type = 'c',
.flags = MODE,
.buffer = c_buf,
.buffer_size = sizeof(c_buf),
.size = (MUTSIZE) ? &c_size : NULL,
}
};
struct lfs_file_config filecfg = {
.attrs = attrs,
.attr_count = 3,
};
lfsr_file_t file;
lfsr_file_opencfg(&lfs, &file, "cat",
MODE | LFS_O_CREAT, &filecfg) => 0;
// did we read the attrs correctly?
if (MUTSIZE) {
assert(a_size == LFS_ERR_NOATTR);
}
if (MUTSIZE) {
assert(b_size == LFS_ERR_NOATTR);
}
if (MUTSIZE) {
assert(c_size == LFS_ERR_NOATTR);
}
lfsr_file_close(&lfs, &file) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that file-attached attrs are written correctly
[cases.test_attrs_fattr_set]
defines.MODE = ['LFS_A_WRONLY', 'LFS_A_RDWR']
@@ -2378,6 +2520,7 @@ code = '''
#[cases.test_attrs_fattr_zombie_resync] TODO do we test file zombie resync?
#[cases.test_attrs_fattr_pl] ?
#[cases.test_attrs_fattr_orphan] ?