Skip to content

Commit 49771a7

Browse files
author
Kent Overstreet
committed
bcachefs: Fix bch2_btree_path_traverse_cached() when paths realloced
btree_key_cache_fill() will allocate and traverse another path (for the underlying btree), so we can't hold pointers to paths across a call - we have to pass indices. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 9c09e59 commit 49771a7

File tree

3 files changed

+19
-11
lines changed

3 files changed

+19
-11
lines changed

fs/bcachefs/btree_iter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ int bch2_btree_path_traverse_one(struct btree_trans *trans,
11621162
}
11631163

11641164
if (path->cached) {
1165-
ret = bch2_btree_path_traverse_cached(trans, path, flags);
1165+
ret = bch2_btree_path_traverse_cached(trans, path_idx, flags);
11661166
goto out;
11671167
}
11681168

fs/bcachefs/btree_key_cache.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,11 @@ static noinline_for_stack void do_trace_key_cache_fill(struct btree_trans *trans
301301
}
302302

303303
static noinline int btree_key_cache_fill(struct btree_trans *trans,
304-
struct btree_path *ck_path,
304+
btree_path_idx_t ck_path_idx,
305305
unsigned flags)
306306
{
307+
struct btree_path *ck_path = trans->paths + ck_path_idx;
308+
307309
if (flags & BTREE_ITER_cached_nofill) {
308310
ck_path->l[0].b = NULL;
309311
return 0;
@@ -325,6 +327,7 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans,
325327
goto err;
326328

327329
/* Recheck after btree lookup, before allocating: */
330+
ck_path = trans->paths + ck_path_idx;
328331
ret = bch2_btree_key_cache_find(c, ck_path->btree_id, ck_path->pos) ? -EEXIST : 0;
329332
if (unlikely(ret))
330333
goto out;
@@ -344,10 +347,11 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans,
344347
}
345348

346349
static inline int btree_path_traverse_cached_fast(struct btree_trans *trans,
347-
struct btree_path *path)
350+
btree_path_idx_t path_idx)
348351
{
349352
struct bch_fs *c = trans->c;
350353
struct bkey_cached *ck;
354+
struct btree_path *path = trans->paths + path_idx;
351355
retry:
352356
ck = bch2_btree_key_cache_find(c, path->btree_id, path->pos);
353357
if (!ck)
@@ -373,27 +377,32 @@ static inline int btree_path_traverse_cached_fast(struct btree_trans *trans,
373377
return 0;
374378
}
375379

376-
int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path *path,
380+
int bch2_btree_path_traverse_cached(struct btree_trans *trans,
381+
btree_path_idx_t path_idx,
377382
unsigned flags)
378383
{
379-
EBUG_ON(path->level);
380-
381-
path->l[1].b = NULL;
384+
EBUG_ON(trans->paths[path_idx].level);
382385

383386
int ret;
384387
do {
385-
ret = btree_path_traverse_cached_fast(trans, path);
388+
ret = btree_path_traverse_cached_fast(trans, path_idx);
386389
if (unlikely(ret == -ENOENT))
387-
ret = btree_key_cache_fill(trans, path, flags);
390+
ret = btree_key_cache_fill(trans, path_idx, flags);
388391
} while (ret == -EEXIST);
389392

393+
struct btree_path *path = trans->paths + path_idx;
394+
390395
if (unlikely(ret)) {
391396
path->uptodate = BTREE_ITER_NEED_TRAVERSE;
392397
if (!bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
393398
btree_node_unlock(trans, path, 0);
394399
path->l[0].b = ERR_PTR(ret);
395400
}
401+
} else {
402+
BUG_ON(path->uptodate);
403+
BUG_ON(!path->nodes_locked);
396404
}
405+
397406
return ret;
398407
}
399408

fs/bcachefs/btree_key_cache.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ int bch2_btree_key_cache_journal_flush(struct journal *,
4040
struct bkey_cached *
4141
bch2_btree_key_cache_find(struct bch_fs *, enum btree_id, struct bpos);
4242

43-
int bch2_btree_path_traverse_cached(struct btree_trans *, struct btree_path *,
44-
unsigned);
43+
int bch2_btree_path_traverse_cached(struct btree_trans *, btree_path_idx_t, unsigned);
4544

4645
bool bch2_btree_insert_key_cached(struct btree_trans *, unsigned,
4746
struct btree_insert_entry *);

0 commit comments

Comments
 (0)