- int ret = 0;
- struct bkey_s_c k;
- struct bkey_s_c_extent e;
- struct btree_iter iter;
-
- bch2_btree_iter_init(&iter, ca->fs, BTREE_ID_EXTENTS,
- POS_MIN, BTREE_ITER_PREFETCH);
-
- while ((k = bch2_btree_iter_peek(&iter)).k &&
- !(ret = btree_iter_err(k))) {
- if (!bkey_extent_is_data(k.k))
- goto advance;
-
- e = bkey_s_c_to_extent(k);
- if (!bch2_extent_has_device(e, ca->dev_idx))
- goto advance;
-
- ret = bch2_flag_key_bad(&iter, ca, e);
-
- /*
- * don't want to leave ret == -EINTR, since if we raced and
- * something else overwrote the key we could spuriously return
- * -EINTR below:
- */
- if (ret == -EINTR)
- ret = 0;
- if (ret)
- break;
-
- /*
- * If the replica we're dropping was dirty and there is an
- * additional cached replica, the cached replica will now be
- * considered dirty - upon inserting the new version of the key,
- * the bucket accounting will be updated to reflect the fact
- * that the cached data is now dirty and everything works out as
- * if by magic without us having to do anything.
- *
- * The one thing we need to be concerned with here is there's a
- * race between when we drop any stale pointers from the key
- * we're about to insert, and when the key actually gets
- * inserted and the cached data is marked as dirty - we could
- * end up trying to insert a key with a pointer that should be
- * dirty, but points to stale data.
- *
- * If that happens the insert code just bails out and doesn't do
- * the insert - however, it doesn't return an error. Hence we
- * need to always recheck the current key before advancing to
- * the next:
- */
- continue;
-advance:
- bch2_btree_iter_advance_pos(&iter);
- }
-
- bch2_btree_iter_unlock(&iter);
-
- return ret;