bcachefs: Change btree_iter_traverse_error() to not use iter->next
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 28 Mar 2019 02:54:42 +0000 (22:54 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:19 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.c

index f018ca7999f74560bda9ba6d763e1d02fee1deaf..0d3e99370a98dca7f907540bb5d4c27638887d12 100644 (file)
@@ -956,10 +956,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;
@@ -975,48 +987,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;