summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-12-21 20:48:26 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2021-12-25 17:37:12 -0500
commit732e06f7684a58c2d77aa1b30f81e473984717d6 (patch)
tree41e1001db2cd7306c0aab5ea40e0faa2531e4312
parentcabc3b6dfbcb7e3e4836ec212aef4bdbd6e62dd4 (diff)
bcachefs: BTREE_ITER_NOPRESERVE
This adds a flag to not mark the initial btree_path as preserve, for paths that we expect to be cheap to reconstitute if necessary - this solves a btree_path overflow caused by need_whiteout_for_snapshot(). Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/btree_iter.c20
-rw-r--r--fs/bcachefs/btree_iter.h5
-rw-r--r--fs/bcachefs/btree_types.h1
-rw-r--r--fs/bcachefs/btree_update_interior.c4
-rw-r--r--fs/bcachefs/btree_update_leaf.c3
5 files changed, 16 insertions, 17 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index c187531ac581..e9091f8a153e 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1818,12 +1818,14 @@ static struct btree_path *btree_path_alloc(struct btree_trans *trans,
return path;
}
-struct btree_path *bch2_path_get(struct btree_trans *trans, bool cached,
+struct btree_path *bch2_path_get(struct btree_trans *trans,
enum btree_id btree_id, struct bpos pos,
unsigned locks_want, unsigned level,
- bool intent, unsigned long ip)
+ unsigned flags, unsigned long ip)
{
struct btree_path *path, *path_pos = NULL;
+ bool cached = flags & BTREE_ITER_CACHED;
+ bool intent = flags & BTREE_ITER_INTENT;
int i;
BUG_ON(trans->restarted);
@@ -1845,7 +1847,6 @@ struct btree_path *bch2_path_get(struct btree_trans *trans, bool cached,
path_pos->level == level) {
__btree_path_get(path_pos, intent);
path = btree_path_set_pos(trans, path_pos, pos, intent, ip);
- path->preserve = true;
} else {
path = btree_path_alloc(trans, path_pos);
path_pos = NULL;
@@ -1854,7 +1855,6 @@ struct btree_path *bch2_path_get(struct btree_trans *trans, bool cached,
path->pos = pos;
path->btree_id = btree_id;
path->cached = cached;
- path->preserve = true;
path->uptodate = BTREE_ITER_NEED_TRAVERSE;
path->should_be_locked = false;
path->level = level;
@@ -1869,6 +1869,9 @@ struct btree_path *bch2_path_get(struct btree_trans *trans, bool cached,
btree_trans_verify_sorted(trans);
}
+ if (!(flags & BTREE_ITER_NOPRESERVE))
+ path->preserve = true;
+
if (path->intent_ref)
locks_want = max(locks_want, level + 1);
@@ -2625,13 +2628,8 @@ static void __bch2_trans_iter_init(struct btree_trans *trans,
iter->ip_allocated = ip;
#endif
- iter->path = bch2_path_get(trans,
- flags & BTREE_ITER_CACHED,
- btree_id,
- iter->pos,
- locks_want,
- depth,
- flags & BTREE_ITER_INTENT, ip);
+ iter->path = bch2_path_get(trans, btree_id, iter->pos,
+ locks_want, depth, flags, ip);
}
void bch2_trans_iter_init(struct btree_trans *trans,
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 26eb90a7eab8..4c903b9dd716 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -134,9 +134,8 @@ bch2_btree_path_make_mut(struct btree_trans *, struct btree_path *,
bool, unsigned long);
int __must_check bch2_btree_path_traverse(struct btree_trans *,
struct btree_path *, unsigned);
-struct btree_path *bch2_path_get(struct btree_trans *, bool, enum btree_id,
- struct bpos, unsigned, unsigned, bool,
- unsigned long);
+struct btree_path *bch2_path_get(struct btree_trans *, enum btree_id, struct bpos,
+ unsigned, unsigned, unsigned, unsigned long);
inline struct bkey_s_c bch2_btree_path_peek_slot(struct btree_path *, struct bkey *);
#ifdef CONFIG_BCACHEFS_DEBUG
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 22dbbe365bbe..c84bba7bcda5 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -210,6 +210,7 @@ struct btree_node_iter {
#define __BTREE_ITER_ALL_SNAPSHOTS (1 << 11)
#define BTREE_ITER_ALL_SNAPSHOTS (1 << 12)
#define BTREE_ITER_FILTER_SNAPSHOTS (1 << 13)
+#define BTREE_ITER_NOPRESERVE (1 << 14)
enum btree_path_uptodate {
BTREE_ITER_UPTODATE = 0,
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index d895d4eff0a9..f5d879dee423 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -1609,8 +1609,8 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
? bpos_predecessor(b->data->min_key)
: bpos_successor(b->data->max_key);
- sib_path = bch2_path_get(trans, false, path->btree_id, sib_pos,
- U8_MAX, level, true, _THIS_IP_);
+ sib_path = bch2_path_get(trans, path->btree_id, sib_pos,
+ U8_MAX, level, BTREE_ITER_INTENT, _THIS_IP_);
ret = bch2_btree_path_traverse(trans, sib_path, false);
if (ret)
goto err;
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 295942e7356e..1966441b1a62 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -1285,7 +1285,8 @@ static int need_whiteout_for_snapshot(struct btree_trans *trans,
pos.snapshot++;
for_each_btree_key_norestart(trans, iter, btree_id, pos,
- BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
+ BTREE_ITER_ALL_SNAPSHOTS|
+ BTREE_ITER_NOPRESERVE, k, ret) {
if (bkey_cmp(k.k->p, pos))
break;