WIP radix-based lfs_dir_getattr

This commit is contained in:
Christopher Haster
2021-01-15 00:22:33 -06:00
parent 907b76fef3
commit a8dce05bbc
2 changed files with 169 additions and 54 deletions
+136 -34
View File
@@ -15,7 +15,6 @@ static inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) {
// do not zero, cheaper if cache is readonly or only going to be
// written with identical data (during relocates)
(void)lfs;
int heh;
rcache->block = LFS_BLOCK_NULL;
}
@@ -2550,6 +2549,105 @@ lfs_ssize_t lfs_bd_progtag_(lfs_t *lfs,
return hdiff;
}
// TODO name dir->mdir for these low-level operations?
// TODO I don't think a mask works anymore, do we need this?
lfs_stag_t lfs_dir_getattrslice_(lfs_t *lfs, lfs_mdir__t *mdir,
lfs_tag_t tag, lfs_off_t off, void *buffer, lfs_size_t size,
lfs_size_t *pnsize) {
// it doesn't make sense to look up a non-radix-tree tag
LFS_ASSERT(lfs_tag_isradix_(tag));
// TODO handle synthetic move
lfs_off_t roff = mdir->roff;
int bit = 28; // tag only uses the lower 28-bits
// iterate through tags
while (bit >= 0) {
lfs_tag_t rtag;
lfs_off_t rsize;
lfs_ssize_t rdiff = lfs_bd_readtag_(lfs,
NULL, &lfs->rcache, 2*sizeof(uint32_t),
mdir->pair[0], roff, &rtag, &rsize);
if (rdiff < 0) {
return rdiff;
}
// TODO handle splices
printf("%08x: rtag %08x %08x %08x\n", roff, rtag, (1 << bit), rsize);
// found tag?
if (tag == rtag) {
lfs_size_t diff = 0;
if (off < rsize) {
diff = lfs_min(size, rsize-off);
int err = lfs_bd_read(lfs,
NULL, &lfs->rcache, diff,
mdir->pair[0], roff+rdiff+off, buffer, diff);
if (err) {
return err;
}
}
if (pnsize) {
*pnsize = diff;
}
return rtag;
}
// TODO better way to handle offsets?
rdiff += rsize;
// iterate through alt-pointers
while (bit >= 0) {
lfs_tag_t ralt;
lfs_off_t nroff;
// TODO are hints correct both here and commit?
lfs_soff_t res = lfs_bd_readtag_(lfs,
NULL, &lfs->rcache, 2*sizeof(uint32_t),
mdir->pair[0], roff+rdiff, &ralt, &nroff);
if (res < 0) {
return res;
}
rdiff += res;
// iterate through bits
while (bit >= 0) {
if (lfs_tag_isalt_(ralt) &&
lfs_tag_alt_(ralt) > bit) {
// need new alt-pointer
goto next_alt;
}
if ((tag ^ rtag) & (1 << bit)) {
if (lfs_tag_isalt_(ralt) &&
lfs_tag_alt_(ralt) == bit) {
// follow alt-pointer
roff = nroff;
bit -= 1;
goto next_tag;
} else {
goto done;
}
}
// next bit
bit -= 1;
}
next_alt:;
}
next_tag:;
}
done:;
// not found
return LFS_ERR_NOENT;
}
lfs_ssize_t lfs_dir_getattr_(lfs_t *lfs, lfs_mdir__t *mdir,
lfs_tag_t tag, void *buffer, lfs_size_t size, lfs_size_t *nsize) {
return lfs_dir_getattrslice_(lfs, mdir, tag, 0, buffer, size, nsize);
}
// TODO should we just take mdir pointer? to a copy? we're carrying
// around a lot of state
@@ -2612,9 +2710,9 @@ lfs_ssize_t lfs_dir_commitattr_(lfs_t *lfs, lfs_off_t *proff,
//printf("finding radices for 0x%08x!\n", tag);
lfs_off_t roff = *proff;
// tags use only the lower 28-bits
for (int i = 0; i < 28 && roff; i++) {
// first get tag
int bit = 28; // tags use only the lower 28-bits
// iterate through tags
while (bit >= 0) {
lfs_tag_t rtag;
lfs_off_t rsize;
lfs_ssize_t res = lfs_bd_readtag_(lfs,
@@ -2625,8 +2723,8 @@ lfs_ssize_t lfs_dir_commitattr_(lfs_t *lfs, lfs_off_t *proff,
}
lfs_ssize_t rdiff = res + rsize;
while (true) {
// and alt-pointer
// iterate through alt-pointers
while (bit >= 0) {
lfs_tag_t ralt;
lfs_off_t nroff;
res = lfs_bd_readtag_(lfs,
@@ -2638,53 +2736,54 @@ lfs_ssize_t lfs_dir_commitattr_(lfs_t *lfs, lfs_off_t *proff,
rdiff += res;
// iterate through bits
for (; i < 28; i++) {
if ((tag ^ rtag) & (1 << (28-i))) {
while (bit >= 0) {
if ((tag ^ rtag) & (1 << bit)) {
// different bit, new alt-pointer
res = lfs_bd_progtag_(lfs,
&lfs->pcache, &lfs->rcache, limit, crc,
block, off+diff, LFS_MKALT_(28-i), roff);
block, off+diff, LFS_MKALT_(bit), roff);
if (res < 0) {
return res;
}
diff += res;
} else if (lfs_tag_isalt_(ralt) &&
lfs_tag_alt_(ralt) == bit) {
// same bit, copy alt-pointer
res = lfs_bd_progtag_(lfs,
&lfs->pcache, &lfs->rcache, limit, crc,
block, off+diff, ralt, nroff);
if (res < 0) {
return res;
}
diff += res;
}
// follow alt-pointer?
if (lfs_tag_isalt_(ralt) &&
lfs_tag_alt_(ralt) > bit) {
// need new alt-pointer
goto next_alt;
}
if ((tag ^ rtag) & (1 << bit)) {
if (lfs_tag_isalt_(ralt) &&
lfs_tag_alt_(ralt) == 28-i) {
lfs_tag_alt_(ralt) == bit) {
// follow alt-pointer
roff = nroff;
bit -= 1;
goto next_tag;
} else {
roff = 0;
goto next_tag;
}
} else {
// same bit, copy alt-pointer
if (lfs_tag_isalt_(ralt) &&
lfs_tag_alt_(ralt) == 28-i) {
//printf("copy alt 0x%08x 0x%08x\n", LFS_MKALT_(28-i), roff);
res = lfs_bd_progtag_(lfs,
&lfs->pcache, &lfs->rcache, limit, crc,
block, off+diff, ralt, nroff);
if (res < 0) {
return res;
}
diff += res;
}
if (lfs_tag_isalt_(ralt) &&
lfs_tag_alt_(ralt) > 28-i) {
// need new alt-pointer
goto next_alt;
goto done;
}
}
// next bit
bit -= 1;
}
next_alt:;
}
next_tag:;
}
done:;
*proff = off;
}
@@ -2968,6 +3067,9 @@ relocate:
LFS_ASSERT(false); // TODO
}
// TODO finish commit?
lfs_pair_swap(mdir->pair);
return 0;
}
+33 -20
View File
@@ -15,24 +15,37 @@ code = '''
.tail = {0xffffffff, 0xffffffff},
};
lfs_dir_compact_(&lfs, &mdir, LFS_MKATTRS_(
{LFS_MKTAG_(LFS_T_USERATTR, 0, 0), "0000", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 01, 0), "0001", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 2, 0), "0002", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 3, 0), "0003", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 4, 0), "0004", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 5, 0), "0005", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 6, 0), "0006", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 7, 0), "0007", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 8, 0), "0008", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 9, 0), "0009", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 10, 0), "0010", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 11, 0), "0011", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 12, 0), "0012", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 13, 0), "0013", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 14, 0), "0014", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 15, 0), "0015", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 0xaa, 0xaaaa), "0015", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 0xcc, 0xcccc), "0015", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 0xff, 0xffff), "0016", 4})) => 0;
struct lfs_mattr_ attrs[] = {
{LFS_MKTAG_(LFS_T_USERATTR, 0, 0), "0000", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 1, 0), "0001", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 2, 0), "0002", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 3, 0), "0003", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 4, 0), "0004", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 5, 0), "0005", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 6, 0), "0006", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 7, 0), "0007", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 8, 0), "0008", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 9, 0), "0009", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 10, 0), "0010", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 11, 0), "0011", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 12, 0), "0012", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 13, 0), "0013", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 14, 0), "0014", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 15, 0), "0015", 4},
{LFS_MKTAG_(LFS_T_USERATTR, 16, 0), "0016", 4}
};
lfs_size_t attr_count = sizeof(attrs)/sizeof(attrs[0]);
lfs_dir_compact_(&lfs, &mdir, attrs, attr_count) => 0;
for (lfs_size_t i = 0; i < attr_count; i++) {
printf("looking up %08x\n", attrs[i].tag);
lfs_size_t nsize;
lfs_dir_getattr_(&lfs, &mdir,
attrs[i].tag,
buffer, sizeof(buffer), &nsize) => attrs[i].tag;
assert(nsize == attrs[i].size);
assert(memcmp(buffer, attrs[i].buffer, attrs[i].size) == 0);
}
'''