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 <zab@versity.com>
This commit is contained in:
Zach Brown
2020-09-18 09:50:31 -07:00
committed by Zach Brown
parent e2a919492d
commit d87e2e0166
5 changed files with 142 additions and 70 deletions

View File

@@ -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);

View File

@@ -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);

97
utils/src/btree.c Normal file
View File

@@ -0,0 +1,97 @@
#include <assert.h>
#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);
}

11
utils/src/btree.h Normal file
View File

@@ -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

View File

@@ -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));