diff options
-rw-r--r-- | drivers/md/bcache/btree_iter.c | 20 | ||||
-rw-r--r-- | drivers/md/bcache/btree_iter.h | 1 | ||||
-rw-r--r-- | drivers/md/bcache/str_hash.h | 24 |
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, |