From 43d416003a0502513d6b50187c46e1e1b1acdb01 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Thu, 24 Oct 2019 15:54:35 -0700 Subject: [PATCH] scoutfs: add scoutfs_btree_force Add a btree_update variant which will insert the item if a previous wasn't found instead of returning -ENOENT. This saves callers from having to lookup befure updating to discover if they should call _create or _update. Signed-off-by: Zach Brown --- kmod/src/btree.c | 34 ++++++++++++++++++++++++++++++++++ kmod/src/btree.h | 6 ++++++ 2 files changed, 40 insertions(+) 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,