diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-03-28 00:07:24 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2019-03-28 00:12:47 -0400 |
commit | 410c5d508c524d892e1e2e629a21f19064d145f6 (patch) | |
tree | 523fdbdb4b606aece26415a9ff7d99413617870a | |
parent | 60a348a914f5192812d35f6bf449c5d2c757314c (diff) |
bcachefs: traverse all iterators on transaction restart
-rw-r--r-- | fs/bcachefs/btree_iter.c | 30 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 11 |
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; } /* |