summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/bcache/btree_iter.c20
-rw-r--r--drivers/md/bcache/btree_iter.h1
-rw-r--r--drivers/md/bcache/str_hash.h24
3 files changed, 36 insertions, 9 deletions
diff --git a/drivers/md/bcache/btree_iter.c b/drivers/md/bcache/btree_iter.c
index fb565016e703..f10d8df3ddc7 100644
--- a/drivers/md/bcache/btree_iter.c
+++ b/drivers/md/bcache/btree_iter.c
@@ -721,6 +721,26 @@ void bch_btree_iter_link(struct btree_iter *iter, struct btree_iter *linked)
iter->next = linked;
}
+void bch_btree_iter_copy(struct btree_iter *dst, struct btree_iter *src)
+{
+ bch_btree_iter_unlock(dst);
+
+ dst->level = src->level;
+ dst->is_extents = src->is_extents;
+ dst->btree_id = src->btree_id;
+ dst->pos = src->pos;
+
+ memcpy(dst->lock_seq,
+ src->lock_seq,
+ sizeof(src->lock_seq));
+ memcpy(dst->nodes,
+ src->nodes,
+ sizeof(src->nodes));
+ memcpy(dst->node_iters,
+ src->node_iters,
+ sizeof(src->node_iters));
+}
+
void bch_btree_iter_init_copy(struct btree_iter *dst, struct btree_iter *src)
{
*dst = *src;
diff --git a/drivers/md/bcache/btree_iter.h b/drivers/md/bcache/btree_iter.h
index 2a4b9259804e..5dc6b0aa6e3b 100644
--- a/drivers/md/bcache/btree_iter.h
+++ b/drivers/md/bcache/btree_iter.h
@@ -153,6 +153,7 @@ static inline void bch_btree_iter_init_intent(struct btree_iter *iter,
int bch_btree_iter_unlink(struct btree_iter *);
void bch_btree_iter_link(struct btree_iter *, struct btree_iter *);
+void bch_btree_iter_copy(struct btree_iter *, struct btree_iter *);
void bch_btree_iter_init_copy(struct btree_iter *, struct btree_iter *);
static inline struct bpos btree_type_successor(enum btree_id id,
diff --git a/drivers/md/bcache/str_hash.h b/drivers/md/bcache/str_hash.h
index 08bd12c6ffe7..6bdd9f26c4e6 100644
--- a/drivers/md/bcache/str_hash.h
+++ b/drivers/md/bcache/str_hash.h
@@ -256,6 +256,8 @@ static inline int bch_hash_set(const struct bch_hash_desc desc,
bch_btree_iter_init_intent(&hashed_slot, c, desc.btree_id,
POS(inode, desc.hash_bkey(info, bkey_i_to_s_c(insert))));
+ bch_btree_iter_init_intent(&iter, c, 0, POS_MIN);
+ bch_btree_iter_link(&hashed_slot, &iter);
do {
ret = bch_btree_iter_traverse(&hashed_slot);
@@ -268,13 +270,13 @@ static inline int bch_hash_set(const struct bch_hash_desc desc,
* to recheck the slot we hashed to - it could have been deleted
* while we dropped locks:
*/
- bch_btree_iter_init_copy(&iter, &hashed_slot);
+ bch_btree_iter_copy(&iter, &hashed_slot);
k = bch_hash_lookup_bkey_at(desc, info, &iter,
bkey_i_to_s_c(insert));
if (IS_ERR(k.k)) {
if (flags & BCH_HASH_SET_MUST_REPLACE) {
ret = -ENOENT;
- goto err_unlink;
+ goto err;
}
/*
@@ -283,30 +285,34 @@ static inline int bch_hash_set(const struct bch_hash_desc desc,
* that we could have used, so restart from the
* slot we hashed to:
*/
- bch_btree_iter_unlink(&iter);
- bch_btree_iter_init_copy(&iter, &hashed_slot);
-
+ bch_btree_iter_copy(&iter, &hashed_slot);
k = bch_hash_hole_at(desc, &iter);
if (IS_ERR(k.k)) {
ret = PTR_ERR(k.k);
- goto err_unlink;
+ goto err;
}
} else {
if (flags & BCH_HASH_SET_MUST_CREATE) {
ret = -EEXIST;
- goto err_unlink;
+ goto err;
}
}
insert->k.p = iter.pos;
ret = bch_btree_insert_at(&iter, insert, NULL, NULL,
journal_seq, BTREE_INSERT_ATOMIC);
-err_unlink:
- ret = bch_btree_iter_unlink(&iter) ?: ret;
+ /* On successful insert, we don't want to clobber ret with error
+ * from iter:
+ */
+ bch_btree_iter_unlock(&iter);
} while (ret == -EINTR);
bch_btree_iter_unlock(&hashed_slot);
return ret;
+err:
+ ret = bch_btree_iter_unlock(&iter) ?: ret;
+ ret = bch_btree_iter_unlock(&hashed_slot) ?: ret;
+ return ret;
}
static inline int bch_hash_delete(const struct bch_hash_desc desc,