summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-25 15:10:15 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2019-03-27 23:44:53 -0400
commit8498b80bf28eb70d29683bd3e18618ec1dc71101 (patch)
tree770a18f32bb9252c1e4474dce26cfc079597a150
parentfad2dc5030ca8a1430aed0ee0e728177dc784ee3 (diff)
bcachefs: Only get btree iters from btree transactions
-rw-r--r--fs/bcachefs/alloc_background.c16
-rw-r--r--fs/bcachefs/btree_gc.c34
-rw-r--r--fs/bcachefs/btree_io.c18
-rw-r--r--fs/bcachefs/btree_iter.c63
-rw-r--r--fs/bcachefs/btree_iter.h53
-rw-r--r--fs/bcachefs/btree_update_leaf.c2
-rw-r--r--fs/bcachefs/chardev.c4
-rw-r--r--fs/bcachefs/debug.c41
-rw-r--r--fs/bcachefs/dirent.c19
-rw-r--r--fs/bcachefs/ec.c39
-rw-r--r--fs/bcachefs/extents.c11
-rw-r--r--fs/bcachefs/fs-io.c58
-rw-r--r--fs/bcachefs/fs.c11
-rw-r--r--fs/bcachefs/fsck.c146
-rw-r--r--fs/bcachefs/fsck.h1
-rw-r--r--fs/bcachefs/inode.c12
-rw-r--r--fs/bcachefs/io.c57
-rw-r--r--fs/bcachefs/journal_seq_blacklist.c17
-rw-r--r--fs/bcachefs/migrate.c22
-rw-r--r--fs/bcachefs/move.c72
-rw-r--r--fs/bcachefs/move_types.h3
-rw-r--r--fs/bcachefs/quota.c18
-rw-r--r--fs/bcachefs/rebalance.c4
-rw-r--r--fs/bcachefs/str_hash.h46
-rw-r--r--fs/bcachefs/sysfs.c9
-rw-r--r--fs/bcachefs/tests.c121
-rw-r--r--fs/bcachefs/xattr.c10
27 files changed, 549 insertions, 358 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index 1a40ac21891c..1fb0a2b4dd31 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -263,18 +263,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)
{
struct journal_replay *r;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
struct bch_dev *ca;
unsigned i;
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_btree_iter_cond_resched(&iter);
+ bch2_trans_cond_resched(&trans);
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_exit(&trans);
if (ret)
return ret;
@@ -390,8 +393,6 @@ static int __bch2_alloc_write_key(struct btree_trans *trans, struct bch_dev *ca,
__alloc_write_key(a, g, m);
percpu_up_read_preempt_enable(&c->mark_lock);
- bch2_btree_iter_cond_resched(iter);
-
bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, &a->k_i));
ret = bch2_trans_commit(trans, NULL, journal_seq,
@@ -449,6 +450,7 @@ int bch2_alloc_write(struct bch_fs *c, bool nowait, bool *wrote)
if (ret)
break;
+ bch2_trans_cond_resched(&trans);
*wrote = true;
}
up_read(&ca->bucket_lock);
@@ -937,8 +939,6 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans,
spin_unlock(&c->freelist_lock);
percpu_up_read_preempt_enable(&c->mark_lock);
- bch2_btree_iter_cond_resched(iter);
-
BUG_ON(BKEY_ALLOC_VAL_U64s_MAX > 8);
bch2_btree_iter_set_pos(iter, POS(ca->dev_idx, b));
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index af75878c06bd..aa05d7eedb56 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -204,13 +204,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,
bool initial)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct btree *b;
struct range_checks r;
unsigned depth = btree_node_type_needs_gc(btree_id) ? 0 : 1;
u8 max_stale;
int ret = 0;
+ bch2_trans_init(&trans, c);
+
gc_pos_set(c, gc_pos_btree(btree_id, POS_MIN, 0));
/*
@@ -224,7 +227,7 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
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) {
btree_node_range_checks(c, b, &r);
@@ -238,22 +241,22 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
if (!initial) {
if (max_stale > 64)
- bch2_btree_node_rewrite(c, &iter,
+ bch2_btree_node_rewrite(c, iter,
b->data->keys.seq,
BTREE_INSERT_USE_RESERVE|
BTREE_INSERT_NOWAIT|
BTREE_INSERT_GC_LOCK_HELD);
else if (!btree_gc_rewrite_disabled(c) &&
(btree_gc_always_rewrite(c) || max_stale > 16))
- bch2_btree_node_rewrite(c, &iter,
+ bch2_btree_node_rewrite(c, iter,
b->data->keys.seq,
BTREE_INSERT_NOWAIT|
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)
return ret;
@@ -1027,7 +1030,8 @@ next:
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;
bool kthread = (current->flags & PF_KTHREAD) != 0;
unsigned i;
@@ -1036,6 +1040,8 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
struct btree *merge[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
* that have the same parent - this code works by handling the cases
@@ -1045,7 +1051,7 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
*/
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_ITER_PREFETCH, b) {
memmove(merge + 1, merge,
@@ -1067,7 +1073,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]));
- bch2_coalesce_nodes(c, &iter, merge);
+ bch2_coalesce_nodes(c, iter, merge);
for (i = 1; i < GC_MERGE_NODES && merge[i]; i++) {
lock_seq[i] = merge[i]->lock.state.seq;
@@ -1077,23 +1083,23 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
lock_seq[0] = merge[0]->lock.state.seq;
if (kthread && kthread_should_stop()) {
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
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
* and the nodes in our sliding window might not have the same
* parent anymore - blow away the sliding window:
*/
- if (btree_iter_node(&iter, iter.level + 1) &&
- !btree_node_intent_locked(&iter, iter.level + 1))
+ if (btree_iter_node(iter, iter->level + 1) &&
+ !btree_node_intent_locked(iter, iter->level + 1))
memset(merge + 1, 0,
(GC_MERGE_NODES - 1) * sizeof(merge[0]));
}
- return bch2_btree_iter_unlock(&iter);
+ return bch2_trans_exit(&trans);
}
/**
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c
index f2107cf7ca5b..0b99e7d217a8 100644
--- a/fs/bcachefs/btree_io.c
+++ b/fs/bcachefs/btree_io.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_s_btree_ptr bp;
struct bch_extent_ptr *ptr;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
int ret;
- __bch2_btree_iter_init(&iter, c, b->btree_id, b->key.k.p,
- BTREE_MAX_DEPTH,
- b->level, BTREE_ITER_NODES);
+ bch2_trans_init(&trans, c);
+
+ iter = bch2_trans_get_node_iter(&trans, b->btree_id, b->key.k.p,
+ BTREE_MAX_DEPTH, b->level, 0);
retry:
- ret = bch2_btree_iter_traverse(&iter);
+ ret = bch2_btree_iter_traverse(iter);
if (ret)
goto err;
/* has node been freed? */
- if (iter.l[b->level].b != b) {
+ if (iter->l[b->level].b != b) {
/* node has been freed: */
BUG_ON(!btree_node_dying(b));
goto out;
@@ -1184,13 +1186,13 @@ retry:
if (!bch2_bkey_nr_ptrs(bp.s_c))
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)
goto retry;
if (ret)
goto err;
out:
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
bio_put(&wbio->wbio.bio);
btree_node_write_done(c, b);
return;
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index d8559520898f..41d9341d0e0b 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1581,15 +1581,15 @@ struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *iter)
return __bch2_btree_iter_peek_slot(iter);
}
-void __bch2_btree_iter_init(struct btree_iter *iter, struct bch_fs *c,
- enum btree_id btree_id, struct bpos pos,
- unsigned locks_want, unsigned depth,
- unsigned flags)
+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)
{
unsigned i;
- EBUG_ON(depth >= BTREE_MAX_DEPTH);
- EBUG_ON(locks_want > BTREE_MAX_DEPTH);
+ if (btree_id == BTREE_ID_EXTENTS &&
+ !(flags & BTREE_ITER_NODES))
+ flags |= BTREE_ITER_IS_EXTENTS;
iter->c = c;
iter->pos = pos;
@@ -1598,8 +1598,8 @@ void __bch2_btree_iter_init(struct btree_iter *iter, struct bch_fs *c,
iter->flags = flags;
iter->uptodate = BTREE_ITER_NEED_TRAVERSE;
iter->btree_id = btree_id;
- iter->level = depth;
- iter->locks_want = locks_want;
+ iter->level = 0;
+ iter->locks_want = flags & BTREE_ITER_INTENT ? 1 : 0;
iter->nodes_locked = 0;
iter->nodes_intent_locked = 0;
for (i = 0; i < ARRAY_SIZE(iter->l); i++)
@@ -1676,12 +1676,14 @@ static inline unsigned btree_trans_iter_idx(struct btree_trans *trans,
return idx;
}
-void bch2_trans_iter_put(struct btree_trans *trans,
- struct btree_iter *iter)
+int bch2_trans_iter_put(struct btree_trans *trans,
+ struct btree_iter *iter)
{
ssize_t idx = btree_trans_iter_idx(trans, iter);
+ int ret = (iter->flags & BTREE_ITER_ERROR) ? -EIO : 0;
trans->iters_live &= ~(1ULL << idx);
+ return ret;
}
static inline void __bch2_trans_iter_free(struct btree_trans *trans,
@@ -1695,17 +1697,23 @@ static inline void __bch2_trans_iter_free(struct btree_trans *trans,
bch2_btree_iter_unlink(&trans->iters[idx]);
}
-void bch2_trans_iter_free(struct btree_trans *trans,
- struct btree_iter *iter)
+int bch2_trans_iter_free(struct btree_trans *trans,
+ struct btree_iter *iter)
{
+ int ret = (iter->flags & BTREE_ITER_ERROR) ? -EIO : 0;
+
__bch2_trans_iter_free(trans, btree_trans_iter_idx(trans, iter));
+ return ret;
}
-void bch2_trans_iter_free_on_commit(struct btree_trans *trans,
- struct btree_iter *iter)
+int bch2_trans_iter_free_on_commit(struct btree_trans *trans,
+ struct btree_iter *iter)
{
+ int ret = (iter->flags & BTREE_ITER_ERROR) ? -EIO : 0;
+
trans->iters_unlink_on_commit |=
1ULL << btree_trans_iter_idx(trans, iter);
+ return ret;
}
static int btree_trans_realloc_iters(struct btree_trans *trans,
@@ -1819,7 +1827,7 @@ got_slot:
iter = &trans->iters[idx];
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 {
iter = &trans->iters[idx];
@@ -1860,6 +1868,31 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans,
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 *src,
u64 iter_id)
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 5d1f7ff79f92..54778b36e990 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -151,20 +151,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(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 *);
static inline struct bpos btree_type_successor(enum btree_id id,
@@ -222,17 +208,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) \
- for (__bch2_btree_iter_init((_iter), (_c), (_btree_id), _start, \
- _locks_want, _depth, \
- _flags|BTREE_ITER_NODES), \
+ for (iter = bch2_trans_get_node_iter((_trans), (_btree_id), \
+ _start, _locks_want, _depth, _flags), \
_b = bch2_btree_iter_peek_node(_iter); \
(_b); \
(_b) = bch2_btree_iter_next_node(_iter, _depth))
-#define for_each_btree_node(_iter, _c, _btree_id, _start, _flags, _b) \
- __for_each_btree_node(_iter, _c, _btree_id, _start, 0, 0, _flags, _b)
+#define for_each_btree_node(_trans, _iter, _btree_id, _start, \
+ _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,
unsigned flags)
@@ -252,9 +239,9 @@ static inline struct bkey_s_c __bch2_btree_iter_next(struct btree_iter *iter,
: bch2_btree_iter_next(iter);
}
-#define for_each_btree_key(_iter, _c, _btree_id, _start, _flags, _k) \
- for (bch2_btree_iter_init((_iter), (_c), (_btree_id), \
- (_start), (_flags)), \
+#define for_each_btree_key(_trans, _iter, _btree_id, _start, _flags, _k)\
+ for (iter = bch2_trans_get_iter((_trans), (_btree_id), \
+ (_start), (_flags)), \
(_k) = __bch2_btree_iter_peek(_iter, _flags); \
!IS_ERR_OR_NULL((_k).k); \
(_k) = __bch2_btree_iter_next(_iter, _flags))
@@ -272,9 +259,9 @@ static inline int btree_iter_err(struct bkey_s_c k)
/* new multiple iterator interface: */
void bch2_trans_preload_iters(struct btree_trans *);
-void bch2_trans_iter_put(struct btree_trans *, struct btree_iter *);
-void 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_put(struct btree_trans *, struct btree_iter *);
+int bch2_trans_iter_free(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);
@@ -309,6 +296,10 @@ bch2_trans_copy_iter(struct btree_trans *trans, struct btree_iter *src)
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 *);
static inline void bch2_trans_begin_updates(struct btree_trans *trans)
@@ -321,6 +312,16 @@ int bch2_trans_unlock(struct btree_trans *);
void bch2_trans_init(struct btree_trans *, struct bch_fs *);
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
#define bch2_trans_begin(_trans) \
do { \
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 04b5699beed0..e3c44d8e2673 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -998,7 +998,7 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id,
if (ret)
break;
- bch2_btree_iter_cond_resched(iter);
+ bch2_trans_cond_resched(&trans);
}
bch2_trans_exit(&trans);
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
index 4e33e7b81872..82d90cdea003 100644
--- a/fs/bcachefs/chardev.c
+++ b/fs/bcachefs/chardev.c
@@ -302,8 +302,8 @@ static ssize_t bch2_data_job_read(struct file *file, char __user *buf,
struct bch_ioctl_data_event e = {
.type = BCH_DATA_EVENT_PROGRESS,
.p.data_type = ctx->stats.data_type,
- .p.btree_id = ctx->stats.iter.btree_id,
- .p.pos = ctx->stats.iter.pos,
+ .p.btree_id = ctx->stats.btree_id,
+ .p.pos = ctx->stats.pos,
.p.sectors_done = atomic64_read(&ctx->stats.sectors_seen),
.p.sectors_total = bch2_fs_usage_read_short(c).used,
};
diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c
index e8a671a1b898..e830e798fc45 100644
--- a/fs/bcachefs/debug.c
+++ b/fs/bcachefs/debug.c
@@ -204,7 +204,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
struct dump_iter *i = file->private_data;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
int err;
@@ -219,8 +220,10 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
if (!i->size)
return i->ret;
- bch2_btree_iter_init(&iter, i->c, i->id, i->from, BTREE_ITER_PREFETCH);
- k = bch2_btree_iter_peek(&iter);
+ bch2_trans_init(&trans, i->c);
+
+ 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))) {
bch2_bkey_val_to_text(&PBUF(i->buf), i->c, k);
@@ -229,8 +232,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
i->buf[i->bytes] = '\n';
i->bytes++;
- k = bch2_btree_iter_next(&iter);
- i->from = iter.pos;
+ k = bch2_btree_iter_next(iter);
+ i->from = iter->pos;
err = flush_buf(i);
if (err)
@@ -239,7 +242,7 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
if (!i->size)
break;
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return err < 0 ? err : i->ret;
}
@@ -255,7 +258,8 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
struct dump_iter *i = file->private_data;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct btree *b;
int err;
@@ -270,7 +274,9 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
if (!i->size || !bkey_cmp(POS_MAX, i->from))
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);
i->bytes = strlen(i->buf);
err = flush_buf(i);
@@ -288,7 +294,7 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
if (!i->size)
break;
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return err < 0 ? err : i->ret;
}
@@ -304,7 +310,8 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
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 btree *prev_node = NULL;
int err;
@@ -320,11 +327,13 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
if (!i->size)
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))) {
- struct btree_iter_level *l = &iter.l[0];
+ struct btree_iter_level *l = &iter->l[0];
struct bkey_packed *_k =
bch2_btree_node_iter_peek(&l->iter, l->b);
@@ -343,8 +352,8 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
if (err)
break;
- bch2_btree_iter_next(&iter);
- i->from = iter.pos;
+ bch2_btree_iter_next(iter);
+ i->from = iter->pos;
err = flush_buf(i);
if (err)
@@ -353,7 +362,7 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
if (!i->size)
break;
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return err < 0 ? err : i->ret;
}
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
index 550561e67ad7..58289fccb8dc 100644
--- a/fs/bcachefs/dirent.c
+++ b/fs/bcachefs/dirent.c
@@ -330,11 +330,15 @@ out:
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;
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)
break;
@@ -343,7 +347,7 @@ int bch2_empty_dir(struct bch_fs *c, u64 dir_inum)
break;
}
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return ret;
}
@@ -352,7 +356,8 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
struct dir_context *ctx)
{
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_dirent dirent;
unsigned len;
@@ -360,7 +365,9 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
if (!dir_emit_dots(file, ctx))
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) {
if (k.k->type != KEY_TYPE_dirent)
continue;
@@ -386,7 +393,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
ctx->pos = k.k->p.offset + 1;
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return 0;
}
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index ea6f4867ae81..941587c13522 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -397,7 +397,8 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
/* recovery read path: */
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 closure cl;
struct bkey_s_c k;
@@ -418,19 +419,21 @@ int bch2_ec_read_extent(struct bch_fs *c, struct bch_read_bio *rbio)
if (!buf)
return -ENOMEM;
- bch2_btree_iter_init(&iter, c, BTREE_ID_EC,
- POS(0, stripe_idx),
- BTREE_ITER_SLOTS);
- k = bch2_btree_iter_peek_slot(&iter);
+ bch2_trans_init(&trans, c);
+
+ iter = bch2_trans_get_iter(&trans, BTREE_ID_EC,
+ POS(0, stripe_idx),
+ BTREE_ITER_SLOTS);
+ k = bch2_btree_iter_peek_slot(iter);
if (btree_iter_err(k) || k.k->type != KEY_TYPE_stripe) {
__bcache_io_error(c,
"error doing reconstruct read: stripe not found");
kfree(buf);
- return bch2_btree_iter_unlock(&iter) ?: -EIO;
+ return bch2_trans_exit(&trans) ?: -EIO;
}
bkey_reassemble(&buf->key.k_i, k);
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
v = &buf->key.v;
@@ -1237,7 +1240,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)
{
struct journal_replay *r;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
int ret;
@@ -1245,12 +1249,14 @@ int bch2_stripes_read(struct bch_fs *c, struct list_head *journal_replay_list)
if (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_btree_iter_cond_resched(&iter);
+ bch2_trans_cond_resched(&trans);
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_exit(&trans);
if (ret)
return ret;
@@ -1268,17 +1274,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)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
size_t i, idx = 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))
idx = k.k->p.offset + 1;
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_exit(&trans);
if (ret)
return ret;
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index 1ab951c97a89..e9ad5592552f 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -1618,15 +1618,18 @@ static bool bch2_extent_merge_inline(struct bch_fs *c,
bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size,
unsigned nr_replicas)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bpos end = pos;
struct bkey_s_c k;
bool ret = true;
end.offset += size;
- for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, pos,
- BTREE_ITER_SLOTS, k) {
+ bch2_trans_init(&trans, c);
+
+ for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, pos,
+ BTREE_ITER_SLOTS, k) {
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
break;
@@ -1635,7 +1638,7 @@ bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size,
break;
}
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return ret;
}
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index d3a03641cbfd..5ffa1ffbbc9e 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -1044,7 +1044,8 @@ int bch2_readpages(struct file *file, struct address_space *mapping,
struct bch_inode_info *inode = to_bch_ei(mapping->host);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
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 readpages_iter readpages_iter;
int ret;
@@ -1052,8 +1053,10 @@ int bch2_readpages(struct file *file, struct address_space *mapping,
ret = readpages_iter_init(&readpages_iter, mapping, pages, nr_pages);
BUG_ON(ret);
- bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, POS_MIN,
- BTREE_ITER_SLOTS);
+ bch2_trans_init(&trans, c);
+
+ iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN,
+ BTREE_ITER_SLOTS);
if (current->pagecache_lock != &mapping->add_lock)
pagecache_add_get(&mapping->add_lock);
@@ -1075,12 +1078,13 @@ int bch2_readpages(struct file *file, struct address_space *mapping,
rbio->bio.bi_end_io = bch2_readpages_end_io;
__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);
}
if (current->pagecache_lock != &mapping->add_lock)
pagecache_add_put(&mapping->add_lock);
+ bch2_trans_exit(&trans);
kfree(readpages_iter.pages);
return 0;
@@ -1089,16 +1093,21 @@ int bch2_readpages(struct file *file, struct address_space *mapping,
static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio,
u64 inum, struct page *page)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
page_state_init_for_read(page);
bio_set_op_attrs(&rbio->bio, REQ_OP_READ, REQ_SYNC);
bio_add_page_contig(&rbio->bio, page);
- bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, POS_MIN,
- BTREE_ITER_SLOTS);
- bchfs_read(c, &iter, rbio, inum, NULL);
+ bch2_trans_init(&trans, c);
+ iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN,
+ BTREE_ITER_SLOTS);
+
+ bchfs_read(c, iter, rbio, inum, NULL);
+
+ bch2_trans_exit(&trans);
}
int bch2_readpage(struct file *file, struct page *page)
@@ -2120,7 +2129,7 @@ static int __bch2_fpunch(struct bch_fs *c, struct bch_inode_info *inode,
if (ret)
break;
- bch2_btree_iter_cond_resched(iter);
+ bch2_trans_cond_resched(&trans);
}
bch2_trans_exit(&trans);
@@ -2132,13 +2141,14 @@ static inline int range_has_data(struct bch_fs *c,
struct bpos start,
struct bpos end)
{
-
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
int ret = 0;
- for_each_btree_key(&iter, c, BTREE_ID_EXTENTS,
- start, 0, k) {
+ bch2_trans_init(&trans, c);
+
+ for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, start, 0, k) {
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
break;
@@ -2148,7 +2158,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,
@@ -2472,7 +2482,7 @@ btree_iter_err:
* pointers... which isn't a _super_ serious problem...
*/
- bch2_btree_iter_cond_resched(src);
+ bch2_trans_cond_resched(&trans);
}
bch2_trans_unlock(&trans);
@@ -2710,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_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;
u64 isize, next_data = MAX_LFS_FILESIZE;
int ret;
@@ -2719,7 +2730,9 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
if (offset >= isize)
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) {
if (k.k->p.inode != inode->v.i_ino) {
break;
@@ -2730,7 +2743,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
break;
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_exit(&trans);
if (ret)
return ret;
@@ -2780,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_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;
u64 isize, next_hole = MAX_LFS_FILESIZE;
int ret;
@@ -2789,7 +2803,9 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
if (offset >= isize)
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),
BTREE_ITER_SLOTS, k) {
if (k.k->p.inode != inode->v.i_ino) {
@@ -2808,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)
return ret;
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index f05606753dd6..cc91af0ad648 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -106,7 +106,7 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
void *p)
{
struct bch_fs *c = trans->c;
- struct btree_iter *iter;
+ struct btree_iter *iter = NULL;
struct bkey_inode_buf *inode_p;
int ret;
@@ -1113,7 +1113,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_inode_info *ei = to_bch_ei(vinode);
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
BKEY_PADDED(k) tmp;
bool have_extent = false;
@@ -1122,7 +1123,9 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
if (start + len < start)
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)
if (bkey_extent_is_data(k.k) ||
k.k->type == KEY_TYPE_reservation) {
@@ -1143,7 +1146,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
if (have_extent)
ret = bch2_fill_extent(info, &tmp.k, FIEMAP_EXTENT_LAST);
out:
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return ret < 0 ? ret : 0;
}
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index fb0cb9a454d6..3b4a168749fb 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -15,6 +15,23 @@
#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
+static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum)
+{
+ struct btree_iter *iter;
+ struct bkey_s_c k;
+ u64 sectors = 0;
+
+ for_each_btree_key(trans, iter, BTREE_ID_EXTENTS, POS(inum, 0), 0, k) {
+ if (k.k->p.inode != inum)
+ break;
+
+ if (bkey_extent_is_allocation(k.k))
+ sectors += k.k->size;
+ }
+
+ return bch2_trans_iter_free(trans, iter) ?: sectors;
+}
+
static int remove_dirent(struct bch_fs *c, struct btree_iter *iter,
struct bkey_s_c_dirent dirent)
{
@@ -180,44 +197,32 @@ err:
return ret;
}
-/* fsck hasn't been converted to new transactions yet: */
-static int fsck_hash_delete_at(const struct bch_hash_desc desc,
+static int fsck_hash_delete_at(struct btree_trans *trans,
+ const struct bch_hash_desc desc,
struct bch_hash_info *info,
- struct btree_iter *orig_iter)
+ struct btree_iter *iter)
{
- struct btree_trans trans;
- struct btree_iter *iter;
int ret;
-
- bch2_btree_iter_unlock(orig_iter);
-
- bch2_trans_init(&trans, orig_iter->c);
retry:
- bch2_trans_begin(&trans);
-
- iter = bch2_trans_copy_iter(&trans, orig_iter);
- if (IS_ERR(iter)) {
- ret = PTR_ERR(iter);
- goto err;
- }
-
- ret = bch2_hash_delete_at(&trans, desc, info, iter) ?:
- bch2_trans_commit(&trans, NULL, NULL,
+ ret = bch2_hash_delete_at(trans, desc, info, iter) ?:
+ bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_ATOMIC|
BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW);
-err:
- if (ret == -EINTR)
- goto retry;
+ if (ret == -EINTR) {
+ ret = bch2_btree_iter_traverse(iter);
+ if (!ret)
+ goto retry;
+ }
- bch2_trans_exit(&trans);
return ret;
}
-static int hash_check_duplicates(const struct bch_hash_desc desc,
- struct hash_check *h, struct bch_fs *c,
- struct btree_iter *k_iter, struct bkey_s_c k)
+static int hash_check_duplicates(struct btree_trans *trans,
+ const struct bch_hash_desc desc, struct hash_check *h,
+ struct btree_iter *k_iter, struct bkey_s_c k)
{
+ struct bch_fs *c = trans->c;
struct btree_iter *iter;
struct bkey_s_c k2;
char buf[200];
@@ -238,7 +243,7 @@ static int hash_check_duplicates(const struct bch_hash_desc desc,
"duplicate hash table keys:\n%s",
(bch2_bkey_val_to_text(&PBUF(buf), c,
k), buf))) {
- ret = fsck_hash_delete_at(desc, &h->info, k_iter);
+ ret = fsck_hash_delete_at(trans, desc, &h->info, k_iter);
if (ret)
return ret;
ret = 1;
@@ -273,9 +278,9 @@ static bool key_has_correct_hash(const struct bch_hash_desc desc,
hash <= k.k->p.offset;
}
-static int hash_check_key(const struct bch_hash_desc desc,
- struct btree_trans *trans, struct hash_check *h,
- struct btree_iter *k_iter, struct bkey_s_c k)
+static int hash_check_key(struct btree_trans *trans,
+ const struct bch_hash_desc desc, struct hash_check *h,
+ struct btree_iter *k_iter, struct bkey_s_c k)
{
struct bch_fs *c = trans->c;
char buf[200];
@@ -311,7 +316,7 @@ static int hash_check_key(const struct bch_hash_desc desc,
return 1;
}
- ret = hash_check_duplicates(desc, h, c, k_iter, k);
+ ret = hash_check_duplicates(trans, desc, h, k_iter, k);
fsck_err:
return ret;
}
@@ -416,14 +421,17 @@ noinline_for_stack
static int check_extents(struct bch_fs *c)
{
struct inode_walker w = inode_walker_init();
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
u64 i_sectors;
int ret = 0;
+ bch2_trans_init(&trans, c);
+
bch_verbose(c, "checking extents");
- for_each_btree_key(&iter, c, BTREE_ID_EXTENTS,
+ for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(BCACHEFS_ROOT_INO, 0), 0, k) {
ret = walk_inode(c, &w, k.k->p.inode);
if (ret)
@@ -436,7 +444,7 @@ static int check_extents(struct bch_fs *c)
!S_ISREG(w.inode.bi_mode) && !S_ISLNK(w.inode.bi_mode), c,
"extent type %u for non regular file, inode %llu mode %o",
k.k->type, k.k->p.inode, w.inode.bi_mode)) {
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_unlock(&trans);
ret = bch2_inode_truncate(c, k.k->p.inode, 0);
if (ret)
@@ -448,14 +456,14 @@ static int check_extents(struct bch_fs *c)
w.have_inode &&
!(w.inode.bi_flags & BCH_INODE_I_SECTORS_DIRTY) &&
w.inode.bi_sectors !=
- (i_sectors = bch2_count_inode_sectors(c, w.cur_inum)),
+ (i_sectors = bch2_count_inode_sectors(&trans, w.cur_inum)),
c, "i_sectors wrong: got %llu, should be %llu",
w.inode.bi_sectors, i_sectors)) {
struct bkey_inode_buf p;
w.inode.bi_sectors = i_sectors;
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_unlock(&trans);
bch2_inode_pack(&p, &w.inode);
@@ -469,7 +477,7 @@ static int check_extents(struct bch_fs *c)
}
/* revalidate iterator: */
- k = bch2_btree_iter_peek(&iter);
+ k = bch2_btree_iter_peek(iter);
}
if (fsck_err_on(w.have_inode &&
@@ -478,7 +486,7 @@ static int check_extents(struct bch_fs *c)
k.k->p.offset > round_up(w.inode.bi_size, PAGE_SIZE) >> 9, c,
"extent type %u offset %llu past end of inode %llu, i_size %llu",
k.k->type, k.k->p.offset, k.k->p.inode, w.inode.bi_size)) {
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_unlock(&trans);
ret = bch2_inode_truncate(c, k.k->p.inode,
w.inode.bi_size);
@@ -489,7 +497,7 @@ static int check_extents(struct bch_fs *c)
}
err:
fsck_err:
- return bch2_btree_iter_unlock(&iter) ?: ret;
+ return bch2_trans_exit(&trans) ?: ret;
}
/*
@@ -687,7 +695,8 @@ static int check_xattrs(struct bch_fs *c)
if (w.first_this_inode && w.have_inode)
hash_check_set_inode(&h, c, &w.inode);
- ret = hash_check_key(bch2_xattr_hash_desc, &trans, &h, iter, k);
+ ret = hash_check_key(&trans, bch2_xattr_hash_desc,
+ &h, iter, k);
if (ret)
goto fsck_err;
}
@@ -862,13 +871,16 @@ static int check_directory_structure(struct bch_fs *c,
struct inode_bitmap dirs_done = { NULL, 0 };
struct pathbuf path = { 0, 0, NULL };
struct pathbuf_entry *e;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
struct bkey_s_c_dirent dirent;
bool had_unreachable;
u64 d_inum;
int ret = 0;
+ bch2_trans_init(&trans, c);
+
bch_verbose(c, "checking directory structure");
/* DFS: */
@@ -893,7 +905,7 @@ next:
if (e->offset == U64_MAX)
goto up;
- for_each_btree_key(&iter, c, BTREE_ID_DIRENTS,
+ for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
POS(e->inum, e->offset + 1), 0, k) {
if (k.k->p.inode != e->inum)
break;
@@ -913,7 +925,7 @@ next:
if (fsck_err_on(inode_bitmap_test(&dirs_done, d_inum), c,
"directory %llu has multiple hardlinks",
d_inum)) {
- ret = remove_dirent(c, &iter, dirent);
+ ret = remove_dirent(c, iter, dirent);
if (ret)
goto err;
continue;
@@ -930,10 +942,14 @@ next:
goto err;
}
- bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_iter_free(&trans, iter);
+ if (ret) {
+ bch_err(c, "btree error %i in fsck", ret);
+ goto err;
+ }
goto next;
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_iter_free(&trans, iter);
if (ret) {
bch_err(c, "btree error %i in fsck", ret);
goto err;
@@ -942,7 +958,7 @@ up:
path.nr--;
}
- for_each_btree_key(&iter, c, BTREE_ID_INODES, POS_MIN, 0, k) {
+ for_each_btree_key(&trans, iter, BTREE_ID_INODES, POS_MIN, 0, k) {
if (k.k->type != KEY_TYPE_inode)
continue;
@@ -955,7 +971,7 @@ up:
if (fsck_err_on(!inode_bitmap_test(&dirs_done, k.k->p.inode), c,
"unreachable directory found (inum %llu)",
k.k->p.inode)) {
- bch2_btree_iter_unlock(&iter);
+ bch2_btree_iter_unlock(iter);
ret = reattach_inode(c, lostfound_inode, k.k->p.inode);
if (ret) {
@@ -965,7 +981,7 @@ up:
had_unreachable = true;
}
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_iter_free(&trans, iter);
if (ret)
goto err;
@@ -984,7 +1000,7 @@ out:
return ret;
err:
fsck_err:
- ret = bch2_btree_iter_unlock(&iter) ?: ret;
+ ret = bch2_trans_exit(&trans) ?: ret;
goto out;
}
@@ -1021,15 +1037,18 @@ noinline_for_stack
static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
u64 range_start, u64 *range_end)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
struct bkey_s_c_dirent d;
u64 d_inum;
int ret;
+ bch2_trans_init(&trans, c);
+
inc_link(c, links, range_start, range_end, BCACHEFS_ROOT_INO, false);
- for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS_MIN, 0, k) {
+ for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN, 0, k) {
switch (k.k->type) {
case KEY_TYPE_dirent:
d = bkey_s_c_to_dirent(k);
@@ -1045,32 +1064,15 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
break;
}
- bch2_btree_iter_cond_resched(&iter);
+ bch2_trans_cond_resched(&trans);
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_exit(&trans);
if (ret)
bch_err(c, "error in fs gc: btree error %i while walking dirents", ret);
return ret;
}
-s64 bch2_count_inode_sectors(struct bch_fs *c, u64 inum)
-{
- struct btree_iter iter;
- struct bkey_s_c k;
- u64 sectors = 0;
-
- for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS(inum, 0), 0, k) {
- if (k.k->p.inode != inum)
- break;
-
- if (bkey_extent_is_allocation(k.k))
- sectors += k.k->size;
- }
-
- return bch2_btree_iter_unlock(&iter) ?: sectors;
-}
-
static int check_inode_nlink(struct bch_fs *c,
struct bch_inode_unpacked *lostfound_inode,
struct bch_inode_unpacked *u,
@@ -1252,7 +1254,7 @@ static int check_inode(struct btree_trans *trans,
bch_verbose(c, "recounting sectors for inode %llu",
u.bi_inum);
- sectors = bch2_count_inode_sectors(c, u.bi_inum);
+ sectors = bch2_count_inode_sectors(trans, u.bi_inum);
if (sectors < 0) {
bch_err(c, "error in fs gc: error %i "
"recounting inode sectors",
@@ -1345,7 +1347,7 @@ peek_nlinks: link = genradix_iter_peek(&nlinks_iter, links);
genradix_iter_advance(&nlinks_iter, links);
bch2_btree_iter_next(iter);
- bch2_btree_iter_cond_resched(iter);
+ bch2_trans_cond_resched(&trans);
}
fsck_err:
bch2_trans_exit(&trans);
diff --git a/fs/bcachefs/fsck.h b/fs/bcachefs/fsck.h
index bc9caaf23797..dc7ce68769fc 100644
--- a/fs/bcachefs/fsck.h
+++ b/fs/bcachefs/fsck.h
@@ -1,7 +1,6 @@
#ifndef _BCACHEFS_FSCK_H
#define _BCACHEFS_FSCK_H
-s64 bch2_count_inode_sectors(struct bch_fs *, u64);
int bch2_fsck(struct bch_fs *);
#endif /* _BCACHEFS_FSCK_H */
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c
index a555a8afd27e..8b24bf092e73 100644
--- a/fs/bcachefs/inode.c
+++ b/fs/bcachefs/inode.c
@@ -448,13 +448,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,
struct bch_inode_unpacked *inode)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
int ret = -ENOENT;
- for_each_btree_key(&iter, c, BTREE_ID_INODES,
- POS(inode_nr, 0),
- BTREE_ITER_SLOTS, k) {
+ bch2_trans_init(&trans, c);
+
+ for_each_btree_key(&trans, iter, BTREE_ID_INODES,
+ POS(inode_nr, 0), BTREE_ITER_SLOTS, k) {
switch (k.k->type) {
case KEY_TYPE_inode:
ret = bch2_inode_unpack(bkey_s_c_to_inode(k), inode);
@@ -467,7 +469,7 @@ int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr,
break;
}
- return bch2_btree_iter_unlock(&iter) ?: ret;
+ return bch2_trans_exit(&trans) ?: ret;
}
#ifdef CONFIG_BCACHEFS_DEBUG
diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c
index 11b927e64a5d..80885885ced9 100644
--- a/fs/bcachefs/io.c
+++ b/fs/bcachefs/io.c
@@ -1245,27 +1245,28 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio
struct bch_io_failures *failed,
unsigned flags)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
BKEY_PADDED(k) tmp;
struct bkey_s_c k;
int ret;
flags &= ~BCH_READ_LAST_FRAGMENT;
- bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS,
- rbio->pos, BTREE_ITER_SLOTS);
+ bch2_trans_init(&trans, c);
+
+ iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
+ rbio->pos, BTREE_ITER_SLOTS);
retry:
rbio->bio.bi_status = 0;
- k = bch2_btree_iter_peek_slot(&iter);
- if (btree_iter_err(k)) {
- bch2_btree_iter_unlock(&iter);
+ k = bch2_btree_iter_peek_slot(iter);
+ if (btree_iter_err(k))
goto err;
- }
bkey_reassemble(&tmp.k, 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) ||
!bch2_extent_matches_ptr(c, bkey_i_to_s_c_extent(&tmp.k),
@@ -1282,25 +1283,30 @@ retry:
goto retry;
if (ret)
goto err;
- goto out;
-err:
- rbio->bio.bi_status = BLK_STS_IOERR;
out:
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,
struct bvec_iter bvec_iter, u64 inode,
struct bch_io_failures *failed, unsigned flags)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
int ret;
+ bch2_trans_init(&trans, c);
+
flags &= ~BCH_READ_LAST_FRAGMENT;
flags |= BCH_READ_MUST_CLONE;
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),
BTREE_ITER_SLOTS, k) {
BKEY_PADDED(k) tmp;
@@ -1308,7 +1314,7 @@ retry:
bkey_reassemble(&tmp.k, 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,
(k.k->p.offset - bvec_iter.bi_sector) << 9);
@@ -1333,12 +1339,12 @@ retry:
* If we get here, it better have been because there was an error
* reading a btree node
*/
- ret = bch2_btree_iter_unlock(&iter);
- BUG_ON(!ret);
- __bcache_io_error(c, "btree IO error %i", ret);
+ BUG_ON(!(iter->flags & BTREE_ITER_ERROR));
+ __bcache_io_error(c, "btree IO error");
err:
rbio->bio.bi_status = BLK_STS_IOERR;
out:
+ bch2_trans_exit(&trans);
bch2_rbio_done(rbio);
}
@@ -1834,12 +1840,14 @@ out_read_done:
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;
unsigned flags = BCH_READ_RETRY_IF_STALE|
BCH_READ_MAY_PROMOTE|
BCH_READ_USER_MAPPED;
- int ret;
+
+ bch2_trans_init(&trans, c);
BUG_ON(rbio->_state);
BUG_ON(flags & BCH_READ_NODECODE);
@@ -1848,7 +1856,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
rbio->c = c;
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),
BTREE_ITER_SLOTS, k) {
BKEY_PADDED(k) tmp;
@@ -1860,7 +1868,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
*/
bkey_reassemble(&tmp.k, 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,
(k.k->p.offset - rbio->bio.bi_iter.bi_sector) << 9);
@@ -1882,9 +1890,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
* reading a btree node
*/
- ret = bch2_btree_iter_unlock(&iter);
- BUG_ON(!ret);
- bcache_io_error(c, &rbio->bio, "btree IO error %i", ret);
+ BUG_ON(!(iter->flags & BTREE_ITER_ERROR));
+ bcache_io_error(c, &rbio->bio, "btree IO error");
+
+ bch2_trans_exit(&trans);
bch2_rbio_done(rbio);
}
diff --git a/fs/bcachefs/journal_seq_blacklist.c b/fs/bcachefs/journal_seq_blacklist.c
index dd0e8d2fce99..5bac41cf437c 100644
--- a/fs/bcachefs/journal_seq_blacklist.c
+++ b/fs/bcachefs/journal_seq_blacklist.c
@@ -61,9 +61,12 @@ static void journal_seq_blacklist_flush(struct journal *j,
closure_init_stack(&cl);
for (i = 0;; i++) {
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct btree *b;
+ bch2_trans_init(&trans, c);
+
mutex_lock(&j->blacklist_lock);
if (i >= bl->nr_entries) {
mutex_unlock(&j->blacklist_lock);
@@ -72,17 +75,17 @@ static void journal_seq_blacklist_flush(struct journal *j,
n = bl->entries[i];
mutex_unlock(&j->blacklist_lock);
- __bch2_btree_iter_init(&iter, c, n.btree_id, n.pos,
- 0, 0, BTREE_ITER_NODES);
+ iter = bch2_trans_get_node_iter(&trans, n.btree_id, n.pos,
+ 0, 0, 0);
- b = bch2_btree_iter_peek_node(&iter);
+ b = bch2_btree_iter_peek_node(iter);
/* The node might have already been rewritten: */
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) {
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
bch2_fs_fatal_error(c,
"error %i rewriting btree node with blacklisted journal seq",
ret);
@@ -91,7 +94,7 @@ static void journal_seq_blacklist_flush(struct journal *j,
}
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
}
for (i = 0;; i++) {
diff --git a/fs/bcachefs/migrate.c b/fs/bcachefs/migrate.c
index 58d7d3a30cd5..3bae97dd65ce 100644
--- a/fs/bcachefs/migrate.c
+++ b/fs/bcachefs/migrate.c
@@ -105,7 +105,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)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct closure cl;
struct btree *b;
unsigned id;
@@ -115,13 +116,15 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
if (flags & BCH_FORCE_IF_METADATA_LOST)
return -EINVAL;
+ bch2_trans_init(&trans, c);
closure_init_stack(&cl);
mutex_lock(&c->replicas_gc_lock);
bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE);
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;
struct bkey_i_btree_ptr *new_key;
retry:
@@ -133,7 +136,7 @@ retry:
* but got -EINTR after upgrading the iter, but
* 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));
if (ret)
@@ -147,16 +150,16 @@ retry:
if (ret)
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) {
- b = bch2_btree_iter_peek_node(&iter);
+ b = bch2_btree_iter_peek_node(iter);
goto retry;
}
if (ret)
goto err;
}
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_iter_free(&trans, iter);
}
/* flush relevant btree updates */
@@ -170,14 +173,13 @@ retry:
}
ret = 0;
-out:
+err:
+ bch2_trans_exit(&trans);
+
ret = bch2_replicas_gc_end(c, ret);
mutex_unlock(&c->replicas_gc_lock);
return ret;
-err:
- bch2_btree_iter_unlock(&iter);
- goto out;
}
int bch2_dev_data_drop(struct bch_fs *c, unsigned dev_idx, int flags)
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c
index 3315bedcabfd..a382c4cd589c 100644
--- a/fs/bcachefs/move.c
+++ b/fs/bcachefs/move.c
@@ -486,6 +486,8 @@ int bch2_move_data(struct bch_fs *c,
struct moving_context ctxt = { .stats = stats };
struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
BKEY_PADDED(k) tmp;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
struct data_opts data_opts;
enum data_cmd data_cmd;
@@ -496,9 +498,14 @@ int bch2_move_data(struct bch_fs *c,
INIT_LIST_HEAD(&ctxt.reads);
init_waitqueue_head(&ctxt.wait);
+ bch2_trans_init(&trans, c);
+
stats->data_type = BCH_DATA_USER;
- bch2_btree_iter_init(&stats->iter, c, BTREE_ID_EXTENTS, start,
- BTREE_ITER_PREFETCH);
+ stats->btree_id = BTREE_ID_EXTENTS;
+ stats->pos = POS_MIN;
+
+ iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, start,
+ BTREE_ITER_PREFETCH);
if (rate)
bch2_ratelimit_reset(rate);
@@ -508,7 +515,7 @@ int bch2_move_data(struct bch_fs *c,
delay = rate ? bch2_ratelimit_delay(rate) : 0;
if (delay) {
- bch2_btree_iter_unlock(&stats->iter);
+ bch2_trans_unlock(&trans);
set_current_state(TASK_INTERRUPTIBLE);
}
@@ -521,13 +528,16 @@ int bch2_move_data(struct bch_fs *c,
schedule_timeout(delay);
if (unlikely(freezing(current))) {
- bch2_btree_iter_unlock(&stats->iter);
+ bch2_trans_unlock(&trans);
move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads));
try_to_freeze();
}
} while (delay);
peek:
- k = bch2_btree_iter_peek(&stats->iter);
+ k = bch2_btree_iter_peek(iter);
+
+ stats->pos = iter->pos;
+
if (!k.k)
break;
ret = btree_iter_err(k);
@@ -543,7 +553,7 @@ peek:
struct bch_inode_unpacked 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);
if (!bch2_inode_find_by_inum(c, k.k->p.inode, &inode))
@@ -568,7 +578,7 @@ peek:
/* unlock before doing IO: */
bkey_reassemble(&tmp.k, 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,
bkey_s_c_to_extent(k),
@@ -590,11 +600,11 @@ next:
atomic64_add(k.k->size * bch2_bkey_nr_dirty_ptrs(k),
&stats->sectors_seen);
next_nondata:
- bch2_btree_iter_next(&stats->iter);
- bch2_btree_iter_cond_resched(&stats->iter);
+ bch2_btree_iter_next(iter);
+ bch2_trans_cond_resched(&trans);
}
out:
- bch2_btree_iter_unlock(&stats->iter);
+ bch2_trans_exit(&trans);
move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads));
closure_sync(&ctxt.cl);
@@ -610,20 +620,23 @@ out:
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;
int ret;
+ bch2_trans_init(&trans, c);
+
mutex_lock(&c->replicas_gc_lock);
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) {
ret = bch2_mark_bkey_replicas(c, k);
if (ret)
break;
}
- ret = bch2_btree_iter_unlock(&iter) ?: ret;
+ ret = bch2_trans_exit(&trans) ?: ret;
bch2_replicas_gc_end(c, ret);
mutex_unlock(&c->replicas_gc_lock);
@@ -633,24 +646,30 @@ static int bch2_gc_data_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;
unsigned id;
int ret = 0;
+ bch2_trans_init(&trans, c);
+
mutex_lock(&c->replicas_gc_lock);
bch2_replicas_gc_start(c, 1 << BCH_DATA_BTREE);
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));
- 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);
mutex_unlock(&c->replicas_gc_lock);
@@ -663,16 +682,25 @@ static int bch2_move_btree(struct bch_fs *c,
struct bch_move_stats *stats)
{
struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct btree *b;
unsigned id;
struct data_opts data_opts;
enum data_cmd cmd;
int ret = 0;
+ bch2_trans_init(&trans, c);
+
stats->data_type = BCH_DATA_BTREE;
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,
bkey_i_to_s_c(&b->key),
&io_opts, &data_opts))) {
@@ -687,15 +715,17 @@ static int bch2_move_btree(struct bch_fs *c,
BUG();
}
- ret = bch2_btree_node_rewrite(c, &stats->iter,
+ ret = bch2_btree_node_rewrite(c, iter,
b->data->keys.seq, 0) ?: ret;
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;
}
diff --git a/fs/bcachefs/move_types.h b/fs/bcachefs/move_types.h
index 832542a879ab..7703ce43dce9 100644
--- a/fs/bcachefs/move_types.h
+++ b/fs/bcachefs/move_types.h
@@ -3,7 +3,8 @@
struct bch_move_stats {
enum bch_data_type data_type;
- struct btree_iter iter;
+ enum btree_id btree_id;
+ struct bpos pos;
atomic64_t keys_moved;
atomic64_t sectors_moved;
diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c
index 6606e85cc8de..aef378d9cf4e 100644
--- a/fs/bcachefs/quota.c
+++ b/fs/bcachefs/quota.c
@@ -355,11 +355,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)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
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) {
if (k.k->p.inode != type)
break;
@@ -369,7 +372,7 @@ static int bch2_quota_init_type(struct bch_fs *c, enum quota_types type)
break;
}
- return bch2_btree_iter_unlock(&iter) ?: ret;
+ return bch2_trans_exit(&trans) ?: ret;
}
void bch2_fs_quota_exit(struct bch_fs *c)
@@ -413,7 +416,8 @@ int bch2_fs_quota_read(struct bch_fs *c)
{
unsigned i, qtypes = enabled_qtypes(c);
struct bch_memquota_type *q;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bch_inode_unpacked u;
struct bkey_s_c k;
int ret;
@@ -428,7 +432,9 @@ int bch2_fs_quota_read(struct bch_fs *c)
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) {
switch (k.k->type) {
case KEY_TYPE_inode:
@@ -442,7 +448,7 @@ int bch2_fs_quota_read(struct bch_fs *c)
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: */
diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c
index 768c02845daf..d7698451f1ae 100644
--- a/fs/bcachefs/rebalance.c
+++ b/fs/bcachefs/rebalance.c
@@ -288,8 +288,8 @@ ssize_t bch2_rebalance_work_show(struct bch_fs *c, char *buf)
case REBALANCE_RUNNING:
pr_buf(&out, "running\n");
pr_buf(&out, "pos %llu:%llu\n",
- r->move_stats.iter.pos.inode,
- r->move_stats.iter.pos.offset);
+ r->move_stats.pos.inode,
+ r->move_stats.pos.offset);
break;
}
diff --git a/fs/bcachefs/str_hash.h b/fs/bcachefs/str_hash.h
index f78f07bd5202..f928ca991043 100644
--- a/fs/bcachefs/str_hash.h
+++ b/fs/bcachefs/str_hash.h
@@ -203,13 +203,16 @@ int bch2_hash_needs_whiteout(struct btree_trans *trans,
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k) {
if (k.k->type != desc.key_type &&
k.k->type != KEY_TYPE_whiteout)
- return false;
+ break;
if (k.k->type == desc.key_type &&
- desc.hash_bkey(info, k) <= start->pos.offset)
- return true;
+ desc.hash_bkey(info, k) <= start->pos.offset) {
+ 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
@@ -220,6 +223,8 @@ int bch2_hash_set(struct btree_trans *trans,
{
struct btree_iter *iter, *slot = NULL;
struct bkey_s_c k;
+ bool found = false;
+ int ret = 0;
iter = bch2_trans_get_iter(trans, desc.btree_id,
POS(inode, desc.hash_bkey(info, bkey_i_to_s_c(insert))),
@@ -250,21 +255,30 @@ int bch2_hash_set(struct btree_trans *trans,
goto not_found;
}
- return btree_iter_err(k) ?: -ENOSPC;
-not_found:
- if (flags & BCH_HASH_SET_MUST_REPLACE)
- return -ENOENT;
+ if (slot)
+ bch2_trans_iter_free(trans, iter);
- insert->k.p = slot->pos;
- bch2_trans_update(trans, BTREE_INSERT_ENTRY(slot, insert));
- return 0;
+ return bch2_trans_iter_free(trans, iter) ?: -ENOSPC;
found:
- if (flags & BCH_HASH_SET_MUST_CREATE)
- return -EEXIST;
+ found = true;
+not_found:
- insert->k.p = iter->pos;
- bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, insert));
- return 0;
+ 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;
+ bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, insert));
+ bch2_trans_iter_free_on_commit(trans, iter);
+ }
+
+ return ret;
}
static __always_inline
diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c
index a6d70ce524e9..f97315139c71 100644
--- a/fs/bcachefs/sysfs.c
+++ b/fs/bcachefs/sysfs.c
@@ -281,7 +281,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)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
u64 nr_uncompressed_extents = 0, uncompressed_sectors = 0,
nr_compressed_extents = 0,
@@ -291,7 +292,9 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
if (!test_bit(BCH_FS_STARTED, &c->flags))
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) {
struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
const union bch_extent_entry *entry;
@@ -313,7 +316,7 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
break;
}
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
return scnprintf(buf, PAGE_SIZE,
"uncompressed data:\n"
diff --git a/fs/bcachefs/tests.c b/fs/bcachefs/tests.c
index c9362af56511..a7b6fef21aef 100644
--- a/fs/bcachefs/tests.c
+++ b/fs/bcachefs/tests.c
@@ -88,11 +88,14 @@ static void test_delete_written(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;
u64 i;
int ret;
+ bch2_trans_init(&trans, c);
+
delete_test_keys(c);
pr_info("inserting test keys");
@@ -112,28 +115,31 @@ static void test_iterate(struct bch_fs *c, u64 nr)
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++);
- bch2_btree_iter_unlock(&iter);
BUG_ON(i != nr);
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);
- bch2_btree_iter_unlock(&iter);
BUG_ON(i);
+
+ bch2_trans_exit(&trans);
}
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;
u64 i;
int ret;
+ bch2_trans_init(&trans, c);
+
delete_test_keys(c);
pr_info("inserting test extents");
@@ -154,32 +160,35 @@ static void test_iterate_extents(struct bch_fs *c, u64 nr)
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);
i = k.k->p.offset;
}
- bch2_btree_iter_unlock(&iter);
BUG_ON(i != nr);
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);
i = bkey_start_offset(k.k);
}
- bch2_btree_iter_unlock(&iter);
BUG_ON(i);
+
+ bch2_trans_exit(&trans);
}
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;
u64 i;
int ret;
+ bch2_trans_init(&trans, c);
+
delete_test_keys(c);
pr_info("inserting test keys");
@@ -199,11 +208,11 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
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);
i += 2;
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_iter_free(&trans, iter);
BUG_ON(i != nr * 2);
@@ -211,7 +220,7 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
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) {
BUG_ON(bkey_deleted(k.k) != (i & 1));
BUG_ON(k.k->p.offset != i++);
@@ -219,16 +228,20 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
if (i == nr * 2)
break;
}
- bch2_btree_iter_unlock(&iter);
+
+ bch2_trans_exit(&trans);
}
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;
u64 i;
int ret;
+ bch2_trans_init(&trans, c);
+
delete_test_keys(c);
pr_info("inserting test keys");
@@ -249,12 +262,12 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
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(k.k->size != 8);
i += 16;
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_iter_free(&trans, iter);
BUG_ON(i != nr);
@@ -262,7 +275,7 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
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) {
BUG_ON(bkey_deleted(k.k) != !(i % 16));
@@ -273,7 +286,8 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
if (i == nr)
break;
}
- bch2_btree_iter_unlock(&iter);
+
+ bch2_trans_exit(&trans);
}
/*
@@ -282,34 +296,40 @@ static void test_iterate_slots_extents(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;
- 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);
- k = bch2_btree_iter_peek(&iter);
+ k = bch2_btree_iter_peek(iter);
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)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
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);
- k = bch2_btree_iter_peek(&iter);
+ k = bch2_btree_iter_peek(iter);
BUG_ON(k.k);
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
}
/* extent unit tests */
@@ -400,32 +420,35 @@ static void rand_insert(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;
- for (i = 0; i < nr; i++) {
- struct btree_iter iter;
- struct bkey_s_c k;
+ bch2_trans_init(&trans, c);
- bch2_btree_iter_init(&iter, c, BTREE_ID_DIRENTS,
- POS(0, test_rand()), 0);
+ for (i = 0; i < nr; i++) {
+ iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS,
+ POS(0, test_rand()), 0);
- k = bch2_btree_iter_peek(&iter);
- bch2_btree_iter_unlock(&iter);
+ k = bch2_btree_iter_peek(iter);
+ bch2_trans_iter_free(&trans, iter);
}
+
+ bch2_trans_exit(&trans);
}
static void rand_mixed(struct bch_fs *c, u64 nr)
{
+ struct btree_trans trans;
+ struct btree_iter *iter;
+ struct bkey_s_c k;
int ret;
u64 i;
- for (i = 0; i < nr; i++) {
- struct btree_trans trans;
- struct btree_iter *iter;
- struct bkey_s_c k;
-
- 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,
POS(0, test_rand()), 0);
@@ -442,9 +465,10 @@ static void rand_mixed(struct bch_fs *c, u64 nr)
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)
@@ -494,12 +518,15 @@ static void seq_insert(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;
- 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)
diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c
index b204b53bb9d6..5ba52a3ff0b2 100644
--- a/fs/bcachefs/xattr.c
+++ b/fs/bcachefs/xattr.c
@@ -270,12 +270,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_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;
u64 inum = dentry->d_inode->i_ino;
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);
if (k.k->p.inode > inum)
@@ -289,7 +293,7 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
if (ret < 0)
break;
}
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_exit(&trans);
if (ret < 0)
return ret;