From d87e2e01667343a542e025c2c3dc5c5da426f70c Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 18 Sep 2020 09:50:31 -0700 Subject: [PATCH] scoutfs-utils: add btree insertion for mkfs Use little helpers to insert items into new single block btrees for mkfs. We're about to insert a whole bunch more items. Signed-off-by: Zach Brown --- utils/src/avl.c | 8 ++++ utils/src/avl.h | 2 + utils/src/btree.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++ utils/src/btree.h | 11 ++++++ utils/src/mkfs.c | 94 ++++++++++++--------------------------------- 5 files changed, 142 insertions(+), 70 deletions(-) create mode 100644 utils/src/btree.c create mode 100644 utils/src/btree.h diff --git a/utils/src/avl.c b/utils/src/avl.c index 5faf39e2..3d86c17f 100644 --- a/utils/src/avl.c +++ b/utils/src/avl.c @@ -10,6 +10,14 @@ static struct scoutfs_avl_node *node_ptr(struct scoutfs_avl_root *root, return off ? (void *)root + le16_to_cpu(off) : NULL; } +__le16 avl_node_off(struct scoutfs_avl_root *root, + struct scoutfs_avl_node *node) +{ + if (!node) + return 0; + return cpu_to_le16((void *)node - (void *)root); +} + struct scoutfs_avl_node *avl_first(struct scoutfs_avl_root *root) { struct scoutfs_avl_node *node = node_ptr(root, root->node); diff --git a/utils/src/avl.h b/utils/src/avl.h index 04c921fe..b72e8e3d 100644 --- a/utils/src/avl.h +++ b/utils/src/avl.h @@ -1,6 +1,8 @@ #ifndef _AVL_H_ #define _AVL_H_ +__le16 avl_node_off(struct scoutfs_avl_root *root, + struct scoutfs_avl_node *node); struct scoutfs_avl_node *avl_first(struct scoutfs_avl_root *root); struct scoutfs_avl_node *avl_next(struct scoutfs_avl_root *root, struct scoutfs_avl_node *node); diff --git a/utils/src/btree.c b/utils/src/btree.c new file mode 100644 index 00000000..5cec36bb --- /dev/null +++ b/utils/src/btree.c @@ -0,0 +1,97 @@ +#include + +#include "sparse.h" +#include "util.h" +#include "format.h" +#include "key.h" +#include "avl.h" +#include "leaf_item_hash.h" +#include "btree.h" + +static void init_block(struct scoutfs_btree_block *bt, int level) +{ + int free; + + free = SCOUTFS_BLOCK_LG_SIZE - sizeof(struct scoutfs_btree_block); + if (level == 0) + free -= SCOUTFS_BTREE_LEAF_ITEM_HASH_BYTES; + + bt->level = level; + bt->mid_free_len = cpu_to_le16(free); +} + +/* + * Point the root at the single leaf block that makes up a btree. + */ +void btree_init_root_single(struct scoutfs_btree_root *root, + struct scoutfs_btree_block *bt, + u64 blkno, u64 seq, __le64 fsid) +{ + root->ref.blkno = cpu_to_le64(blkno); + root->ref.seq = cpu_to_le64(1); + root->height = 1; + + memset(bt, 0, SCOUTFS_BLOCK_LG_SIZE); + bt->hdr.magic = cpu_to_le32(SCOUTFS_BLOCK_MAGIC_BTREE); + bt->hdr.fsid = fsid; + bt->hdr.blkno = cpu_to_le64(blkno); + bt->hdr.seq = cpu_to_le64(1); + + init_block(bt, 0); +} + +static void *alloc_val(struct scoutfs_btree_block *bt, int len) +{ + le16_add_cpu(&bt->mid_free_len, -len); + le16_add_cpu(&bt->total_item_bytes, len); + return (void *)bt + le16_to_cpu(bt->mid_free_len); +} + +/* + * Add a sorted item after all the items in the block. + * + * We simply implement the special case of a wildly imbalanced avl tree. + * Mkfs only ever inserts a handful of items and they'll be rebalanced + * over time. + */ +void btree_append_item(struct scoutfs_btree_block *bt, + struct scoutfs_key *key, void *val, int val_len) +{ + struct scoutfs_btree_item *item; + struct scoutfs_avl_node *prev; + __le16 *own_buf; + __le16 own; + void *val_buf; + + item = &bt->items[le16_to_cpu(bt->nr_items)]; + + if (bt->nr_items) { + assert(scoutfs_key_compare(key, &(item - 1)->key) > 0); + prev = &(item - 1)->node; + + item->node.height = prev->height++; + item->node.left = avl_node_off(&bt->item_root, prev); + prev->parent = avl_node_off(&bt->item_root, &item->node); + } + + bt->item_root.node = avl_node_off(&bt->item_root, &item->node); + le16_add_cpu(&bt->nr_items, 1); + le16_add_cpu(&bt->mid_free_len, + -(u16)sizeof(struct scoutfs_btree_item)); + le16_add_cpu(&bt->total_item_bytes, sizeof(struct scoutfs_btree_item)); + + item->key = *key; + leaf_item_hash_insert(bt, &item->key, + cpu_to_le16((void *)item - (void *)bt)); + if (val_len == 0) + return; + + own_buf = alloc_val(bt, SCOUTFS_BTREE_VAL_OWNER_BYTES); + own = cpu_to_le16((void *)item - (void *)bt); + memcpy(own_buf, &own, sizeof(own)); + + val_buf = alloc_val(bt, val_len); + item->val_off = cpu_to_le16((void *)val_buf - (void *)bt); + item->val_len = cpu_to_le16(val_len); + memcpy(val_buf, val, val_len); +} diff --git a/utils/src/btree.h b/utils/src/btree.h new file mode 100644 index 00000000..1f176a8b --- /dev/null +++ b/utils/src/btree.h @@ -0,0 +1,11 @@ +#ifndef _BTREE_H_ +#define _BTREE_H_ + +void btree_init_root_single(struct scoutfs_btree_root *root, + struct scoutfs_btree_block *bt, + u64 blkno, u64 seq, __le64 fsid); + +void btree_append_item(struct scoutfs_btree_block *bt, + struct scoutfs_key *key, void *val, int val_len); + +#endif diff --git a/utils/src/mkfs.c b/utils/src/mkfs.c index eddf01e5..373de609 100644 --- a/utils/src/mkfs.c +++ b/utils/src/mkfs.c @@ -27,6 +27,7 @@ #include "key.h" #include "bitops.h" #include "radix.h" +#include "btree.h" #include "leaf_item_hash.h" static int write_raw_block(int fd, u64 blkno, int shift, void *blk) @@ -281,14 +282,11 @@ out: static int write_new_fs(char *path, int fd, u8 quorum_count) { struct scoutfs_super_block *super; - struct scoutfs_inode *inode; + struct scoutfs_inode inode; struct scoutfs_btree_block *bt; - struct scoutfs_btree_item *btitem; - struct scoutfs_avl_node *par; - struct scoutfs_key *key; + struct scoutfs_key key; struct timeval tv; char uuid_str[37]; - __le16 *own; void *zeros; u64 blkno; u64 limit; @@ -356,75 +354,31 @@ static int write_new_fs(char *path, int fd, u8 quorum_count) /* fs root starts with root inode and its index items */ blkno = next_meta++; + btree_init_root_single(&super->fs_root, bt, blkno, 1, super->hdr.fsid); - super->fs_root.ref.blkno = cpu_to_le64(blkno); - super->fs_root.ref.seq = cpu_to_le64(1); - super->fs_root.height = 1; + memset(&key, 0, sizeof(key)); + key.sk_zone = SCOUTFS_INODE_INDEX_ZONE; + key.sk_type = SCOUTFS_INODE_INDEX_META_SEQ_TYPE; + key.skii_ino = cpu_to_le64(SCOUTFS_ROOT_INO); + btree_append_item(bt, &key, NULL, 0); - memset(bt, 0, SCOUTFS_BLOCK_LG_SIZE); - bt->hdr.fsid = super->hdr.fsid; - bt->hdr.blkno = cpu_to_le64(blkno); - bt->hdr.seq = cpu_to_le64(1); + memset(&key, 0, sizeof(key)); + key.sk_zone = SCOUTFS_FS_ZONE; + key.ski_ino = cpu_to_le64(SCOUTFS_ROOT_INO); + key.sk_type = SCOUTFS_INODE_TYPE; - /* meta seq index for the root inode */ - btitem = &bt->items[le16_to_cpu(bt->nr_items)]; - le16_add_cpu(&bt->nr_items, 1); - key = &btitem->key; + memset(&inode, 0, sizeof(inode)); + inode.next_readdir_pos = cpu_to_le64(2); + inode.nlink = cpu_to_le32(SCOUTFS_DIRENT_FIRST_POS); + inode.mode = cpu_to_le32(0755 | 0040000); + inode.atime.sec = cpu_to_le64(tv.tv_sec); + inode.atime.nsec = cpu_to_le32(tv.tv_usec * 1000); + inode.ctime.sec = inode.atime.sec; + inode.ctime.nsec = inode.atime.nsec; + inode.mtime.sec = inode.atime.sec; + inode.mtime.nsec = inode.atime.nsec; + btree_append_item(bt, &key, &inode, sizeof(inode)); - bt->item_root.node = cpu_to_le16((void *)&btitem->node - - (void *)&bt->item_root); - btitem->node.height = 2; - btitem->val_len = cpu_to_le16(0); - - key->sk_zone = SCOUTFS_INODE_INDEX_ZONE; - key->sk_type = SCOUTFS_INODE_INDEX_META_SEQ_TYPE; - key->skii_ino = cpu_to_le64(SCOUTFS_ROOT_INO); - - leaf_item_hash_insert(bt, &btitem->key, - cpu_to_le16((void *)btitem - (void *)bt)); - - /* root inode */ - par = &btitem->node; - btitem = &bt->items[le16_to_cpu(bt->nr_items)]; - le16_add_cpu(&bt->nr_items, 1); - key = &btitem->key; - own = (void *)bt + SCOUTFS_BLOCK_LG_SIZE - - SCOUTFS_BTREE_LEAF_ITEM_HASH_BYTES - - SCOUTFS_BTREE_VAL_OWNER_BYTES; - inode = (void *)own - sizeof(*inode); - - par->right = cpu_to_le16((void *)&btitem->node - - (void *)&bt->item_root); - btitem->node.height = 1; - btitem->node.parent = cpu_to_le16((void *)par - (void *)&bt->item_root); - btitem->val_off = cpu_to_le16((void *)inode - (void *)bt); - btitem->val_len = cpu_to_le16(sizeof(*inode)); - le16_add_cpu(&bt->total_item_bytes, le16_to_cpu(btitem->val_len) + - SCOUTFS_BTREE_VAL_OWNER_BYTES); - - key->sk_zone = SCOUTFS_FS_ZONE; - key->ski_ino = cpu_to_le64(SCOUTFS_ROOT_INO); - key->sk_type = SCOUTFS_INODE_TYPE; - - inode->next_readdir_pos = cpu_to_le64(2); - inode->nlink = cpu_to_le32(SCOUTFS_DIRENT_FIRST_POS); - inode->mode = cpu_to_le32(0755 | 0040000); - inode->atime.sec = cpu_to_le64(tv.tv_sec); - inode->atime.nsec = cpu_to_le32(tv.tv_usec * 1000); - inode->ctime.sec = inode->atime.sec; - inode->ctime.nsec = inode->atime.nsec; - inode->mtime.sec = inode->atime.sec; - inode->mtime.nsec = inode->atime.nsec; - - leaf_item_hash_insert(bt, &btitem->key, - cpu_to_le16((void *)btitem - (void *)bt)); - *own = cpu_to_le16((void *)btitem - (void *)bt); - - le16_add_cpu(&bt->total_item_bytes, le16_to_cpu(bt->nr_items) * - sizeof(struct scoutfs_btree_item)); - bt->mid_free_len = cpu_to_le16((void *)inode - - (void *)&bt->items[le16_to_cpu(bt->nr_items)]); - bt->hdr.magic = cpu_to_le32(SCOUTFS_BLOCK_MAGIC_BTREE); bt->hdr.crc = cpu_to_le32(crc_block(&bt->hdr, SCOUTFS_BLOCK_LG_SIZE));