summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-28 00:07:24 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2019-03-28 00:12:47 -0400
commit410c5d508c524d892e1e2e629a21f19064d145f6 (patch)
tree523fdbdb4b606aece26415a9ff7d99413617870a
parent60a348a914f5192812d35f6bf449c5d2c757314c (diff)
bcachefs: traverse all iterators on transaction restart
-rw-r--r--fs/bcachefs/btree_iter.c30
-rw-r--r--fs/bcachefs/btree_iter.h1
-rw-r--r--fs/bcachefs/btree_update_leaf.c11
3 files changed, 23 insertions, 19 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index c01ceed476f7..cd00e68e7036 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -953,9 +953,9 @@ static void btree_iter_up(struct btree_iter *iter)
int __must_check __bch2_btree_iter_traverse(struct btree_iter *);
-static int btree_iter_traverse_error(struct btree_iter *iter, int ret)
+static int __btree_iter_traverse_all(struct btree_trans *trans,
+ struct btree_iter *iter, int ret)
{
- struct btree_trans *trans = iter->trans;
struct bch_fs *c = trans->c;
u8 sorted[BTREE_ITER_MAX];
unsigned i, nr_sorted = 0;
@@ -972,10 +972,7 @@ static int btree_iter_traverse_error(struct btree_iter *iter, int ret)
retry_all:
bch2_btree_trans_unlock(trans);
- if (ret != -ENOMEM && ret != -EINTR)
- goto io_error;
-
- if (ret == -ENOMEM) {
+ if (unlikely(ret == -ENOMEM)) {
struct closure cl;
closure_init_stack(&cl);
@@ -986,6 +983,14 @@ retry_all:
} while (ret);
}
+ if (unlikely(ret == -EIO)) {
+ iter->flags |= BTREE_ITER_ERROR;
+ iter->l[iter->level].b = BTREE_ITER_NOT_END;
+ goto out;
+ }
+
+ BUG_ON(ret && ret != -EINTR);
+
/* Now, redo traversals in correct order: */
for (i = 0; i < nr_sorted; i++) {
iter = &trans->iters[sorted[i]];
@@ -1002,12 +1007,11 @@ retry_all:
out:
bch2_btree_cache_cannibalize_unlock(c);
return ret;
-io_error:
- BUG_ON(ret != -EIO);
+}
- iter->flags |= BTREE_ITER_ERROR;
- iter->l[iter->level].b = BTREE_ITER_NOT_END;
- goto out;
+int bch2_btree_iter_traverse_all(struct btree_trans *trans)
+{
+ return __btree_iter_traverse_all(trans, NULL, 0);
}
static unsigned btree_iter_up_until_locked(struct btree_iter *iter,
@@ -1095,7 +1099,7 @@ int __must_check bch2_btree_iter_traverse(struct btree_iter *iter)
ret = __bch2_btree_iter_traverse(iter);
if (unlikely(ret))
- ret = btree_iter_traverse_error(iter, ret);
+ ret = __btree_iter_traverse_all(iter->trans, iter, ret);
BUG_ON(ret == -EINTR && !btree_trans_has_multiple_iters(iter->trans));
@@ -1921,6 +1925,8 @@ void __bch2_trans_begin(struct btree_trans *trans)
trans->iters_unlink_on_commit = 0;
trans->nr_updates = 0;
trans->mem_top = 0;
+
+ bch2_btree_iter_traverse_all(trans);
}
void bch2_trans_init(struct btree_trans *trans, struct bch_fs *c)
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index a0790c56a948..c05b2dac1726 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -136,6 +136,7 @@ void bch2_btree_iter_node_drop(struct btree_iter *, struct btree *);
void bch2_btree_iter_reinit_node(struct btree_iter *, struct btree *);
int __must_check bch2_btree_iter_traverse(struct btree_iter *);
+int bch2_btree_iter_traverse_all(struct btree_trans *);
struct btree *bch2_btree_iter_peek_node(struct btree_iter *);
struct btree *bch2_btree_iter_next_node(struct btree_iter *, unsigned);
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index b6baf18968de..8c13a2e3e13f 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -707,14 +707,11 @@ int bch2_trans_commit_error(struct btree_trans *trans,
}
if (ret == -EINTR) {
- trans_for_each_update_iter(trans, i) {
- int ret2 = bch2_btree_iter_traverse(i->iter);
- if (ret2) {
- trans_restart(" (traverse)");
- return ret2;
- }
+ int ret2 = bch2_btree_iter_traverse_all(trans);
- BUG_ON(i->iter->uptodate > BTREE_ITER_NEED_PEEK);
+ if (ret2) {
+ trans_restart(" (traverse)");
+ return ret2;
}
/*