diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-03-27 22:54:42 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2019-03-28 00:12:47 -0400 |
commit | 63f0cd28491e10229bbe1d41d88dcc3afce6be11 (patch) | |
tree | 2ad3a401bec9ef604dc3282aaa4f6567d0b1c23c | |
parent | f7b1bf41873579d4f494d0f0c80325de3862b716 (diff) |
bcachefs: Change btree_iter_traverse_error() to not use iter->next
-rw-r--r-- | fs/bcachefs/btree_iter.c | 65 |
1 files changed, 24 insertions, 41 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index f4f2c1cfde4e..4e14d1ad5756 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -955,10 +955,22 @@ int __must_check __bch2_btree_iter_traverse(struct btree_iter *); static int btree_iter_traverse_error(struct btree_iter *iter, int ret) { - struct bch_fs *c = iter->trans->c; - struct btree_iter *linked, *sorted_iters, **i; + struct btree_trans *trans = iter->trans; + struct bch_fs *c = trans->c; + u8 sorted[BTREE_ITER_MAX]; + unsigned i, nr_sorted = 0; + + trans_for_each_iter(trans, iter) + sorted[nr_sorted++] = iter - trans->iters; + +#define btree_iter_cmp_by_idx(_l, _r) \ + btree_iter_cmp(&trans->iters[_l], &trans->iters[_r]) + + bubble_sort(sorted, nr_sorted, btree_iter_cmp_by_idx); +#undef btree_iter_cmp_by_idx + retry_all: - bch2_btree_iter_unlock(iter); + bch2_btree_trans_unlock(trans); if (ret != -ENOMEM && ret != -EINTR) goto io_error; @@ -974,48 +986,19 @@ retry_all: } while (ret); } - /* - * Linked iters are normally a circular singly linked list - break cycle - * while we sort them: - */ - linked = iter->next; - iter->next = NULL; - sorted_iters = NULL; - - while (linked) { - iter = linked; - linked = linked->next; - - i = &sorted_iters; - while (*i && btree_iter_cmp(iter, *i) > 0) - i = &(*i)->next; - - iter->next = *i; - *i = iter; - } - - /* Make list circular again: */ - iter = sorted_iters; - while (iter->next) - iter = iter->next; - iter->next = sorted_iters; - /* Now, redo traversals in correct order: */ + for (i = 0; i < nr_sorted; i++) { + iter = &trans->iters[sorted[i]]; - iter = sorted_iters; - do { -retry: - ret = __bch2_btree_iter_traverse(iter); - if (unlikely(ret)) { - if (ret == -EINTR) - goto retry; - goto retry_all; - } + do { + ret = __bch2_btree_iter_traverse(iter); + } while (ret == -EINTR); - iter = iter->next; - } while (iter != sorted_iters); + if (ret) + goto retry_all; + } - ret = btree_trans_has_multiple_iters(iter->trans) ? -EINTR : 0; + ret = btree_trans_has_multiple_iters(trans) ? -EINTR : 0; out: bch2_btree_cache_cannibalize_unlock(c); return ret; |