summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-06-04 00:29:49 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-06-10 13:22:54 -0400
commit22dff78704b9e9e2c8539c4c0dc1a861241e8f26 (patch)
tree927231f851f1816b2ccf8c05e3d080635c34a1c3
parentf2309daa61179e07b02ba9dad80986cce376bc33 (diff)
bcachefs: BTREE_ITER_WITH_UPDATES
This drops bch2_btree_iter_peek_with_updates() and replaces it with a new flag, BTREE_ITER_WITH_UPDATES, and also reworks bch2_btree_iter_peek_slot() to respect it too. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/btree_iter.c177
-rw-r--r--fs/bcachefs/btree_iter.h3
-rw-r--r--fs/bcachefs/btree_types.h13
-rw-r--r--fs/bcachefs/btree_update_leaf.c12
4 files changed, 99 insertions, 106 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 9c19b5fd5a83..830a6de02110 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -857,10 +857,9 @@ static inline struct bkey_s_c __btree_iter_unpack(struct btree_iter *iter,
/* peek_all() doesn't skip deleted keys */
static inline struct bkey_s_c btree_iter_level_peek_all(struct btree_iter *iter,
- struct btree_iter_level *l,
- struct bkey *u)
+ struct btree_iter_level *l)
{
- return __btree_iter_unpack(iter, l, u,
+ return __btree_iter_unpack(iter, l, &iter->k,
bch2_btree_node_iter_peek_all(&l->iter, l->b));
}
@@ -1644,15 +1643,18 @@ static inline bool btree_iter_set_pos_to_prev_leaf(struct btree_iter *iter)
return ret;
}
-static struct bkey_i *btree_trans_peek_updates(struct btree_trans *trans,
- enum btree_id btree_id, struct bpos pos)
+static inline struct bkey_i *btree_trans_peek_updates(struct btree_iter *iter,
+ struct bpos pos)
{
struct btree_insert_entry *i;
- trans_for_each_update2(trans, i)
- if ((cmp_int(btree_id, i->iter->btree_id) ?:
- bkey_cmp(pos, i->k->k.p)) <= 0) {
- if (btree_id == i->iter->btree_id)
+ if (!(iter->flags & BTREE_ITER_WITH_UPDATES))
+ return NULL;
+
+ trans_for_each_update2(iter->trans, i)
+ if ((cmp_int(iter->btree_id, i->iter->btree_id) ?:
+ bkey_cmp(pos, i->k->k.p)) <= 0) {
+ if (iter->btree_id == i->iter->btree_id)
return i->k;
break;
}
@@ -1660,7 +1662,11 @@ static struct bkey_i *btree_trans_peek_updates(struct btree_trans *trans,
return NULL;
}
-static inline struct bkey_s_c __btree_iter_peek(struct btree_iter *iter, bool with_updates)
+/**
+ * bch2_btree_iter_peek: returns first key greater than or equal to iterator's
+ * current position
+ */
+struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
{
struct bpos search_key = btree_iter_search_key(iter);
struct bkey_i *next_update;
@@ -1671,9 +1677,7 @@ static inline struct bkey_s_c __btree_iter_peek(struct btree_iter *iter, bool wi
bch2_btree_iter_verify(iter);
bch2_btree_iter_verify_entry_exit(iter);
start:
- next_update = with_updates
- ? btree_trans_peek_updates(iter->trans, iter->btree_id, search_key)
- : NULL;
+ next_update = btree_trans_peek_updates(iter, search_key);
btree_iter_set_search_pos(iter, search_key);
while (1) {
@@ -1716,15 +1720,6 @@ start:
}
/**
- * bch2_btree_iter_peek: returns first key greater than or equal to iterator's
- * current position
- */
-struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
-{
- return __btree_iter_peek(iter, false);
-}
-
-/**
* bch2_btree_iter_next: returns first key greater than iterator's current
* position
*/
@@ -1736,19 +1731,6 @@ struct bkey_s_c bch2_btree_iter_next(struct btree_iter *iter)
return bch2_btree_iter_peek(iter);
}
-struct bkey_s_c bch2_btree_iter_peek_with_updates(struct btree_iter *iter)
-{
- return __btree_iter_peek(iter, true);
-}
-
-struct bkey_s_c bch2_btree_iter_next_with_updates(struct btree_iter *iter)
-{
- if (!bch2_btree_iter_advance(iter))
- return bkey_s_c_null;
-
- return bch2_btree_iter_peek_with_updates(iter);
-}
-
/**
* bch2_btree_iter_peek_prev: returns first key less than or equal to
* iterator's current position
@@ -1760,6 +1742,7 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
int ret;
EBUG_ON(btree_iter_type(iter) != BTREE_ITER_KEYS);
+ EBUG_ON(iter->flags & BTREE_ITER_WITH_UPDATES);
bch2_btree_iter_verify(iter);
bch2_btree_iter_verify_entry_exit(iter);
@@ -1821,52 +1804,9 @@ struct bkey_s_c bch2_btree_iter_prev(struct btree_iter *iter)
return bch2_btree_iter_peek_prev(iter);
}
-static inline struct bkey_s_c
-__bch2_btree_iter_peek_slot_extents(struct btree_iter *iter)
-{
- struct bkey_s_c k;
- struct bpos pos, next_start;
-
- /* keys & holes can't span inode numbers: */
- if (iter->pos.offset == KEY_OFFSET_MAX) {
- if (iter->pos.inode == KEY_INODE_MAX)
- return bkey_s_c_null;
-
- bch2_btree_iter_set_pos(iter, bkey_successor(iter, iter->pos));
- }
-
- pos = iter->pos;
- k = bch2_btree_iter_peek(iter);
- iter->pos = pos;
-
- if (bkey_err(k))
- return k;
-
- if (k.k && bkey_cmp(bkey_start_pos(k.k), iter->pos) <= 0)
- return k;
-
- next_start = k.k ? bkey_start_pos(k.k) : POS_MAX;
-
- bkey_init(&iter->k);
- iter->k.p = iter->pos;
- bch2_key_resize(&iter->k,
- min_t(u64, KEY_SIZE_MAX,
- (next_start.inode == iter->pos.inode
- ? next_start.offset
- : KEY_OFFSET_MAX) -
- iter->pos.offset));
-
- EBUG_ON(!iter->k.size);
-
- bch2_btree_iter_verify_entry_exit(iter);
- bch2_btree_iter_verify(iter);
-
- return (struct bkey_s_c) { &iter->k, NULL };
-}
-
struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
{
- struct btree_iter_level *l = &iter->l[0];
+ struct bpos search_key = btree_iter_search_key(iter);
struct bkey_s_c k;
int ret;
@@ -1874,24 +1814,78 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
bch2_btree_iter_verify(iter);
bch2_btree_iter_verify_entry_exit(iter);
- btree_iter_set_search_pos(iter, btree_iter_search_key(iter));
+ btree_iter_set_search_pos(iter, search_key);
- if (iter->flags & BTREE_ITER_IS_EXTENTS)
- return __bch2_btree_iter_peek_slot_extents(iter);
+ /* extents can't span inode numbers: */
+ if ((iter->flags & BTREE_ITER_IS_EXTENTS) &&
+ iter->pos.offset == KEY_OFFSET_MAX) {
+ if (iter->pos.inode == KEY_INODE_MAX)
+ return bkey_s_c_null;
+
+ bch2_btree_iter_set_pos(iter, bpos_nosnap_successor(iter->pos));
+ }
ret = btree_iter_traverse(iter);
if (unlikely(ret))
return bkey_s_c_err(ret);
- k = btree_iter_level_peek_all(iter, l, &iter->k);
+ if (!(iter->flags & BTREE_ITER_IS_EXTENTS)) {
+ struct bkey_i *next_update = btree_trans_peek_updates(iter, search_key);
- EBUG_ON(k.k && bkey_deleted(k.k) && bkey_cmp(k.k->p, iter->pos) == 0);
+ k = btree_iter_level_peek_all(iter, &iter->l[0]);
+ EBUG_ON(k.k && bkey_deleted(k.k) && bkey_cmp(k.k->p, iter->pos) == 0);
- if (!k.k || bkey_cmp(iter->pos, k.k->p)) {
- /* hole */
- bkey_init(&iter->k);
- iter->k.p = iter->pos;
- k = (struct bkey_s_c) { &iter->k, NULL };
+ if (next_update &&
+ (!k.k || bpos_cmp(next_update->k.p, k.k->p) <= 0)) {
+ iter->k = next_update->k;
+ k = bkey_i_to_s_c(next_update);
+ }
+ } else {
+ if ((iter->flags & BTREE_ITER_INTENT)) {
+ struct btree_iter *child =
+ btree_iter_child_alloc(iter, _THIS_IP_);
+
+ btree_iter_copy(child, iter);
+ k = bch2_btree_iter_peek(child);
+
+ if (k.k && !bkey_err(k))
+ iter->k = child->k;
+ } else {
+ struct bpos pos = iter->pos;
+
+ k = bch2_btree_iter_peek(iter);
+ iter->pos = pos;
+ }
+
+ if (unlikely(bkey_err(k)))
+ return k;
+ }
+
+ if (!(iter->flags & BTREE_ITER_IS_EXTENTS)) {
+ if (!k.k ||
+ ((iter->flags & BTREE_ITER_ALL_SNAPSHOTS)
+ ? bpos_cmp(iter->pos, k.k->p)
+ : bkey_cmp(iter->pos, k.k->p))) {
+ bkey_init(&iter->k);
+ iter->k.p = iter->pos;
+ k = (struct bkey_s_c) { &iter->k, NULL };
+ }
+ } else {
+ struct bpos next = k.k ? bkey_start_pos(k.k) : POS_MAX;
+
+ if (bkey_cmp(iter->pos, next) < 0) {
+ bkey_init(&iter->k);
+ iter->k.p = iter->pos;
+ bch2_key_resize(&iter->k,
+ min_t(u64, KEY_SIZE_MAX,
+ (next.inode == iter->pos.inode
+ ? next.offset
+ : KEY_OFFSET_MAX) -
+ iter->pos.offset));
+
+ k = (struct bkey_s_c) { &iter->k, NULL };
+ EBUG_ON(!k.k->size);
+ }
}
bch2_btree_iter_verify_entry_exit(iter);
@@ -1919,12 +1913,17 @@ struct bkey_s_c bch2_btree_iter_prev_slot(struct btree_iter *iter)
struct bkey_s_c bch2_btree_iter_peek_cached(struct btree_iter *iter)
{
+ struct bkey_i *next_update;
struct bkey_cached *ck;
int ret;
EBUG_ON(btree_iter_type(iter) != BTREE_ITER_CACHED);
bch2_btree_iter_verify(iter);
+ next_update = btree_trans_peek_updates(iter, iter->pos);
+ if (next_update && !bpos_cmp(next_update->k.p, iter->pos))
+ return bkey_i_to_s_c(next_update);
+
ret = btree_iter_traverse(iter);
if (unlikely(ret))
return bkey_s_c_err(ret);
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 18732ca531ec..ba98cfea4d60 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -153,9 +153,6 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *);
struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *);
struct bkey_s_c bch2_btree_iter_next(struct btree_iter *);
-struct bkey_s_c bch2_btree_iter_peek_with_updates(struct btree_iter *);
-struct bkey_s_c bch2_btree_iter_next_with_updates(struct btree_iter *);
-
struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *);
struct bkey_s_c bch2_btree_iter_prev(struct btree_iter *);
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 36fa89bc9d34..ee392cdf58ad 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -209,12 +209,13 @@ enum btree_iter_type {
* @pos or the first key strictly greater than @pos
*/
#define BTREE_ITER_IS_EXTENTS (1 << 6)
-#define BTREE_ITER_ERROR (1 << 7)
-#define BTREE_ITER_SET_POS_AFTER_COMMIT (1 << 8)
-#define BTREE_ITER_CACHED_NOFILL (1 << 9)
-#define BTREE_ITER_CACHED_NOCREATE (1 << 10)
-#define BTREE_ITER_NOT_EXTENTS (1 << 11)
-#define BTREE_ITER_ALL_SNAPSHOTS (1 << 12)
+#define BTREE_ITER_NOT_EXTENTS (1 << 7)
+#define BTREE_ITER_ERROR (1 << 8)
+#define BTREE_ITER_SET_POS_AFTER_COMMIT (1 << 9)
+#define BTREE_ITER_CACHED_NOFILL (1 << 10)
+#define BTREE_ITER_CACHED_NOCREATE (1 << 11)
+#define BTREE_ITER_WITH_UPDATES (1 << 12)
+#define BTREE_ITER_ALL_SNAPSHOTS (1 << 13)
enum btree_iter_uptodate {
BTREE_ITER_UPTODATE = 0,
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 0d566be7455e..6557dbc0b64e 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -841,13 +841,11 @@ static int extent_handle_overwrites(struct btree_trans *trans,
struct bpos start = bkey_start_pos(&insert->k);
struct bkey_i *update;
struct bkey_s_c k;
- int ret = 0;
-
- iter = bch2_trans_get_iter(trans, btree_id, start,
- BTREE_ITER_INTENT);
- k = bch2_btree_iter_peek_with_updates(iter);
+ int ret;
- while (k.k && !(ret = bkey_err(k))) {
+ for_each_btree_key(trans, iter, btree_id, start,
+ BTREE_ITER_INTENT|
+ BTREE_ITER_WITH_UPDATES, k, ret) {
if (bkey_cmp(insert->k.p, bkey_start_pos(k.k)) <= 0)
break;
@@ -898,8 +896,6 @@ static int extent_handle_overwrites(struct btree_trans *trans,
bch2_trans_iter_put(trans, update_iter);
break;
}
-
- k = bch2_btree_iter_next_with_updates(iter);
}
bch2_trans_iter_put(trans, iter);