scoutfs-utils: support btree avl and hash

Update the internal structure of btree blocks to use the avl item index
and hash table direct item lookup.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2020-08-26 14:39:28 -07:00
committed by Zach Brown
parent aa84f7c601
commit b86a1bebbb
7 changed files with 237 additions and 52 deletions
+35 -26
View File
@@ -184,26 +184,22 @@ struct scoutfs_radix_root {
~(__u64)SCOUTFS_RADIX_LG_MASK)
#define SCOUTFS_RADIX_BITS_BYTES (SCOUTFS_RADIX_BITS / 8)
struct scoutfs_avl_root {
__le16 node;
} __packed;
struct scoutfs_avl_node {
__le16 parent;
__le16 left;
__le16 right;
__u8 height;
} __packed;
/* when we split we want to have multiple items on each side */
#define SCOUTFS_BTREE_MAX_VAL_LEN (SCOUTFS_BLOCK_SIZE / 8)
#define SCOUTFS_BTREE_MAX_VAL_LEN 512
/*
* The min number of free bytes we must leave in a parent as we descend
* to modify. This guarantees enough free bytes in a parent to insert a
* new child reference item as a child block splits.
*/
#define SCOUTFS_BTREE_PARENT_MIN_FREE_BYTES \
(sizeof(struct scoutfs_btree_item_header) + \
sizeof(struct scoutfs_btree_item) + \
sizeof(struct scoutfs_btree_ref))
/*
* When debugging we can tune the splitting and merging thresholds to
* create much larger trees by having blocks with many fewer items. We
* implement this by pretending the blocks are tiny. They're still
* large enough for a handful of items.
*/
#define SCOUTFS_BTREE_TINY_BLOCK_SIZE 512
/* each value ends with an offset which lets compaction iterate over values */
#define SCOUTFS_BTREE_VAL_OWNER_BYTES sizeof(__le16)
/*
* A 4EB test image measured a worst case height of 17. This is plenty
@@ -225,24 +221,37 @@ struct scoutfs_btree_root {
__u8 height;
} __packed;
struct scoutfs_btree_item_header {
__le32 off;
} __packed;
struct scoutfs_btree_item {
struct scoutfs_avl_node node;
struct scoutfs_key key;
__le16 val_off;
__le16 val_len;
__u8 val[0];
} __packed;
struct scoutfs_btree_block {
struct scoutfs_block_header hdr;
__le32 free_end;
__le32 nr_items;
struct scoutfs_avl_root item_root;
__le16 nr_items;
__le16 total_item_bytes;
__le16 mid_free_len;
__le16 last_free_off;
__le16 last_free_len;
__u8 level;
struct scoutfs_btree_item_header item_hdrs[0];
struct scoutfs_btree_item items[0];
/* leaf blocks have a fixed size item offset hash table at the end */
} __packed;
/*
* Try to aim for a 75% load in a leaf full of items with no value.
* We'll almost never see this because most items have values and most
* blocks aren't full.
*/
#define SCOUTFS_BTREE_LEAF_ITEM_HASH_NR \
((SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_btree_block)) / \
(sizeof(struct scoutfs_btree_item) + (sizeof(__le16))) * 100 / 75)
#define SCOUTFS_BTREE_LEAF_ITEM_HASH_BYTES \
(SCOUTFS_BTREE_LEAF_ITEM_HASH_NR * sizeof(__le16))
struct scoutfs_mounted_client_btree_val {
__u8 flags;
} __packed;