Initial groundwork for rbyd trees

- primitive lfs_rbyd_fetch
- primitive lfs_rbyd_commit
- tag reading/progging and encoding machinery

The tag encoding scheme here uses pairs of leb128s, encoding either
a normal tag:

  iiii iiiiiii iiiiiTT TTTTTTt ttttt0v
                   ^--------^------^-^- 16-bit id
                            '------|-|- 8-bit type2
                                   '-|- 6-bit type1
                                     '- valid bit
  llll lllllll lllllll lllllll lllllll
                                     ^- n-bit length

Or an alt pointer:

  wwww wwwwwww wwwwwww wwwwwww wwwcd1v
                                 ^^^-^- 28-bit weight
                                  '|-|- color bit
                                   '-|- direction bit
                                     '- valid bit
  jjjj jjjjjjj jjjjjjj jjjjjjj jjjjjjj
                                     ^- n-bit jump

Note that two bits overlap the alt pointer dir/color encoding, this
is actually not a problem at all since some tags (crcs/fcrcs) don't
participate in the rbyd tree and can use these bits.

There's a number of benefits to using leb128s, which should probably
be written about, most notably is the abstraction of the device's
word-size. The "n-bits" above can be whatever word size works on the
device, trading off code-size for storage capabilities without breaking
compatibility with other devices. This will eventually be negotiated via
the superblock.
This commit is contained in:
Christopher Haster
2022-12-20 00:26:43 -06:00
parent 37dcee8868
commit 2802880eaa
5 changed files with 943 additions and 0 deletions
+39
View File
@@ -10,6 +10,45 @@
// Only compile if user does not provide custom config
#ifndef LFS_CONFIG
// Need lfs.h for error codes
// TODO should we actually move the error codes to lfs_util.h?
#include "lfs.h"
// Convert to/from leb128 encoding
ssize_t lfs_toleb128(uint32_t word, void *buffer, size_t size) {
uint8_t *data = buffer;
for (size_t i = 0; i < size; i++) {
uint8_t dat = word & 0x7f;
word >>= 7;
if (word != 0) {
data[i] = dat | 0x80;
} else {
data[i] = dat | 0x00;
return i+1;
}
}
return LFS_ERR_OVERFLOW;
}
ssize_t lfs_fromleb128(uint32_t *word, const void *buffer, size_t size) {
const uint8_t *data = buffer;
uint32_t word_ = 0;
for (size_t i = 0; i < size; i++) {
uint8_t dat = data[i];
word_ |= (dat & 0x7f) << 7*i;
if (!(dat & 0x80)) {
*word = word_;
return i+1;
}
}
return LFS_ERR_OVERFLOW;
}
// Software CRC implementation with small lookup table
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {