Commit 424eb881 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Only get btree iters from btree transactions

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 5df4be3f
...@@ -264,18 +264,21 @@ static void bch2_alloc_read_key(struct bch_fs *c, struct bkey_s_c k) ...@@ -264,18 +264,21 @@ static void bch2_alloc_read_key(struct bch_fs *c, struct bkey_s_c k)
int bch2_alloc_read(struct bch_fs *c, struct list_head *journal_replay_list) int bch2_alloc_read(struct bch_fs *c, struct list_head *journal_replay_list)
{ {
struct journal_replay *r; struct journal_replay *r;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_dev *ca; struct bch_dev *ca;
unsigned i; unsigned i;
int ret; int ret;
for_each_btree_key(&iter, c, BTREE_ID_ALLOC, POS_MIN, 0, k) { bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_ALLOC, POS_MIN, 0, k) {
bch2_alloc_read_key(c, k); bch2_alloc_read_key(c, k);
bch2_btree_iter_cond_resched(&iter); bch2_trans_cond_resched(&trans);
} }
ret = bch2_btree_iter_unlock(&iter); ret = bch2_trans_exit(&trans);
if (ret) if (ret)
return ret; return ret;
...@@ -391,8 +394,6 @@ static int __bch2_alloc_write_key(struct btree_trans *trans, struct bch_dev *ca, ...@@ -391,8 +394,6 @@ static int __bch2_alloc_write_key(struct btree_trans *trans, struct bch_dev *ca,
__alloc_write_key(a, g, m); __alloc_write_key(a, g, m);
percpu_up_read(&c->mark_lock); percpu_up_read(&c->mark_lock);
bch2_btree_iter_cond_resched(iter);
bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, &a->k_i)); bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, &a->k_i));
ret = bch2_trans_commit(trans, NULL, journal_seq, ret = bch2_trans_commit(trans, NULL, journal_seq,
...@@ -450,6 +451,7 @@ int bch2_alloc_write(struct bch_fs *c, bool nowait, bool *wrote) ...@@ -450,6 +451,7 @@ int bch2_alloc_write(struct bch_fs *c, bool nowait, bool *wrote)
if (ret) if (ret)
break; break;
bch2_trans_cond_resched(&trans);
*wrote = true; *wrote = true;
} }
up_read(&ca->bucket_lock); up_read(&ca->bucket_lock);
...@@ -938,8 +940,6 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans, ...@@ -938,8 +940,6 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans,
spin_unlock(&c->freelist_lock); spin_unlock(&c->freelist_lock);
percpu_up_read(&c->mark_lock); percpu_up_read(&c->mark_lock);
bch2_btree_iter_cond_resched(iter);
BUG_ON(BKEY_ALLOC_VAL_U64s_MAX > 8); BUG_ON(BKEY_ALLOC_VAL_U64s_MAX > 8);
bch2_btree_iter_set_pos(iter, POS(ca->dev_idx, b)); bch2_btree_iter_set_pos(iter, POS(ca->dev_idx, b));
......
...@@ -207,13 +207,16 @@ static int btree_gc_mark_node(struct bch_fs *c, struct btree *b, ...@@ -207,13 +207,16 @@ static int btree_gc_mark_node(struct bch_fs *c, struct btree *b,
static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id, static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
bool initial) bool initial)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct btree *b; struct btree *b;
struct range_checks r; struct range_checks r;
unsigned depth = btree_node_type_needs_gc(btree_id) ? 0 : 1; unsigned depth = btree_node_type_needs_gc(btree_id) ? 0 : 1;
u8 max_stale; u8 max_stale;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c);
gc_pos_set(c, gc_pos_btree(btree_id, POS_MIN, 0)); gc_pos_set(c, gc_pos_btree(btree_id, POS_MIN, 0));
/* /*
...@@ -227,7 +230,7 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id, ...@@ -227,7 +230,7 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
btree_node_range_checks_init(&r, depth); btree_node_range_checks_init(&r, depth);
__for_each_btree_node(&iter, c, btree_id, POS_MIN, __for_each_btree_node(&trans, iter, btree_id, POS_MIN,
0, depth, BTREE_ITER_PREFETCH, b) { 0, depth, BTREE_ITER_PREFETCH, b) {
btree_node_range_checks(c, b, &r); btree_node_range_checks(c, b, &r);
...@@ -241,22 +244,22 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id, ...@@ -241,22 +244,22 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
if (!initial) { if (!initial) {
if (max_stale > 64) if (max_stale > 64)
bch2_btree_node_rewrite(c, &iter, bch2_btree_node_rewrite(c, iter,
b->data->keys.seq, b->data->keys.seq,
BTREE_INSERT_USE_RESERVE| BTREE_INSERT_USE_RESERVE|
BTREE_INSERT_NOWAIT| BTREE_INSERT_NOWAIT|
BTREE_INSERT_GC_LOCK_HELD); BTREE_INSERT_GC_LOCK_HELD);
else if (!btree_gc_rewrite_disabled(c) && else if (!btree_gc_rewrite_disabled(c) &&
(btree_gc_always_rewrite(c) || max_stale > 16)) (btree_gc_always_rewrite(c) || max_stale > 16))
bch2_btree_node_rewrite(c, &iter, bch2_btree_node_rewrite(c, iter,
b->data->keys.seq, b->data->keys.seq,
BTREE_INSERT_NOWAIT| BTREE_INSERT_NOWAIT|
BTREE_INSERT_GC_LOCK_HELD); BTREE_INSERT_GC_LOCK_HELD);
} }
bch2_btree_iter_cond_resched(&iter); bch2_trans_cond_resched(&trans);
} }
ret = bch2_btree_iter_unlock(&iter) ?: ret; ret = bch2_trans_exit(&trans) ?: ret;
if (ret) if (ret)
return ret; return ret;
...@@ -1030,7 +1033,8 @@ static void bch2_coalesce_nodes(struct bch_fs *c, struct btree_iter *iter, ...@@ -1030,7 +1033,8 @@ static void bch2_coalesce_nodes(struct bch_fs *c, struct btree_iter *iter,
static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id) static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct btree *b; struct btree *b;
bool kthread = (current->flags & PF_KTHREAD) != 0; bool kthread = (current->flags & PF_KTHREAD) != 0;
unsigned i; unsigned i;
...@@ -1039,6 +1043,8 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id) ...@@ -1039,6 +1043,8 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
struct btree *merge[GC_MERGE_NODES]; struct btree *merge[GC_MERGE_NODES];
u32 lock_seq[GC_MERGE_NODES]; u32 lock_seq[GC_MERGE_NODES];
bch2_trans_init(&trans, c);
/* /*
* XXX: We don't have a good way of positively matching on sibling nodes * XXX: We don't have a good way of positively matching on sibling nodes
* that have the same parent - this code works by handling the cases * that have the same parent - this code works by handling the cases
...@@ -1048,7 +1054,7 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id) ...@@ -1048,7 +1054,7 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
*/ */
memset(merge, 0, sizeof(merge)); memset(merge, 0, sizeof(merge));
__for_each_btree_node(&iter, c, btree_id, POS_MIN, __for_each_btree_node(&trans, iter, btree_id, POS_MIN,
BTREE_MAX_DEPTH, 0, BTREE_MAX_DEPTH, 0,
BTREE_ITER_PREFETCH, b) { BTREE_ITER_PREFETCH, b) {
memmove(merge + 1, merge, memmove(merge + 1, merge,
...@@ -1070,7 +1076,7 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id) ...@@ -1070,7 +1076,7 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
} }
memset(merge + i, 0, (GC_MERGE_NODES - i) * sizeof(merge[0])); memset(merge + i, 0, (GC_MERGE_NODES - i) * sizeof(merge[0]));
bch2_coalesce_nodes(c, &iter, merge); bch2_coalesce_nodes(c, iter, merge);
for (i = 1; i < GC_MERGE_NODES && merge[i]; i++) { for (i = 1; i < GC_MERGE_NODES && merge[i]; i++) {
lock_seq[i] = merge[i]->lock.state.seq; lock_seq[i] = merge[i]->lock.state.seq;
...@@ -1080,23 +1086,23 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id) ...@@ -1080,23 +1086,23 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
lock_seq[0] = merge[0]->lock.state.seq; lock_seq[0] = merge[0]->lock.state.seq;
if (kthread && kthread_should_stop()) { if (kthread && kthread_should_stop()) {
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return -ESHUTDOWN; return -ESHUTDOWN;
} }
bch2_btree_iter_cond_resched(&iter); bch2_trans_cond_resched(&trans);
/* /*
* If the parent node wasn't relocked, it might have been split * If the parent node wasn't relocked, it might have been split
* and the nodes in our sliding window might not have the same * and the nodes in our sliding window might not have the same
* parent anymore - blow away the sliding window: * parent anymore - blow away the sliding window:
*/ */
if (btree_iter_node(&iter, iter.level + 1) && if (btree_iter_node(iter, iter->level + 1) &&
!btree_node_intent_locked(&iter, iter.level + 1)) !btree_node_intent_locked(iter, iter->level + 1))
memset(merge + 1, 0, memset(merge + 1, 0,
(GC_MERGE_NODES - 1) * sizeof(merge[0])); (GC_MERGE_NODES - 1) * sizeof(merge[0]));
} }
return bch2_btree_iter_unlock(&iter); return bch2_trans_exit(&trans);
} }
/** /**
......
...@@ -1153,19 +1153,21 @@ static void bch2_btree_node_write_error(struct bch_fs *c, ...@@ -1153,19 +1153,21 @@ static void bch2_btree_node_write_error(struct bch_fs *c,
struct bkey_i_btree_ptr *new_key; struct bkey_i_btree_ptr *new_key;
struct bkey_s_btree_ptr bp; struct bkey_s_btree_ptr bp;
struct bch_extent_ptr *ptr; struct bch_extent_ptr *ptr;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
int ret; int ret;
__bch2_btree_iter_init(&iter, c, b->btree_id, b->key.k.p, bch2_trans_init(&trans, c);
BTREE_MAX_DEPTH,
b->level, BTREE_ITER_NODES); iter = bch2_trans_get_node_iter(&trans, b->btree_id, b->key.k.p,
BTREE_MAX_DEPTH, b->level, 0);
retry: retry:
ret = bch2_btree_iter_traverse(&iter); ret = bch2_btree_iter_traverse(iter);
if (ret) if (ret)
goto err; goto err;
/* has node been freed? */ /* has node been freed? */
if (iter.l[b->level].b != b) { if (iter->l[b->level].b != b) {
/* node has been freed: */ /* node has been freed: */
BUG_ON(!btree_node_dying(b)); BUG_ON(!btree_node_dying(b));
goto out; goto out;
...@@ -1184,13 +1186,13 @@ static void bch2_btree_node_write_error(struct bch_fs *c, ...@@ -1184,13 +1186,13 @@ static void bch2_btree_node_write_error(struct bch_fs *c,
if (!bch2_bkey_nr_ptrs(bp.s_c)) if (!bch2_bkey_nr_ptrs(bp.s_c))
goto err; goto err;
ret = bch2_btree_node_update_key(c, &iter, b, new_key); ret = bch2_btree_node_update_key(c, iter, b, new_key);
if (ret == -EINTR) if (ret == -EINTR)
goto retry; goto retry;
if (ret) if (ret)
goto err; goto err;
out: out:
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
bio_put(&wbio->wbio.bio); bio_put(&wbio->wbio.bio);
btree_node_write_done(c, b); btree_node_write_done(c, b);
return; return;
......
...@@ -1582,15 +1582,15 @@ struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *iter) ...@@ -1582,15 +1582,15 @@ struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *iter)
return __bch2_btree_iter_peek_slot(iter); return __bch2_btree_iter_peek_slot(iter);
} }
void __bch2_btree_iter_init(struct btree_iter *iter, struct bch_fs *c, static inline void bch2_btree_iter_init(struct btree_iter *iter,
enum btree_id btree_id, struct bpos pos, struct bch_fs *c, enum btree_id btree_id,
unsigned locks_want, unsigned depth, struct bpos pos, unsigned flags)
unsigned flags)
{ {
unsigned i; unsigned i;
EBUG_ON(depth >= BTREE_MAX_DEPTH); if (btree_id == BTREE_ID_EXTENTS &&
EBUG_ON(locks_want > BTREE_MAX_DEPTH); !(flags & BTREE_ITER_NODES))
flags |= BTREE_ITER_IS_EXTENTS;
iter->c = c; iter->c = c;
iter->pos = pos; iter->pos = pos;
...@@ -1599,8 +1599,8 @@ void __bch2_btree_iter_init(struct btree_iter *iter, struct bch_fs *c, ...@@ -1599,8 +1599,8 @@ void __bch2_btree_iter_init(struct btree_iter *iter, struct bch_fs *c,
iter->flags = flags; iter->flags = flags;
iter->uptodate = BTREE_ITER_NEED_TRAVERSE; iter->uptodate = BTREE_ITER_NEED_TRAVERSE;
iter->btree_id = btree_id; iter->btree_id = btree_id;
iter->level = depth; iter->level = 0;
iter->locks_want = locks_want; iter->locks_want = flags & BTREE_ITER_INTENT ? 1 : 0;
iter->nodes_locked = 0; iter->nodes_locked = 0;
iter->nodes_intent_locked = 0; iter->nodes_intent_locked = 0;
for (i = 0; i < ARRAY_SIZE(iter->l); i++) for (i = 0; i < ARRAY_SIZE(iter->l); i++)
...@@ -1677,12 +1677,14 @@ static inline unsigned btree_trans_iter_idx(struct btree_trans *trans, ...@@ -1677,12 +1677,14 @@ static inline unsigned btree_trans_iter_idx(struct btree_trans *trans,
return idx; return idx;
} }
void bch2_trans_iter_put(struct btree_trans *trans, int bch2_trans_iter_put(struct btree_trans *trans,
struct btree_iter *iter) struct btree_iter *iter)
{ {
ssize_t idx = btree_trans_iter_idx(trans, iter); ssize_t idx = btree_trans_iter_idx(trans, iter);
int ret = (iter->flags & BTREE_ITER_ERROR) ? -EIO : 0;
trans->iters_live &= ~(1ULL << idx); trans->iters_live &= ~(1ULL << idx);
return ret;
} }
static inline void __bch2_trans_iter_free(struct btree_trans *trans, static inline void __bch2_trans_iter_free(struct btree_trans *trans,
...@@ -1696,17 +1698,23 @@ static inline void __bch2_trans_iter_free(struct btree_trans *trans, ...@@ -1696,17 +1698,23 @@ static inline void __bch2_trans_iter_free(struct btree_trans *trans,
bch2_btree_iter_unlink(&trans->iters[idx]); bch2_btree_iter_unlink(&trans->iters[idx]);
} }
void bch2_trans_iter_free(struct btree_trans *trans, int bch2_trans_iter_free(struct btree_trans *trans,
struct btree_iter *iter) struct btree_iter *iter)
{ {
int ret = (iter->flags & BTREE_ITER_ERROR) ? -EIO : 0;
__bch2_trans_iter_free(trans, btree_trans_iter_idx(trans, iter)); __bch2_trans_iter_free(trans, btree_trans_iter_idx(trans, iter));
return ret;
} }
void bch2_trans_iter_free_on_commit(struct btree_trans *trans, int bch2_trans_iter_free_on_commit(struct btree_trans *trans,
struct btree_iter *iter) struct btree_iter *iter)
{ {
int ret = (iter->flags & BTREE_ITER_ERROR) ? -EIO : 0;
trans->iters_unlink_on_commit |= trans->iters_unlink_on_commit |=
1ULL << btree_trans_iter_idx(trans, iter); 1ULL << btree_trans_iter_idx(trans, iter);
return ret;
} }
static int btree_trans_realloc_iters(struct btree_trans *trans, static int btree_trans_realloc_iters(struct btree_trans *trans,
...@@ -1820,7 +1828,7 @@ static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans, ...@@ -1820,7 +1828,7 @@ static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans,
iter = &trans->iters[idx]; iter = &trans->iters[idx];
iter->id = iter_id; iter->id = iter_id;
bch2_btree_iter_init(iter, trans->c, btree_id, POS_MIN, flags); bch2_btree_iter_init(iter, trans->c, btree_id, pos, flags);
} else { } else {
iter = &trans->iters[idx]; iter = &trans->iters[idx];
...@@ -1861,6 +1869,31 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans, ...@@ -1861,6 +1869,31 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans,
return iter; return iter;
} }
struct btree_iter *bch2_trans_get_node_iter(struct btree_trans *trans,
enum btree_id btree_id,
struct bpos pos,
unsigned locks_want,
unsigned depth,
unsigned flags)
{
struct btree_iter *iter =
__btree_trans_get_iter(trans, btree_id, pos,
flags|BTREE_ITER_NODES, 0);
unsigned i;
BUG_ON(IS_ERR(iter));
BUG_ON(bkey_cmp(iter->pos, pos));
iter->locks_want = locks_want;
iter->level = depth;
for (i = 0; i < ARRAY_SIZE(iter->l); i++)
iter->l[i].b = NULL;
iter->l[iter->level].b = BTREE_ITER_NOT_END;
return iter;
}
struct btree_iter *__bch2_trans_copy_iter(struct btree_trans *trans, struct btree_iter *__bch2_trans_copy_iter(struct btree_trans *trans,
struct btree_iter *src, struct btree_iter *src,
u64 iter_id) u64 iter_id)
......
...@@ -150,20 +150,6 @@ struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *); ...@@ -150,20 +150,6 @@ struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *);
void bch2_btree_iter_set_pos_same_leaf(struct btree_iter *, struct bpos); void bch2_btree_iter_set_pos_same_leaf(struct btree_iter *, struct bpos);
void bch2_btree_iter_set_pos(struct btree_iter *, struct bpos); void bch2_btree_iter_set_pos(struct btree_iter *, struct bpos);
void __bch2_btree_iter_init(struct btree_iter *, struct bch_fs *,
enum btree_id, struct bpos,
unsigned , unsigned, unsigned);
static inline void bch2_btree_iter_init(struct btree_iter *iter,
struct bch_fs *c, enum btree_id btree_id,
struct bpos pos, unsigned flags)
{
__bch2_btree_iter_init(iter, c, btree_id, pos,
flags & BTREE_ITER_INTENT ? 1 : 0, 0,
(btree_id == BTREE_ID_EXTENTS
? BTREE_ITER_IS_EXTENTS : 0)|flags);
}
void bch2_btree_iter_copy(struct btree_iter *, struct btree_iter *); void bch2_btree_iter_copy(struct btree_iter *, struct btree_iter *);
static inline struct bpos btree_type_successor(enum btree_id id, static inline struct bpos btree_type_successor(enum btree_id id,
...@@ -221,17 +207,18 @@ static inline void bch2_btree_iter_cond_resched(struct btree_iter *iter) ...@@ -221,17 +207,18 @@ static inline void bch2_btree_iter_cond_resched(struct btree_iter *iter)
} }
} }
#define __for_each_btree_node(_iter, _c, _btree_id, _start, \ #define __for_each_btree_node(_trans, _iter, _btree_id, _start, \
_locks_want, _depth, _flags, _b) \ _locks_want, _depth, _flags, _b) \
for (__bch2_btree_iter_init((_iter), (_c), (_btree_id), _start, \ for (iter = bch2_trans_get_node_iter((_trans), (_btree_id), \
_locks_want, _depth, \ _start, _locks_want, _depth, _flags), \
_flags|BTREE_ITER_NODES), \
_b = bch2_btree_iter_peek_node(_iter); \ _b = bch2_btree_iter_peek_node(_iter); \
(_b); \ (_b); \
(_b) = bch2_btree_iter_next_node(_iter, _depth)) (_b) = bch2_btree_iter_next_node(_iter, _depth))
#define for_each_btree_node(_iter, _c, _btree_id, _start, _flags, _b) \ #define for_each_btree_node(_trans, _iter, _btree_id, _start, \
__for_each_btree_node(_iter, _c, _btree_id, _start, 0, 0, _flags, _b) _flags, _b) \
__for_each_btree_node(_trans, _iter, _btree_id, _start, \
0, 0, _flags, _b)
static inline struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter, static inline struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter,
unsigned flags) unsigned flags)
...@@ -251,8 +238,8 @@ static inline struct bkey_s_c __bch2_btree_iter_next(struct btree_iter *iter, ...@@ -251,8 +238,8 @@ static inline struct bkey_s_c __bch2_btree_iter_next(struct btree_iter *iter,
: bch2_btree_iter_next(iter); : bch2_btree_iter_next(iter);
} }
#define for_each_btree_key(_iter, _c, _btree_id, _start, _flags, _k) \ #define for_each_btree_key(_trans, _iter, _btree_id, _start, _flags, _k)\
for (bch2_btree_iter_init((_iter), (_c), (_btree_id), \ for (iter = bch2_trans_get_iter((_trans), (_btree_id), \
(_start), (_flags)), \ (_start), (_flags)), \
(_k) = __bch2_btree_iter_peek(_iter, _flags); \ (_k) = __bch2_btree_iter_peek(_iter, _flags); \
!IS_ERR_OR_NULL((_k).k); \ !IS_ERR_OR_NULL((_k).k); \
...@@ -271,9 +258,9 @@ static inline int btree_iter_err(struct bkey_s_c k) ...@@ -271,9 +258,9 @@ static inline int btree_iter_err(struct bkey_s_c k)
/* new multiple iterator interface: */ /* new multiple iterator interface: */
void bch2_trans_preload_iters(struct btree_trans *); void bch2_trans_preload_iters(struct btree_trans *);
void bch2_trans_iter_put(struct btree_trans *, struct btree_iter *); int bch2_trans_iter_put(struct btree_trans *, struct btree_iter *);
void bch2_trans_iter_free(struct btree_trans *, struct btree_iter *); int bch2_trans_iter_free(struct btree_trans *, struct btree_iter *);
void bch2_trans_iter_free_on_commit(struct btree_trans *, struct btree_iter *); int bch2_trans_iter_free_on_commit(struct btree_trans *, struct btree_iter *);
void bch2_trans_unlink_iters(struct btree_trans *, u64); void bch2_trans_unlink_iters(struct btree_trans *, u64);
...@@ -308,6 +295,10 @@ bch2_trans_copy_iter(struct btree_trans *trans, struct btree_iter *src) ...@@ -308,6 +295,10 @@ bch2_trans_copy_iter(struct btree_trans *trans, struct btree_iter *src)
return __bch2_trans_copy_iter(trans, src, __btree_iter_id()); return __bch2_trans_copy_iter(trans, src, __btree_iter_id());
} }
struct btree_iter *bch2_trans_get_node_iter(struct btree_trans *,
enum btree_id, struct bpos,
unsigned, unsigned, unsigned);
void __bch2_trans_begin(struct btree_trans *); void __bch2_trans_begin(struct btree_trans *);
static inline void bch2_trans_begin_updates(struct btree_trans *trans) static inline void bch2_trans_begin_updates(struct btree_trans *trans)
...@@ -320,6 +311,16 @@ int bch2_trans_unlock(struct btree_trans *); ...@@ -320,6 +311,16 @@ int bch2_trans_unlock(struct btree_trans *);
void bch2_trans_init(struct btree_trans *, struct bch_fs *); void bch2_trans_init(struct btree_trans *, struct bch_fs *);
int bch2_trans_exit(struct btree_trans *); int bch2_trans_exit(struct btree_trans *);
static inline void bch2_trans_cond_resched(struct btree_trans *trans)
{
if (need_resched()) {
bch2_trans_unlock(trans);
schedule();
} else if (race_fault()) {
bch2_trans_unlock(trans);
}
}
#ifdef TRACE_TRANSACTION_RESTARTS #ifdef TRACE_TRANSACTION_RESTARTS
#define bch2_trans_begin(_trans) \ #define bch2_trans_begin(_trans) \
do { \ do { \
......
...@@ -999,7 +999,7 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id, ...@@ -999,7 +999,7 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id,
if (ret) if (ret)
break; break;
bch2_btree_iter_cond_resched(iter); bch2_trans_cond_resched(&trans);
} }
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
......
...@@ -303,8 +303,8 @@ static ssize_t bch2_data_job_read(struct file *file, char __user *buf, ...@@ -303,8 +303,8 @@ static ssize_t bch2_data_job_read(struct file *file, char __user *buf,
struct bch_ioctl_data_event e = { struct bch_ioctl_data_event e = {
.type = BCH_DATA_EVENT_PROGRESS, .type = BCH_DATA_EVENT_PROGRESS,
.p.data_type = ctx->stats.data_type, .p.data_type = ctx->stats.data_type,
.p.btree_id = ctx->stats.iter.btree_id, .p.btree_id = ctx->stats.btree_id,
.p.pos = ctx->stats.iter.pos, .p.pos = ctx->stats.pos,
.p.sectors_done = atomic64_read(&ctx->stats.sectors_seen), .p.sectors_done = atomic64_read(&ctx->stats.sectors_seen),
.p.sectors_total = bch2_fs_usage_read_short(c).used, .p.sectors_total = bch2_fs_usage_read_short(c).used,
}; };
......
...@@ -205,7 +205,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf, ...@@ -205,7 +205,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
size_t size, loff_t *ppos) size_t size, loff_t *ppos)
{ {
struct dump_iter *i = file->private_data; struct dump_iter *i = file->private_data;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int err; int err;
...@@ -220,8 +221,10 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf, ...@@ -220,8 +221,10 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
if (!i->size) if (!i->size)
return i->ret; return i->ret;
bch2_btree_iter_init(&iter, i->c, i->id, i->from, BTREE_ITER_PREFETCH); bch2_trans_init(&trans, i->c);
k = bch2_btree_iter_peek(&iter);
iter = bch2_trans_get_iter(&trans, i->id, i->from, BTREE_ITER_PREFETCH);
k = bch2_btree_iter_peek(iter);
while (k.k && !(err = btree_iter_err(k))) { while (k.k && !(err = btree_iter_err(k))) {
bch2_bkey_val_to_text(&PBUF(i->buf), i->c, k); bch2_bkey_val_to_text(&PBUF(i->buf), i->c, k);
...@@ -230,8 +233,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf, ...@@ -230,8 +233,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
i->buf[i->bytes] = '\n'; i->buf[i->bytes] = '\n';
i->bytes++; i->bytes++;
k = bch2_btree_iter_next(&iter); k = bch2_btree_iter_next(iter);
i->from = iter.pos; i->from = iter->pos;
err = flush_buf(i); err = flush_buf(i);
if (err) if (err)
...@@ -240,7 +243,7 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf, ...@@ -240,7 +243,7 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
if (!i->size) if (!i->size)
break; break;
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return err < 0 ? err : i->ret; return err < 0 ? err : i->ret;
} }
...@@ -256,7 +259,8 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf, ...@@ -256,7 +259,8 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
size_t size, loff_t *ppos) size_t size, loff_t *ppos)
{ {
struct dump_iter *i = file->private_data; struct dump_iter *i = file->private_data;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct btree *b; struct btree *b;
int err; int err;
...@@ -271,7 +275,9 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf, ...@@ -271,7 +275,9 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
if (!i->size || !bkey_cmp(POS_MAX, i->from)) if (!i->size || !bkey_cmp(POS_MAX, i->from))
return i->ret; return i->ret;
for_each_btree_node(&iter, i->c, i->id, i->from, 0, b) { bch2_trans_init(&trans, i->c);
for_each_btree_node(&trans, iter, i->id, i->from, 0, b) {
bch2_btree_node_to_text(&PBUF(i->buf), i->c, b); bch2_btree_node_to_text(&PBUF(i->buf), i->c, b);
i->bytes = strlen(i->buf); i->bytes = strlen(i->buf);
err = flush_buf(i); err = flush_buf(i);
...@@ -289,7 +295,7 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf, ...@@ -289,7 +295,7 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
if (!i->size) if (!i->size)
break; break;
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return err < 0 ? err : i->ret; return err < 0 ? err : i->ret;
} }
...@@ -305,7 +311,8 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf, ...@@ -305,7 +311,8 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
size_t size, loff_t *ppos) size_t size, loff_t *ppos)
{ {
struct dump_iter *i = file->private_data; struct dump_iter *i = file->private_data;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
struct btree *prev_node = NULL; struct btree *prev_node = NULL;
int err; int err;
...@@ -321,11 +328,13 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf, ...@@ -321,11 +328,13 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
if (!i->size) if (!i->size)
return i->ret; return i->ret;
bch2_btree_iter_init(&iter, i->c, i->id, i->from, BTREE_ITER_PREFETCH); bch2_trans_init(&trans, i->c);
iter = bch2_trans_get_iter(&trans, i->id, i->from, BTREE_ITER_PREFETCH);
while ((k = bch2_btree_iter_peek(&iter)).k && while ((k = bch2_btree_iter_peek(iter)).k &&
!(err = btree_iter_err(k))) { !(err = btree_iter_err(k))) {
struct btree_iter_level *l = &iter.l[0]; struct btree_iter_level *l = &iter->l[0];
struct bkey_packed *_k = struct bkey_packed *_k =
bch2_btree_node_iter_peek(&l->iter, l->b); bch2_btree_node_iter_peek(&l->iter, l->b);
...@@ -344,8 +353,8 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf, ...@@ -344,8 +353,8 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
if (err) if (err)
break; break;
bch2_btree_iter_next(&iter); bch2_btree_iter_next(iter);
i->from = iter.pos; i->from = iter->pos;
err = flush_buf(i); err = flush_buf(i);
if (err) if (err)
...@@ -354,7 +363,7 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf, ...@@ -354,7 +363,7 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
if (!i->size) if (!i->size)
break; break;
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return err < 0 ? err : i->ret; return err < 0 ? err : i->ret;
} }
......
...@@ -331,11 +331,15 @@ u64 bch2_dirent_lookup(struct bch_fs *c, u64 dir_inum, ...@@ -331,11 +331,15 @@ u64 bch2_dirent_lookup(struct bch_fs *c, u64 dir_inum,
int bch2_empty_dir(struct bch_fs *c, u64 dir_inum) int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS(dir_inum, 0), 0, k) { bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
POS(dir_inum, 0), 0, k) {
if (k.k->p.inode > dir_inum) if (k.k->p.inode > dir_inum)
break; break;
...@@ -344,7 +348,7 @@ int bch2_empty_dir(struct bch_fs *c, u64 dir_inum) ...@@ -344,7 +348,7 @@ int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
break; break;
} }
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return ret; return ret;
} }
...@@ -353,7 +357,8 @@ int bch2_readdir(struct bch_fs *c, struct file *file, ...@@ -353,7 +357,8 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
struct dir_context *ctx) struct dir_context *ctx)
{ {
struct bch_inode_info *inode = file_bch_inode(file); struct bch_inode_info *inode = file_bch_inode(file);
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_s_c_dirent dirent; struct bkey_s_c_dirent dirent;
unsigned len; unsigned len;
...@@ -361,7 +366,9 @@ int bch2_readdir(struct bch_fs *c, struct file *file, ...@@ -361,7 +366,9 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
if (!dir_emit_dots(file, ctx)) if (!dir_emit_dots(file, ctx))
return 0; return 0;
for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
POS(inode->v.i_ino, ctx->pos), 0, k) { POS(inode->v.i_ino, ctx->pos), 0, k) {
if (k.k->type != KEY_TYPE_dirent) if (k.k->type != KEY_TYPE_dirent)
continue; continue;
...@@ -387,7 +394,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file, ...@@ -387,7 +394,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
ctx->pos = k.k->p.offset + 1; ctx->pos = k.k->p.offset + 1;
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return 0; return 0;
} }
...@@ -398,7 +398,8 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf, ...@@ -398,7 +398,8 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
/* recovery read path: */ /* recovery read path: */
int bch2_ec_read_extent(struct bch_fs *c, struct bch_read_bio *rbio) int bch2_ec_read_extent(struct bch_fs *c, struct bch_read_bio *rbio)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct ec_stripe_buf *buf; struct ec_stripe_buf *buf;
struct closure cl; struct closure cl;
struct bkey_s_c k; struct bkey_s_c k;
...@@ -419,19 +420,21 @@ int bch2_ec_read_extent(struct bch_fs *c, struct bch_read_bio *rbio) ...@@ -419,19 +420,21 @@ int bch2_ec_read_extent(struct bch_fs *c, struct bch_read_bio *rbio)
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
bch2_btree_iter_init(&iter, c, BTREE_ID_EC, bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_EC,
POS(0, stripe_idx), POS(0, stripe_idx),
BTREE_ITER_SLOTS); BTREE_ITER_SLOTS);
k = bch2_btree_iter_peek_slot(&iter); k = bch2_btree_iter_peek_slot(iter);
if (btree_iter_err(k) || k.k->type != KEY_TYPE_stripe) { if (btree_iter_err(k) || k.k->type != KEY_TYPE_stripe) {
__bcache_io_error(c, __bcache_io_error(c,
"error doing reconstruct read: stripe not found"); "error doing reconstruct read: stripe not found");
kfree(buf); kfree(buf);
return bch2_btree_iter_unlock(&iter) ?: -EIO; return bch2_trans_exit(&trans) ?: -EIO;
} }
bkey_reassemble(&buf->key.k_i, k); bkey_reassemble(&buf->key.k_i, k);
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
v = &buf->key.v; v = &buf->key.v;
...@@ -1238,7 +1241,8 @@ static void bch2_stripe_read_key(struct bch_fs *c, struct bkey_s_c k) ...@@ -1238,7 +1241,8 @@ static void bch2_stripe_read_key(struct bch_fs *c, struct bkey_s_c k)
int bch2_stripes_read(struct bch_fs *c, struct list_head *journal_replay_list) int bch2_stripes_read(struct bch_fs *c, struct list_head *journal_replay_list)
{ {
struct journal_replay *r; struct journal_replay *r;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
...@@ -1246,12 +1250,14 @@ int bch2_stripes_read(struct bch_fs *c, struct list_head *journal_replay_list) ...@@ -1246,12 +1250,14 @@ int bch2_stripes_read(struct bch_fs *c, struct list_head *journal_replay_list)
if (ret) if (ret)
return ret; return ret;
for_each_btree_key(&iter, c, BTREE_ID_EC, POS_MIN, 0, k) { bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN, 0, k) {
bch2_stripe_read_key(c, k); bch2_stripe_read_key(c, k);
bch2_btree_iter_cond_resched(&iter); bch2_trans_cond_resched(&trans);
} }
ret = bch2_btree_iter_unlock(&iter); ret = bch2_trans_exit(&trans);
if (ret) if (ret)
return ret; return ret;
...@@ -1269,17 +1275,20 @@ int bch2_stripes_read(struct bch_fs *c, struct list_head *journal_replay_list) ...@@ -1269,17 +1275,20 @@ int bch2_stripes_read(struct bch_fs *c, struct list_head *journal_replay_list)
int bch2_ec_mem_alloc(struct bch_fs *c, bool gc) int bch2_ec_mem_alloc(struct bch_fs *c, bool gc)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
size_t i, idx = 0; size_t i, idx = 0;
int ret = 0; int ret = 0;
bch2_btree_iter_init(&iter, c, BTREE_ID_EC, POS(0, U64_MAX), 0); bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_EC, POS(0, U64_MAX), 0);
k = bch2_btree_iter_prev(&iter); k = bch2_btree_iter_prev(iter);
if (!IS_ERR_OR_NULL(k.k)) if (!IS_ERR_OR_NULL(k.k))
idx = k.k->p.offset + 1; idx = k.k->p.offset + 1;
ret = bch2_btree_iter_unlock(&iter); ret = bch2_trans_exit(&trans);
if (ret) if (ret)
return ret; return ret;
......
...@@ -1623,14 +1623,17 @@ static bool bch2_extent_merge_inline(struct bch_fs *c, ...@@ -1623,14 +1623,17 @@ static bool bch2_extent_merge_inline(struct bch_fs *c,
bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size, bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size,
unsigned nr_replicas) unsigned nr_replicas)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bpos end = pos; struct bpos end = pos;
struct bkey_s_c k; struct bkey_s_c k;
bool ret = true; bool ret = true;
end.offset += size; end.offset += size;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, pos, bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, pos,
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k) {
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0) if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
break; break;
...@@ -1640,7 +1643,7 @@ bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size, ...@@ -1640,7 +1643,7 @@ bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size,
break; break;
} }
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return ret; return ret;
} }
......
...@@ -997,7 +997,8 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -997,7 +997,8 @@ void bch2_readahead(struct readahead_control *ractl)
struct bch_inode_info *inode = to_bch_ei(ractl->mapping->host); struct bch_inode_info *inode = to_bch_ei(ractl->mapping->host);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_io_opts opts = io_opts(c, inode); struct bch_io_opts opts = io_opts(c, inode);
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct page *page; struct page *page;
struct readpages_iter readpages_iter; struct readpages_iter readpages_iter;
int ret; int ret;
...@@ -1005,7 +1006,9 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -1005,7 +1006,9 @@ void bch2_readahead(struct readahead_control *ractl)
ret = readpages_iter_init(&readpages_iter, ractl); ret = readpages_iter_init(&readpages_iter, ractl);
BUG_ON(ret); BUG_ON(ret);
bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, POS_MIN, bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN,
BTREE_ITER_SLOTS); BTREE_ITER_SLOTS);
bch2_pagecache_add_get(&inode->ei_pagecache_lock); bch2_pagecache_add_get(&inode->ei_pagecache_lock);
...@@ -1027,26 +1030,33 @@ void bch2_readahead(struct readahead_control *ractl) ...@@ -1027,26 +1030,33 @@ void bch2_readahead(struct readahead_control *ractl)
rbio->bio.bi_end_io = bch2_readpages_end_io; rbio->bio.bi_end_io = bch2_readpages_end_io;
__bio_add_page(&rbio->bio, page, PAGE_SIZE, 0); __bio_add_page(&rbio->bio, page, PAGE_SIZE, 0);
bchfs_read(c, &iter, rbio, inode->v.i_ino, &readpages_iter); bchfs_read(c, iter, rbio, inode->v.i_ino, &readpages_iter);
} }
bch2_pagecache_add_put(&inode->ei_pagecache_lock); bch2_pagecache_add_put(&inode->ei_pagecache_lock);
bch2_trans_exit(&trans);
kfree(readpages_iter.pages); kfree(readpages_iter.pages);
} }
static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio, static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio,
u64 inum, struct page *page) u64 inum, struct page *page)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
page_state_init_for_read(page); page_state_init_for_read(page);
rbio->bio.bi_opf = REQ_OP_READ|REQ_SYNC; rbio->bio.bi_opf = REQ_OP_READ|REQ_SYNC;
bio_add_page_contig(&rbio->bio, page); bio_add_page_contig(&rbio->bio, page);
bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, POS_MIN, bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN,
BTREE_ITER_SLOTS); BTREE_ITER_SLOTS);
bchfs_read(c, &iter, rbio, inum, NULL);
bchfs_read(c, iter, rbio, inum, NULL);
bch2_trans_exit(&trans);
} }
static void bch2_read_single_page_end_io(struct bio *bio) static void bch2_read_single_page_end_io(struct bio *bio)
...@@ -2111,7 +2121,7 @@ static int __bch2_fpunch(struct bch_fs *c, struct bch_inode_info *inode, ...@@ -2111,7 +2121,7 @@ static int __bch2_fpunch(struct bch_fs *c, struct bch_inode_info *inode,
if (ret) if (ret)
break; break;
bch2_btree_iter_cond_resched(iter); bch2_trans_cond_resched(&trans);
} }
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
...@@ -2123,13 +2133,14 @@ static inline int range_has_data(struct bch_fs *c, ...@@ -2123,13 +2133,14 @@ static inline int range_has_data(struct bch_fs *c,
struct bpos start, struct bpos start,
struct bpos end) struct bpos end)
{ {
struct btree_trans trans;
struct btree_iter iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, bch2_trans_init(&trans, c);
start, 0, k) {
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, start, 0, k) {
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0) if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
break; break;
...@@ -2139,7 +2150,7 @@ static inline int range_has_data(struct bch_fs *c, ...@@ -2139,7 +2150,7 @@ static inline int range_has_data(struct bch_fs *c,
} }
} }
return bch2_btree_iter_unlock(&iter) ?: ret; return bch2_trans_exit(&trans) ?: ret;
} }
static int __bch2_truncate_page(struct bch_inode_info *inode, static int __bch2_truncate_page(struct bch_inode_info *inode,
...@@ -2464,7 +2475,7 @@ static long bch2_fcollapse(struct bch_inode_info *inode, ...@@ -2464,7 +2475,7 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
* pointers... which isn't a _super_ serious problem... * pointers... which isn't a _super_ serious problem...
*/ */
bch2_btree_iter_cond_resched(src); bch2_trans_cond_resched(&trans);
} }
bch2_trans_unlock(&trans); bch2_trans_unlock(&trans);
...@@ -2709,7 +2720,8 @@ static loff_t bch2_seek_data(struct file *file, u64 offset) ...@@ -2709,7 +2720,8 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
{ {
struct bch_inode_info *inode = file_bch_inode(file); struct bch_inode_info *inode = file_bch_inode(file);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 isize, next_data = MAX_LFS_FILESIZE; u64 isize, next_data = MAX_LFS_FILESIZE;
int ret; int ret;
...@@ -2718,7 +2730,9 @@ static loff_t bch2_seek_data(struct file *file, u64 offset) ...@@ -2718,7 +2730,9 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
if (offset >= isize) if (offset >= isize)
return -ENXIO; return -ENXIO;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode->v.i_ino, offset >> 9), 0, k) { POS(inode->v.i_ino, offset >> 9), 0, k) {
if (k.k->p.inode != inode->v.i_ino) { if (k.k->p.inode != inode->v.i_ino) {
break; break;
...@@ -2729,7 +2743,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset) ...@@ -2729,7 +2743,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
break; break;
} }
ret = bch2_btree_iter_unlock(&iter); ret = bch2_trans_exit(&trans);
if (ret) if (ret)
return ret; return ret;
...@@ -2779,7 +2793,8 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset) ...@@ -2779,7 +2793,8 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
{ {
struct bch_inode_info *inode = file_bch_inode(file); struct bch_inode_info *inode = file_bch_inode(file);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 isize, next_hole = MAX_LFS_FILESIZE; u64 isize, next_hole = MAX_LFS_FILESIZE;
int ret; int ret;
...@@ -2788,7 +2803,9 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset) ...@@ -2788,7 +2803,9 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
if (offset >= isize) if (offset >= isize)
return -ENXIO; return -ENXIO;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode->v.i_ino, offset >> 9), POS(inode->v.i_ino, offset >> 9),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k) {
if (k.k->p.inode != inode->v.i_ino) { if (k.k->p.inode != inode->v.i_ino) {
...@@ -2807,7 +2824,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset) ...@@ -2807,7 +2824,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
} }
} }
ret = bch2_btree_iter_unlock(&iter); ret = bch2_trans_exit(&trans);
if (ret) if (ret)
return ret; return ret;
......
...@@ -157,7 +157,7 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans, ...@@ -157,7 +157,7 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
void *p) void *p)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct btree_iter *iter; struct btree_iter *iter = NULL;
struct bkey_inode_buf *inode_p; struct bkey_inode_buf *inode_p;
int ret; int ret;
...@@ -1193,7 +1193,8 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1193,7 +1193,8 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
{ {
struct bch_fs *c = vinode->i_sb->s_fs_info; struct bch_fs *c = vinode->i_sb->s_fs_info;
struct bch_inode_info *ei = to_bch_ei(vinode); struct bch_inode_info *ei = to_bch_ei(vinode);
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
BKEY_PADDED(k) tmp; BKEY_PADDED(k) tmp;
bool have_extent = false; bool have_extent = false;
...@@ -1206,7 +1207,9 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1206,7 +1207,9 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
if (start + len < start) if (start + len < start)
return -EINVAL; return -EINVAL;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(ei->v.i_ino, start >> 9), 0, k) POS(ei->v.i_ino, start >> 9), 0, k)
if (bkey_extent_is_data(k.k) || if (bkey_extent_is_data(k.k) ||
k.k->type == KEY_TYPE_reservation) { k.k->type == KEY_TYPE_reservation) {
...@@ -1227,7 +1230,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1227,7 +1230,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
if (have_extent) if (have_extent)
ret = bch2_fill_extent(info, &tmp.k, FIEMAP_EXTENT_LAST); ret = bch2_fill_extent(info, &tmp.k, FIEMAP_EXTENT_LAST);
out: out:
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
......
This diff is collapsed.
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#ifndef _BCACHEFS_FSCK_H #ifndef _BCACHEFS_FSCK_H
#define _BCACHEFS_FSCK_H #define _BCACHEFS_FSCK_H
s64 bch2_count_inode_sectors(struct bch_fs *, u64);
int bch2_fsck(struct bch_fs *); int bch2_fsck(struct bch_fs *);
#endif /* _BCACHEFS_FSCK_H */ #endif /* _BCACHEFS_FSCK_H */
...@@ -447,13 +447,15 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr) ...@@ -447,13 +447,15 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr, int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr,
struct bch_inode_unpacked *inode) struct bch_inode_unpacked *inode)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = -ENOENT; int ret = -ENOENT;
for_each_btree_key(&iter, c, BTREE_ID_INODES, bch2_trans_init(&trans, c);
POS(inode_nr, 0),
BTREE_ITER_SLOTS, k) { for_each_btree_key(&trans, iter, BTREE_ID_INODES,
POS(inode_nr, 0), BTREE_ITER_SLOTS, k) {
switch (k.k->type) { switch (k.k->type) {
case KEY_TYPE_inode: case KEY_TYPE_inode:
ret = bch2_inode_unpack(bkey_s_c_to_inode(k), inode); ret = bch2_inode_unpack(bkey_s_c_to_inode(k), inode);
...@@ -466,7 +468,7 @@ int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr, ...@@ -466,7 +468,7 @@ int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr,
break; break;
} }
return bch2_btree_iter_unlock(&iter) ?: ret; return bch2_trans_exit(&trans) ?: ret;
} }
#ifdef CONFIG_BCACHEFS_DEBUG #ifdef CONFIG_BCACHEFS_DEBUG
......
...@@ -1263,27 +1263,28 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio ...@@ -1263,27 +1263,28 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio
struct bch_io_failures *failed, struct bch_io_failures *failed,
unsigned flags) unsigned flags)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
BKEY_PADDED(k) tmp; BKEY_PADDED(k) tmp;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
flags &= ~BCH_READ_LAST_FRAGMENT; flags &= ~BCH_READ_LAST_FRAGMENT;
bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
rbio->pos, BTREE_ITER_SLOTS); rbio->pos, BTREE_ITER_SLOTS);
retry: retry:
rbio->bio.bi_status = 0; rbio->bio.bi_status = 0;
k = bch2_btree_iter_peek_slot(&iter); k = bch2_btree_iter_peek_slot(iter);
if (btree_iter_err(k)) { if (btree_iter_err(k))
bch2_btree_iter_unlock(&iter);
goto err; goto err;
}
bkey_reassemble(&tmp.k, k); bkey_reassemble(&tmp.k, k);
k = bkey_i_to_s_c(&tmp.k); k = bkey_i_to_s_c(&tmp.k);
bch2_btree_iter_unlock(&iter); bch2_trans_unlock(&trans);
if (!bkey_extent_is_data(k.k) || if (!bkey_extent_is_data(k.k) ||
!bch2_extent_matches_ptr(c, bkey_i_to_s_c_extent(&tmp.k), !bch2_extent_matches_ptr(c, bkey_i_to_s_c_extent(&tmp.k),
...@@ -1300,25 +1301,30 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio ...@@ -1300,25 +1301,30 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio
goto retry; goto retry;
if (ret) if (ret)
goto err; goto err;
goto out;
err:
rbio->bio.bi_status = BLK_STS_IOERR;
out: out:
bch2_rbio_done(rbio); bch2_rbio_done(rbio);
bch2_trans_exit(&trans);
return;
err:
rbio->bio.bi_status = BLK_STS_IOERR;
goto out;
} }
static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio, static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio,
struct bvec_iter bvec_iter, u64 inode, struct bvec_iter bvec_iter, u64 inode,
struct bch_io_failures *failed, unsigned flags) struct bch_io_failures *failed, unsigned flags)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
bch2_trans_init(&trans, c);
flags &= ~BCH_READ_LAST_FRAGMENT; flags &= ~BCH_READ_LAST_FRAGMENT;
flags |= BCH_READ_MUST_CLONE; flags |= BCH_READ_MUST_CLONE;
retry: retry:
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode, bvec_iter.bi_sector), POS(inode, bvec_iter.bi_sector),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k) {
BKEY_PADDED(k) tmp; BKEY_PADDED(k) tmp;
...@@ -1326,7 +1332,7 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -1326,7 +1332,7 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio,
bkey_reassemble(&tmp.k, k); bkey_reassemble(&tmp.k, k);
k = bkey_i_to_s_c(&tmp.k); k = bkey_i_to_s_c(&tmp.k);
bch2_btree_iter_unlock(&iter); bch2_btree_iter_unlock(iter);
bytes = min_t(unsigned, bvec_iter.bi_size, bytes = min_t(unsigned, bvec_iter.bi_size,
(k.k->p.offset - bvec_iter.bi_sector) << 9); (k.k->p.offset - bvec_iter.bi_sector) << 9);
...@@ -1351,12 +1357,12 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -1351,12 +1357,12 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio,
* If we get here, it better have been because there was an error * If we get here, it better have been because there was an error
* reading a btree node * reading a btree node
*/ */
ret = bch2_btree_iter_unlock(&iter); BUG_ON(!(iter->flags & BTREE_ITER_ERROR));
BUG_ON(!ret); __bcache_io_error(c, "btree IO error");
__bcache_io_error(c, "btree IO error %i", ret);
err: err:
rbio->bio.bi_status = BLK_STS_IOERR; rbio->bio.bi_status = BLK_STS_IOERR;
out: out:
bch2_trans_exit(&trans);
bch2_rbio_done(rbio); bch2_rbio_done(rbio);
} }
...@@ -1859,12 +1865,14 @@ int __bch2_read_extent(struct bch_fs *c, struct bch_read_bio *orig, ...@@ -1859,12 +1865,14 @@ int __bch2_read_extent(struct bch_fs *c, struct bch_read_bio *orig,
void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode) void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
unsigned flags = BCH_READ_RETRY_IF_STALE| unsigned flags = BCH_READ_RETRY_IF_STALE|
BCH_READ_MAY_PROMOTE| BCH_READ_MAY_PROMOTE|
BCH_READ_USER_MAPPED; BCH_READ_USER_MAPPED;
int ret;
bch2_trans_init(&trans, c);
BUG_ON(rbio->_state); BUG_ON(rbio->_state);
BUG_ON(flags & BCH_READ_NODECODE); BUG_ON(flags & BCH_READ_NODECODE);
...@@ -1873,7 +1881,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode) ...@@ -1873,7 +1881,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
rbio->c = c; rbio->c = c;
rbio->start_time = local_clock(); rbio->start_time = local_clock();
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode, rbio->bio.bi_iter.bi_sector), POS(inode, rbio->bio.bi_iter.bi_sector),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k) {
BKEY_PADDED(k) tmp; BKEY_PADDED(k) tmp;
...@@ -1885,7 +1893,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode) ...@@ -1885,7 +1893,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
*/ */
bkey_reassemble(&tmp.k, k); bkey_reassemble(&tmp.k, k);
k = bkey_i_to_s_c(&tmp.k); k = bkey_i_to_s_c(&tmp.k);
bch2_btree_iter_unlock(&iter); bch2_btree_iter_unlock(iter);
bytes = min_t(unsigned, rbio->bio.bi_iter.bi_size, bytes = min_t(unsigned, rbio->bio.bi_iter.bi_size,
(k.k->p.offset - rbio->bio.bi_iter.bi_sector) << 9); (k.k->p.offset - rbio->bio.bi_iter.bi_sector) << 9);
...@@ -1907,9 +1915,10 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode) ...@@ -1907,9 +1915,10 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
* If we get here, it better have been because there was an error * If we get here, it better have been because there was an error
* reading a btree node * reading a btree node
*/ */
ret = bch2_btree_iter_unlock(&iter); BUG_ON(!(iter->flags & BTREE_ITER_ERROR));
BUG_ON(!ret); bcache_io_error(c, &rbio->bio, "btree IO error");
bcache_io_error(c, &rbio->bio, "btree IO error %i", ret);
bch2_trans_exit(&trans);
bch2_rbio_done(rbio); bch2_rbio_done(rbio);
} }
......
...@@ -62,9 +62,12 @@ static void journal_seq_blacklist_flush(struct journal *j, ...@@ -62,9 +62,12 @@ static void journal_seq_blacklist_flush(struct journal *j,
closure_init_stack(&cl); closure_init_stack(&cl);
for (i = 0;; i++) { for (i = 0;; i++) {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct btree *b; struct btree *b;
bch2_trans_init(&trans, c);
mutex_lock(&j->blacklist_lock); mutex_lock(&j->blacklist_lock);
if (i >= bl->nr_entries) { if (i >= bl->nr_entries) {
mutex_unlock(&j->blacklist_lock); mutex_unlock(&j->blacklist_lock);
...@@ -73,17 +76,17 @@ static void journal_seq_blacklist_flush(struct journal *j, ...@@ -73,17 +76,17 @@ static void journal_seq_blacklist_flush(struct journal *j,
n = bl->entries[i]; n = bl->entries[i];
mutex_unlock(&j->blacklist_lock); mutex_unlock(&j->blacklist_lock);
__bch2_btree_iter_init(&iter, c, n.btree_id, n.pos, iter = bch2_trans_get_node_iter(&trans, n.btree_id, n.pos,
0, 0, BTREE_ITER_NODES); 0, 0, 0);
b = bch2_btree_iter_peek_node(&iter); b = bch2_btree_iter_peek_node(iter);
/* The node might have already been rewritten: */ /* The node might have already been rewritten: */
if (b->data->keys.seq == n.seq) { if (b->data->keys.seq == n.seq) {
ret = bch2_btree_node_rewrite(c, &iter, n.seq, 0); ret = bch2_btree_node_rewrite(c, iter, n.seq, 0);
if (ret) { if (ret) {
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
bch2_fs_fatal_error(c, bch2_fs_fatal_error(c,
"error %i rewriting btree node with blacklisted journal seq", "error %i rewriting btree node with blacklisted journal seq",
ret); ret);
...@@ -92,7 +95,7 @@ static void journal_seq_blacklist_flush(struct journal *j, ...@@ -92,7 +95,7 @@ static void journal_seq_blacklist_flush(struct journal *j,
} }
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
} }
for (i = 0;; i++) { for (i = 0;; i++) {
......
...@@ -106,7 +106,8 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -106,7 +106,8 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct closure cl; struct closure cl;
struct btree *b; struct btree *b;
unsigned id; unsigned id;
...@@ -116,13 +117,15 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -116,13 +117,15 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
if (flags & BCH_FORCE_IF_METADATA_LOST) if (flags & BCH_FORCE_IF_METADATA_LOST)
return -EINVAL; return -EINVAL;
bch2_trans_init(&trans, c);
closure_init_stack(&cl); closure_init_stack(&cl);
mutex_lock(&c->replicas_gc_lock); mutex_lock(&c->replicas_gc_lock);
bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE); bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE);
for (id = 0; id < BTREE_ID_NR; id++) { for (id = 0; id < BTREE_ID_NR; id++) {
for_each_btree_node(&iter, c, id, POS_MIN, BTREE_ITER_PREFETCH, b) { for_each_btree_node(&trans, iter, id, POS_MIN,
BTREE_ITER_PREFETCH, b) {
__BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX) tmp; __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX) tmp;
struct bkey_i_btree_ptr *new_key; struct bkey_i_btree_ptr *new_key;
retry: retry:
...@@ -134,7 +137,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -134,7 +137,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
* but got -EINTR after upgrading the iter, but * but got -EINTR after upgrading the iter, but
* then raced and the node is now gone: * then raced and the node is now gone:
*/ */
bch2_btree_iter_downgrade(&iter); bch2_btree_iter_downgrade(iter);
ret = bch2_mark_bkey_replicas(c, bkey_i_to_s_c(&b->key)); ret = bch2_mark_bkey_replicas(c, bkey_i_to_s_c(&b->key));
if (ret) if (ret)
...@@ -148,16 +151,16 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -148,16 +151,16 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
if (ret) if (ret)
goto err; goto err;
ret = bch2_btree_node_update_key(c, &iter, b, new_key); ret = bch2_btree_node_update_key(c, iter, b, new_key);
if (ret == -EINTR) { if (ret == -EINTR) {
b = bch2_btree_iter_peek_node(&iter); b = bch2_btree_iter_peek_node(iter);
goto retry; goto retry;
} }
if (ret) if (ret)
goto err; goto err;
} }
} }
bch2_btree_iter_unlock(&iter); bch2_trans_iter_free(&trans, iter);
} }
/* flush relevant btree updates */ /* flush relevant btree updates */
...@@ -171,14 +174,13 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -171,14 +174,13 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
} }
ret = 0; ret = 0;
out: err:
bch2_trans_exit(&trans);
ret = bch2_replicas_gc_end(c, ret); ret = bch2_replicas_gc_end(c, ret);
mutex_unlock(&c->replicas_gc_lock); mutex_unlock(&c->replicas_gc_lock);
return ret; return ret;
err:
bch2_btree_iter_unlock(&iter);
goto out;
} }
int bch2_dev_data_drop(struct bch_fs *c, unsigned dev_idx, int flags) int bch2_dev_data_drop(struct bch_fs *c, unsigned dev_idx, int flags)
......
...@@ -485,6 +485,8 @@ int bch2_move_data(struct bch_fs *c, ...@@ -485,6 +485,8 @@ int bch2_move_data(struct bch_fs *c,
struct moving_context ctxt = { .stats = stats }; struct moving_context ctxt = { .stats = stats };
struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts); struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
BKEY_PADDED(k) tmp; BKEY_PADDED(k) tmp;
struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
struct data_opts data_opts; struct data_opts data_opts;
enum data_cmd data_cmd; enum data_cmd data_cmd;
...@@ -495,8 +497,13 @@ int bch2_move_data(struct bch_fs *c, ...@@ -495,8 +497,13 @@ int bch2_move_data(struct bch_fs *c,
INIT_LIST_HEAD(&ctxt.reads); INIT_LIST_HEAD(&ctxt.reads);
init_waitqueue_head(&ctxt.wait); init_waitqueue_head(&ctxt.wait);
bch2_trans_init(&trans, c);
stats->data_type = BCH_DATA_USER; stats->data_type = BCH_DATA_USER;
bch2_btree_iter_init(&stats->iter, c, BTREE_ID_EXTENTS, start, stats->btree_id = BTREE_ID_EXTENTS;
stats->pos = POS_MIN;
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, start,
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
if (rate) if (rate)
...@@ -507,7 +514,7 @@ int bch2_move_data(struct bch_fs *c, ...@@ -507,7 +514,7 @@ int bch2_move_data(struct bch_fs *c,
delay = rate ? bch2_ratelimit_delay(rate) : 0; delay = rate ? bch2_ratelimit_delay(rate) : 0;
if (delay) { if (delay) {
bch2_btree_iter_unlock(&stats->iter); bch2_trans_unlock(&trans);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
} }
...@@ -520,13 +527,16 @@ int bch2_move_data(struct bch_fs *c, ...@@ -520,13 +527,16 @@ int bch2_move_data(struct bch_fs *c,
schedule_timeout(delay); schedule_timeout(delay);
if (unlikely(freezing(current))) { if (unlikely(freezing(current))) {
bch2_btree_iter_unlock(&stats->iter); bch2_trans_unlock(&trans);
move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads)); move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads));
try_to_freeze(); try_to_freeze();
} }
} while (delay); } while (delay);
peek: peek:
k = bch2_btree_iter_peek(&stats->iter); k = bch2_btree_iter_peek(iter);
stats->pos = iter->pos;
if (!k.k) if (!k.k)
break; break;
ret = btree_iter_err(k); ret = btree_iter_err(k);
...@@ -542,7 +552,7 @@ int bch2_move_data(struct bch_fs *c, ...@@ -542,7 +552,7 @@ int bch2_move_data(struct bch_fs *c,
struct bch_inode_unpacked inode; struct bch_inode_unpacked inode;
/* don't hold btree locks while looking up inode: */ /* don't hold btree locks while looking up inode: */
bch2_btree_iter_unlock(&stats->iter); bch2_trans_unlock(&trans);
io_opts = bch2_opts_to_inode_opts(c->opts); io_opts = bch2_opts_to_inode_opts(c->opts);
if (!bch2_inode_find_by_inum(c, k.k->p.inode, &inode)) if (!bch2_inode_find_by_inum(c, k.k->p.inode, &inode))
...@@ -567,7 +577,7 @@ int bch2_move_data(struct bch_fs *c, ...@@ -567,7 +577,7 @@ int bch2_move_data(struct bch_fs *c,
/* unlock before doing IO: */ /* unlock before doing IO: */
bkey_reassemble(&tmp.k, k); bkey_reassemble(&tmp.k, k);
k = bkey_i_to_s_c(&tmp.k); k = bkey_i_to_s_c(&tmp.k);
bch2_btree_iter_unlock(&stats->iter); bch2_trans_unlock(&trans);
ret2 = bch2_move_extent(c, &ctxt, wp, io_opts, ret2 = bch2_move_extent(c, &ctxt, wp, io_opts,
bkey_s_c_to_extent(k), bkey_s_c_to_extent(k),
...@@ -589,11 +599,11 @@ int bch2_move_data(struct bch_fs *c, ...@@ -589,11 +599,11 @@ int bch2_move_data(struct bch_fs *c,
atomic64_add(k.k->size * bch2_bkey_nr_dirty_ptrs(k), atomic64_add(k.k->size * bch2_bkey_nr_dirty_ptrs(k),
&stats->sectors_seen); &stats->sectors_seen);
next_nondata: next_nondata:
bch2_btree_iter_next(&stats->iter); bch2_btree_iter_next(iter);
bch2_btree_iter_cond_resched(&stats->iter); bch2_trans_cond_resched(&trans);
} }
out: out:
bch2_btree_iter_unlock(&stats->iter); bch2_trans_exit(&trans);
move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads)); move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads));
closure_sync(&ctxt.cl); closure_sync(&ctxt.cl);
...@@ -609,20 +619,23 @@ int bch2_move_data(struct bch_fs *c, ...@@ -609,20 +619,23 @@ int bch2_move_data(struct bch_fs *c,
static int bch2_gc_data_replicas(struct bch_fs *c) static int bch2_gc_data_replicas(struct bch_fs *c)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
bch2_trans_init(&trans, c);
mutex_lock(&c->replicas_gc_lock); mutex_lock(&c->replicas_gc_lock);
bch2_replicas_gc_start(c, (1 << BCH_DATA_USER)|(1 << BCH_DATA_CACHED)); bch2_replicas_gc_start(c, (1 << BCH_DATA_USER)|(1 << BCH_DATA_CACHED));
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN,
BTREE_ITER_PREFETCH, k) { BTREE_ITER_PREFETCH, k) {
ret = bch2_mark_bkey_replicas(c, k); ret = bch2_mark_bkey_replicas(c, k);
if (ret) if (ret)
break; break;
} }
ret = bch2_btree_iter_unlock(&iter) ?: ret; ret = bch2_trans_exit(&trans) ?: ret;
bch2_replicas_gc_end(c, ret); bch2_replicas_gc_end(c, ret);
mutex_unlock(&c->replicas_gc_lock); mutex_unlock(&c->replicas_gc_lock);
...@@ -632,24 +645,30 @@ static int bch2_gc_data_replicas(struct bch_fs *c) ...@@ -632,24 +645,30 @@ static int bch2_gc_data_replicas(struct bch_fs *c)
static int bch2_gc_btree_replicas(struct bch_fs *c) static int bch2_gc_btree_replicas(struct bch_fs *c)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct btree *b; struct btree *b;
unsigned id; unsigned id;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c);
mutex_lock(&c->replicas_gc_lock); mutex_lock(&c->replicas_gc_lock);
bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE); bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE);
for (id = 0; id < BTREE_ID_NR; id++) { for (id = 0; id < BTREE_ID_NR; id++) {
for_each_btree_node(&iter, c, id, POS_MIN, BTREE_ITER_PREFETCH, b) { for_each_btree_node(&trans, iter, id, POS_MIN,
BTREE_ITER_PREFETCH, b) {
ret = bch2_mark_bkey_replicas(c, bkey_i_to_s_c(&b->key)); ret = bch2_mark_bkey_replicas(c, bkey_i_to_s_c(&b->key));
bch2_btree_iter_cond_resched(&iter); bch2_trans_cond_resched(&trans);
} }
ret = bch2_btree_iter_unlock(&iter) ?: ret; ret = bch2_trans_iter_free(&trans, iter) ?: ret;
} }
bch2_trans_exit(&trans);
bch2_replicas_gc_end(c, ret); bch2_replicas_gc_end(c, ret);
mutex_unlock(&c->replicas_gc_lock); mutex_unlock(&c->replicas_gc_lock);
...@@ -662,16 +681,25 @@ static int bch2_move_btree(struct bch_fs *c, ...@@ -662,16 +681,25 @@ static int bch2_move_btree(struct bch_fs *c,
struct bch_move_stats *stats) struct bch_move_stats *stats)
{ {
struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts); struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
struct btree_trans trans;
struct btree_iter *iter;
struct btree *b; struct btree *b;
unsigned id; unsigned id;
struct data_opts data_opts; struct data_opts data_opts;
enum data_cmd cmd; enum data_cmd cmd;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c);
stats->data_type = BCH_DATA_BTREE; stats->data_type = BCH_DATA_BTREE;
for (id = 0; id < BTREE_ID_NR; id++) { for (id = 0; id < BTREE_ID_NR; id++) {
for_each_btree_node(&stats->iter, c, id, POS_MIN, BTREE_ITER_PREFETCH, b) { stats->btree_id = id;
for_each_btree_node(&trans, iter, id, POS_MIN,
BTREE_ITER_PREFETCH, b) {
stats->pos = iter->pos;
switch ((cmd = pred(c, arg, switch ((cmd = pred(c, arg,
bkey_i_to_s_c(&b->key), bkey_i_to_s_c(&b->key),
&io_opts, &data_opts))) { &io_opts, &data_opts))) {
...@@ -686,15 +714,17 @@ static int bch2_move_btree(struct bch_fs *c, ...@@ -686,15 +714,17 @@ static int bch2_move_btree(struct bch_fs *c,
BUG(); BUG();
} }
ret = bch2_btree_node_rewrite(c, &stats->iter, ret = bch2_btree_node_rewrite(c, iter,
b->data->keys.seq, 0) ?: ret; b->data->keys.seq, 0) ?: ret;
next: next:
bch2_btree_iter_cond_resched(&stats->iter); bch2_trans_cond_resched(&trans);
} }
ret = bch2_btree_iter_unlock(&stats->iter) ?: ret; ret = bch2_trans_iter_free(&trans, iter) ?: ret;
} }
bch2_trans_exit(&trans);
return ret; return ret;
} }
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
struct bch_move_stats { struct bch_move_stats {
enum bch_data_type data_type; enum bch_data_type data_type;
struct btree_iter iter; enum btree_id btree_id;
struct bpos pos;
atomic64_t keys_moved; atomic64_t keys_moved;
atomic64_t sectors_moved; atomic64_t sectors_moved;
......
...@@ -356,11 +356,14 @@ static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k) ...@@ -356,11 +356,14 @@ static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k)
static int bch2_quota_init_type(struct bch_fs *c, enum quota_types type) static int bch2_quota_init_type(struct bch_fs *c, enum quota_types type)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
for_each_btree_key(&iter, c, BTREE_ID_QUOTAS, POS(type, 0), bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_QUOTAS, POS(type, 0),
BTREE_ITER_PREFETCH, k) { BTREE_ITER_PREFETCH, k) {
if (k.k->p.inode != type) if (k.k->p.inode != type)
break; break;
...@@ -370,7 +373,7 @@ static int bch2_quota_init_type(struct bch_fs *c, enum quota_types type) ...@@ -370,7 +373,7 @@ static int bch2_quota_init_type(struct bch_fs *c, enum quota_types type)
break; break;
} }
return bch2_btree_iter_unlock(&iter) ?: ret; return bch2_trans_exit(&trans) ?: ret;
} }
void bch2_fs_quota_exit(struct bch_fs *c) void bch2_fs_quota_exit(struct bch_fs *c)
...@@ -414,7 +417,8 @@ int bch2_fs_quota_read(struct bch_fs *c) ...@@ -414,7 +417,8 @@ int bch2_fs_quota_read(struct bch_fs *c)
{ {
unsigned i, qtypes = enabled_qtypes(c); unsigned i, qtypes = enabled_qtypes(c);
struct bch_memquota_type *q; struct bch_memquota_type *q;
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bch_inode_unpacked u; struct bch_inode_unpacked u;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
...@@ -429,7 +433,9 @@ int bch2_fs_quota_read(struct bch_fs *c) ...@@ -429,7 +433,9 @@ int bch2_fs_quota_read(struct bch_fs *c)
return ret; return ret;
} }
for_each_btree_key(&iter, c, BTREE_ID_INODES, POS_MIN, bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_INODES, POS_MIN,
BTREE_ITER_PREFETCH, k) { BTREE_ITER_PREFETCH, k) {
switch (k.k->type) { switch (k.k->type) {
case KEY_TYPE_inode: case KEY_TYPE_inode:
...@@ -443,7 +449,7 @@ int bch2_fs_quota_read(struct bch_fs *c) ...@@ -443,7 +449,7 @@ int bch2_fs_quota_read(struct bch_fs *c)
KEY_TYPE_QUOTA_NOCHECK); KEY_TYPE_QUOTA_NOCHECK);
} }
} }
return bch2_btree_iter_unlock(&iter) ?: ret; return bch2_trans_exit(&trans) ?: ret;
} }
/* Enable/disable/delete quotas for an entire filesystem: */ /* Enable/disable/delete quotas for an entire filesystem: */
......
...@@ -289,8 +289,8 @@ ssize_t bch2_rebalance_work_show(struct bch_fs *c, char *buf) ...@@ -289,8 +289,8 @@ ssize_t bch2_rebalance_work_show(struct bch_fs *c, char *buf)
case REBALANCE_RUNNING: case REBALANCE_RUNNING:
pr_buf(&out, "running\n"); pr_buf(&out, "running\n");
pr_buf(&out, "pos %llu:%llu\n", pr_buf(&out, "pos %llu:%llu\n",
r->move_stats.iter.pos.inode, r->move_stats.pos.inode,
r->move_stats.iter.pos.offset); r->move_stats.pos.offset);
break; break;
} }
......
...@@ -203,13 +203,16 @@ int bch2_hash_needs_whiteout(struct btree_trans *trans, ...@@ -203,13 +203,16 @@ int bch2_hash_needs_whiteout(struct btree_trans *trans,
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k) { for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k) {
if (k.k->type != desc.key_type && if (k.k->type != desc.key_type &&
k.k->type != KEY_TYPE_whiteout) k.k->type != KEY_TYPE_whiteout)
return false; break;
if (k.k->type == desc.key_type && if (k.k->type == desc.key_type &&
desc.hash_bkey(info, k) <= start->pos.offset) desc.hash_bkey(info, k) <= start->pos.offset) {
return true; bch2_trans_iter_free_on_commit(trans, iter);
return 1;
}
} }
return btree_iter_err(k);
return bch2_trans_iter_free(trans, iter);
} }
static __always_inline static __always_inline
...@@ -220,6 +223,8 @@ int bch2_hash_set(struct btree_trans *trans, ...@@ -220,6 +223,8 @@ int bch2_hash_set(struct btree_trans *trans,
{ {
struct btree_iter *iter, *slot = NULL; struct btree_iter *iter, *slot = NULL;
struct bkey_s_c k; struct bkey_s_c k;
bool found = false;
int ret = 0;
iter = bch2_trans_get_iter(trans, desc.btree_id, iter = bch2_trans_get_iter(trans, desc.btree_id,
POS(inode, desc.hash_bkey(info, bkey_i_to_s_c(insert))), POS(inode, desc.hash_bkey(info, bkey_i_to_s_c(insert))),
...@@ -250,21 +255,30 @@ int bch2_hash_set(struct btree_trans *trans, ...@@ -250,21 +255,30 @@ int bch2_hash_set(struct btree_trans *trans,
goto not_found; goto not_found;
} }
return btree_iter_err(k) ?: -ENOSPC; if (slot)
not_found: bch2_trans_iter_free(trans, iter);
if (flags & BCH_HASH_SET_MUST_REPLACE)
return -ENOENT;
insert->k.p = slot->pos; return bch2_trans_iter_free(trans, iter) ?: -ENOSPC;
bch2_trans_update(trans, BTREE_INSERT_ENTRY(slot, insert));
return 0;
found: found:
if (flags & BCH_HASH_SET_MUST_CREATE) found = true;
return -EEXIST; not_found:
if (!found && (flags & BCH_HASH_SET_MUST_REPLACE)) {
ret = -ENOENT;
} else if (found && (flags & BCH_HASH_SET_MUST_CREATE)) {
ret = -EEXIST;
} else {
if (!found && slot) {
bch2_trans_iter_free(trans, iter);
iter = slot;
}
insert->k.p = iter->pos; insert->k.p = iter->pos;
bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, insert)); bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, insert));
return 0; bch2_trans_iter_free_on_commit(trans, iter);
}
return ret;
} }
static __always_inline static __always_inline
......
...@@ -282,7 +282,8 @@ static ssize_t show_fs_alloc_debug(struct bch_fs *c, char *buf) ...@@ -282,7 +282,8 @@ static ssize_t show_fs_alloc_debug(struct bch_fs *c, char *buf)
static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf) static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 nr_uncompressed_extents = 0, uncompressed_sectors = 0, u64 nr_uncompressed_extents = 0, uncompressed_sectors = 0,
nr_compressed_extents = 0, nr_compressed_extents = 0,
...@@ -292,7 +293,9 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf) ...@@ -292,7 +293,9 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
if (!test_bit(BCH_FS_STARTED, &c->flags)) if (!test_bit(BCH_FS_STARTED, &c->flags))
return -EPERM; return -EPERM;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS_MIN, 0, k) bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN, 0, k)
if (k.k->type == KEY_TYPE_extent) { if (k.k->type == KEY_TYPE_extent) {
struct bkey_s_c_extent e = bkey_s_c_to_extent(k); struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
const union bch_extent_entry *entry; const union bch_extent_entry *entry;
...@@ -314,7 +317,7 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf) ...@@ -314,7 +317,7 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
break; break;
} }
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
return scnprintf(buf, PAGE_SIZE, return scnprintf(buf, PAGE_SIZE,
"uncompressed data:\n" "uncompressed data:\n"
......
...@@ -89,11 +89,14 @@ static void test_delete_written(struct bch_fs *c, u64 nr) ...@@ -89,11 +89,14 @@ static void test_delete_written(struct bch_fs *c, u64 nr)
static void test_iterate(struct bch_fs *c, u64 nr) static void test_iterate(struct bch_fs *c, u64 nr)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret; int ret;
bch2_trans_init(&trans, c);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test keys"); pr_info("inserting test keys");
...@@ -113,28 +116,31 @@ static void test_iterate(struct bch_fs *c, u64 nr) ...@@ -113,28 +116,31 @@ static void test_iterate(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS(0, 0), 0, k) for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS(0, 0), 0, k)
BUG_ON(k.k->p.offset != i++); BUG_ON(k.k->p.offset != i++);
bch2_btree_iter_unlock(&iter);
BUG_ON(i != nr); BUG_ON(i != nr);
pr_info("iterating backwards"); pr_info("iterating backwards");
while (!IS_ERR_OR_NULL((k = bch2_btree_iter_prev(&iter)).k)) while (!IS_ERR_OR_NULL((k = bch2_btree_iter_prev(iter)).k))
BUG_ON(k.k->p.offset != --i); BUG_ON(k.k->p.offset != --i);
bch2_btree_iter_unlock(&iter);
BUG_ON(i); BUG_ON(i);
bch2_trans_exit(&trans);
} }
static void test_iterate_extents(struct bch_fs *c, u64 nr) static void test_iterate_extents(struct bch_fs *c, u64 nr)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret; int ret;
bch2_trans_init(&trans, c);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test extents"); pr_info("inserting test extents");
...@@ -155,32 +161,35 @@ static void test_iterate_extents(struct bch_fs *c, u64 nr) ...@@ -155,32 +161,35 @@ static void test_iterate_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS(0, 0), 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS(0, 0), 0, k) {
BUG_ON(bkey_start_offset(k.k) != i); BUG_ON(bkey_start_offset(k.k) != i);
i = k.k->p.offset; i = k.k->p.offset;
} }
bch2_btree_iter_unlock(&iter);
BUG_ON(i != nr); BUG_ON(i != nr);
pr_info("iterating backwards"); pr_info("iterating backwards");
while (!IS_ERR_OR_NULL((k = bch2_btree_iter_prev(&iter)).k)) { while (!IS_ERR_OR_NULL((k = bch2_btree_iter_prev(iter)).k)) {
BUG_ON(k.k->p.offset != i); BUG_ON(k.k->p.offset != i);
i = bkey_start_offset(k.k); i = bkey_start_offset(k.k);
} }
bch2_btree_iter_unlock(&iter);
BUG_ON(i); BUG_ON(i);
bch2_trans_exit(&trans);
} }
static void test_iterate_slots(struct bch_fs *c, u64 nr) static void test_iterate_slots(struct bch_fs *c, u64 nr)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret; int ret;
bch2_trans_init(&trans, c);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test keys"); pr_info("inserting test keys");
...@@ -200,11 +209,11 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr) ...@@ -200,11 +209,11 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS(0, 0), 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS(0, 0), 0, k) {
BUG_ON(k.k->p.offset != i); BUG_ON(k.k->p.offset != i);
i += 2; i += 2;
} }
bch2_btree_iter_unlock(&iter); bch2_trans_iter_free(&trans, iter);
BUG_ON(i != nr * 2); BUG_ON(i != nr * 2);
...@@ -212,7 +221,7 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr) ...@@ -212,7 +221,7 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS(0, 0), for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS(0, 0),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k) {
BUG_ON(bkey_deleted(k.k) != (i & 1)); BUG_ON(bkey_deleted(k.k) != (i & 1));
BUG_ON(k.k->p.offset != i++); BUG_ON(k.k->p.offset != i++);
...@@ -220,16 +229,20 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr) ...@@ -220,16 +229,20 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
if (i == nr * 2) if (i == nr * 2)
break; break;
} }
bch2_btree_iter_unlock(&iter);
bch2_trans_exit(&trans);
} }
static void test_iterate_slots_extents(struct bch_fs *c, u64 nr) static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret; int ret;
bch2_trans_init(&trans, c);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test keys"); pr_info("inserting test keys");
...@@ -250,12 +263,12 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr) ...@@ -250,12 +263,12 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS(0, 0), 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS(0, 0), 0, k) {
BUG_ON(bkey_start_offset(k.k) != i + 8); BUG_ON(bkey_start_offset(k.k) != i + 8);
BUG_ON(k.k->size != 8); BUG_ON(k.k->size != 8);
i += 16; i += 16;
} }
bch2_btree_iter_unlock(&iter); bch2_trans_iter_free(&trans, iter);
BUG_ON(i != nr); BUG_ON(i != nr);
...@@ -263,7 +276,7 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr) ...@@ -263,7 +276,7 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS(0, 0), for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS(0, 0),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k) {
BUG_ON(bkey_deleted(k.k) != !(i % 16)); BUG_ON(bkey_deleted(k.k) != !(i % 16));
...@@ -274,7 +287,8 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr) ...@@ -274,7 +287,8 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
if (i == nr) if (i == nr)
break; break;
} }
bch2_btree_iter_unlock(&iter);
bch2_trans_exit(&trans);
} }
/* /*
...@@ -283,34 +297,40 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr) ...@@ -283,34 +297,40 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
*/ */
static void test_peek_end(struct bch_fs *c, u64 nr) static void test_peek_end(struct bch_fs *c, u64 nr)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
bch2_btree_iter_init(&iter, c, BTREE_ID_DIRENTS, POS_MIN, 0); bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS, POS_MIN, 0);
k = bch2_btree_iter_peek(&iter); k = bch2_btree_iter_peek(iter);
BUG_ON(k.k); BUG_ON(k.k);
k = bch2_btree_iter_peek(&iter); k = bch2_btree_iter_peek(iter);
BUG_ON(k.k); BUG_ON(k.k);
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
} }
static void test_peek_end_extents(struct bch_fs *c, u64 nr) static void test_peek_end_extents(struct bch_fs *c, u64 nr)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, POS_MIN, 0); bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN, 0);
k = bch2_btree_iter_peek(&iter); k = bch2_btree_iter_peek(iter);
BUG_ON(k.k); BUG_ON(k.k);
k = bch2_btree_iter_peek(&iter); k = bch2_btree_iter_peek(iter);
BUG_ON(k.k); BUG_ON(k.k);
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
} }
/* extent unit tests */ /* extent unit tests */
...@@ -401,32 +421,35 @@ static void rand_insert(struct bch_fs *c, u64 nr) ...@@ -401,32 +421,35 @@ static void rand_insert(struct bch_fs *c, u64 nr)
static void rand_lookup(struct bch_fs *c, u64 nr) static void rand_lookup(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k;
u64 i; u64 i;
for (i = 0; i < nr; i++) { bch2_trans_init(&trans, c);
struct btree_iter iter;
struct bkey_s_c k;
bch2_btree_iter_init(&iter, c, BTREE_ID_DIRENTS, for (i = 0; i < nr; i++) {
iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS,
POS(0, test_rand()), 0); POS(0, test_rand()), 0);
k = bch2_btree_iter_peek(&iter); k = bch2_btree_iter_peek(iter);
bch2_btree_iter_unlock(&iter); bch2_trans_iter_free(&trans, iter);
} }
bch2_trans_exit(&trans);
} }
static void rand_mixed(struct bch_fs *c, u64 nr) static void rand_mixed(struct bch_fs *c, u64 nr)
{ {
int ret;
u64 i;
for (i = 0; i < nr; i++) {
struct btree_trans trans; struct btree_trans trans;
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret;
u64 i;
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for (i = 0; i < nr; i++) {
iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS, iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS,
POS(0, test_rand()), 0); POS(0, test_rand()), 0);
...@@ -443,9 +466,10 @@ static void rand_mixed(struct bch_fs *c, u64 nr) ...@@ -443,9 +466,10 @@ static void rand_mixed(struct bch_fs *c, u64 nr)
BUG_ON(ret); BUG_ON(ret);
} }
bch2_trans_exit(&trans); bch2_trans_iter_free(&trans, iter);
} }
bch2_trans_exit(&trans);
} }
static void rand_delete(struct bch_fs *c, u64 nr) static void rand_delete(struct bch_fs *c, u64 nr)
...@@ -495,12 +519,15 @@ static void seq_insert(struct bch_fs *c, u64 nr) ...@@ -495,12 +519,15 @@ static void seq_insert(struct bch_fs *c, u64 nr)
static void seq_lookup(struct bch_fs *c, u64 nr) static void seq_lookup(struct bch_fs *c, u64 nr)
{ {
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS_MIN, 0, k) bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN, 0, k)
; ;
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
} }
static void seq_overwrite(struct bch_fs *c, u64 nr) static void seq_overwrite(struct bch_fs *c, u64 nr)
......
...@@ -271,12 +271,16 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -271,12 +271,16 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{ {
struct bch_fs *c = dentry->d_sb->s_fs_info; struct bch_fs *c = dentry->d_sb->s_fs_info;
struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); struct bch_inode_info *inode = to_bch_ei(dentry->d_inode);
struct btree_iter iter; struct btree_trans trans;
struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 inum = dentry->d_inode->i_ino; u64 inum = dentry->d_inode->i_ino;
ssize_t ret = 0; ssize_t ret = 0;
for_each_btree_key(&iter, c, BTREE_ID_XATTRS, POS(inum, 0), 0, k) { bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_XATTRS,
POS(inum, 0), 0, k) {
BUG_ON(k.k->p.inode < inum); BUG_ON(k.k->p.inode < inum);
if (k.k->p.inode > inum) if (k.k->p.inode > inum)
...@@ -290,7 +294,7 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -290,7 +294,7 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
if (ret < 0) if (ret < 0)
break; break;
} }
bch2_btree_iter_unlock(&iter); bch2_trans_exit(&trans);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment