mirror of
https://github.com/versity/scoutfs.git
synced 2026-02-11 04:51:08 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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
97
utils/src/btree.c
Normal 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
11
utils/src/btree.h
Normal 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
|
||||
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user