diff --git a/kmod/src/btree.c b/kmod/src/btree.c index c8919c52..936de009 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -1115,6 +1115,40 @@ int scoutfs_btree_update(struct super_block *sb, return ret; } +/* + * Create an item, overwriting any item that might exist. It's _update + * which will insert instead of returning -ENOENT. + */ +int scoutfs_btree_force(struct super_block *sb, + struct scoutfs_balloc_allocator *alloc, + struct scoutfs_block_writer *wri, + struct scoutfs_btree_root *root, + void *key, unsigned key_len, + void *val, unsigned val_len) +{ + struct scoutfs_btree_block *bt; + struct scoutfs_block *bl; + int pos; + int cmp; + int ret; + + if (invalid_item(key, key_len, val_len)) + return -EINVAL; + + ret = btree_walk(sb, alloc, wri, root, BTW_DIRTY | BTW_INSERT, + key, key_len, val_len, &bl, NULL, NULL); + if (ret == 0) { + bt = bl->data; + pos = find_pos(bt, key, key_len, &cmp); + if (cmp == 0) + delete_item(bt, pos); + create_item(bt, pos, key, key_len, val, val_len); + scoutfs_block_put(sb, bl); + } + + return ret; +} + /* * Delete an item from the tree. -ENOENT is returned if the key isn't * found. diff --git a/kmod/src/btree.h b/kmod/src/btree.h index d56b2f3e..9278cec8 100644 --- a/kmod/src/btree.h +++ b/kmod/src/btree.h @@ -35,6 +35,12 @@ int scoutfs_btree_update(struct super_block *sb, struct scoutfs_btree_root *root, void *key, unsigned key_len, void *val, unsigned val_len); +int scoutfs_btree_force(struct super_block *sb, + struct scoutfs_balloc_allocator *alloc, + struct scoutfs_block_writer *wri, + struct scoutfs_btree_root *root, + void *key, unsigned key_len, + void *val, unsigned val_len); int scoutfs_btree_delete(struct super_block *sb, struct scoutfs_balloc_allocator *alloc, struct scoutfs_block_writer *wri,