mirror of
https://github.com/versity/scoutfs.git
synced 2026-09-08 17:17:13 +00:00
scoutfs: add btree methods for item cache
Add btree calls to call a callback for all items in a leaf, and to insert a list of items into their leaf blocks. These will be used by the item cache to populate the cache and to write dirty items into dirty btree blocks. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -1780,3 +1780,107 @@ int scoutfs_btree_dirty(struct super_block *sb,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the users callback on all the items in the leaf that we find.
|
||||
* We also set the caller's keys for the first and last possible keys
|
||||
* that could exist in the leaf block.
|
||||
*/
|
||||
int scoutfs_btree_read_items(struct super_block *sb,
|
||||
struct scoutfs_btree_root *root,
|
||||
struct scoutfs_key *key,
|
||||
struct scoutfs_key *start,
|
||||
struct scoutfs_key *end,
|
||||
scoutfs_btree_item_cb cb, void *arg)
|
||||
{
|
||||
struct scoutfs_btree_item *item;
|
||||
struct scoutfs_btree_block *bt;
|
||||
struct scoutfs_avl_node *next_node;
|
||||
struct scoutfs_avl_node *node;
|
||||
struct btree_walk_key_range kr;
|
||||
struct scoutfs_block *bl;
|
||||
int ret;
|
||||
|
||||
ret = btree_walk(sb, NULL, NULL, root, 0, key, 0, &bl, &kr);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
bt = bl->data;
|
||||
|
||||
if (scoutfs_key_compare(&kr.start, start) > 0)
|
||||
*start = kr.start;
|
||||
if (scoutfs_key_compare(&kr.end, end) < 0)
|
||||
*end = kr.end;
|
||||
|
||||
node = scoutfs_avl_search(&bt->item_root, cmp_key_item, start, NULL,
|
||||
NULL, &next_node, NULL) ?: next_node;
|
||||
while (node) {
|
||||
item = node_item(node);
|
||||
if (scoutfs_key_compare(&item->key, end) > 0)
|
||||
break;
|
||||
|
||||
ret = cb(sb, item_key(item), item_val(bt, item),
|
||||
item_val_len(item), arg);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
node = scoutfs_avl_next(&bt->item_root, node);
|
||||
}
|
||||
|
||||
scoutfs_block_put(sb, bl);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller has a sorted list of items to insert. We find the leaf
|
||||
* block that contains each item and either overwrite or insert the
|
||||
* caller's item. This has no mechanism for deleting items.
|
||||
*
|
||||
* This can make partial progress before returning an error, leaving
|
||||
* dirty btree blocks with only some of the caller's items. It's up to
|
||||
* the caller to resolve this.
|
||||
*/
|
||||
int scoutfs_btree_insert_list(struct super_block *sb,
|
||||
struct scoutfs_radix_allocator *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_btree_root *root,
|
||||
struct scoutfs_btree_item_list *lst)
|
||||
{
|
||||
struct scoutfs_btree_item *item;
|
||||
struct btree_walk_key_range kr;
|
||||
struct scoutfs_btree_block *bt;
|
||||
struct scoutfs_avl_node *par;
|
||||
struct scoutfs_block *bl;
|
||||
int cmp;
|
||||
int ret = 0;
|
||||
|
||||
while (lst) {
|
||||
ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT,
|
||||
&lst->key, lst->val_len, &bl, &kr);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
bt = bl->data;
|
||||
|
||||
do {
|
||||
item = leaf_item_hash_search(sb, bt, &lst->key);
|
||||
if (item) {
|
||||
update_item_value(bt, item, lst->val,
|
||||
lst->val_len);
|
||||
} else {
|
||||
scoutfs_avl_search(&bt->item_root,
|
||||
cmp_key_item, &lst->key,
|
||||
&cmp, &par, NULL, NULL);
|
||||
create_item(bt, &lst->key, lst->val,
|
||||
lst->val_len, par, cmp);
|
||||
}
|
||||
|
||||
lst = lst->next;
|
||||
} while (lst && scoutfs_key_compare(&lst->key, &kr.end) <= 0 &&
|
||||
mid_free_item_room(bt, lst->val_len));
|
||||
|
||||
scoutfs_block_put(sb, bl);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,18 @@ struct scoutfs_btree_item_ref {
|
||||
#define SCOUTFS_BTREE_ITEM_REF(name) \
|
||||
struct scoutfs_btree_item_ref name = {NULL,}
|
||||
|
||||
/* caller gives an item to the callback */
|
||||
typedef int (*scoutfs_btree_item_cb)(struct super_block *sb,
|
||||
struct scoutfs_key *key,
|
||||
void *val, int val_len, void *arg);
|
||||
|
||||
/* simple singly-linked list of items */
|
||||
struct scoutfs_btree_item_list {
|
||||
struct scoutfs_btree_item_list *next;
|
||||
struct scoutfs_key key;
|
||||
int val_len;
|
||||
u8 val[0];
|
||||
};
|
||||
|
||||
int scoutfs_btree_lookup(struct super_block *sb,
|
||||
struct scoutfs_btree_root *root,
|
||||
@@ -58,6 +70,18 @@ int scoutfs_btree_dirty(struct super_block *sb,
|
||||
struct scoutfs_btree_root *root,
|
||||
struct scoutfs_key *key);
|
||||
|
||||
int scoutfs_btree_read_items(struct super_block *sb,
|
||||
struct scoutfs_btree_root *root,
|
||||
struct scoutfs_key *key,
|
||||
struct scoutfs_key *start,
|
||||
struct scoutfs_key *end,
|
||||
scoutfs_btree_item_cb cb, void *arg);
|
||||
int scoutfs_btree_insert_list(struct super_block *sb,
|
||||
struct scoutfs_radix_allocator *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_btree_root *root,
|
||||
struct scoutfs_btree_item_list *lst);
|
||||
|
||||
void scoutfs_btree_put_iref(struct scoutfs_btree_item_ref *iref);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user