]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bcachefs: get_existing_stripe() uses new stripe lru
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 11 Feb 2025 01:34:47 +0000 (20:34 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Mar 2025 01:02:16 +0000 (21:02 -0400)
Convert to the new persistent stripe LRU.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/ec.c
fs/bcachefs/ec.h

index dba4b599f82745a92f2841f76629ef080462cf29..84f232f4cbf8c1c0669ff49006f6c313a7f078b2 100644 (file)
@@ -1981,39 +1981,40 @@ static int new_stripe_alloc_buckets(struct btree_trans *trans,
        return 0;
 }
 
-static s64 get_existing_stripe(struct bch_fs *c,
-                              struct ec_stripe_head *head)
+static int __get_existing_stripe(struct btree_trans *trans,
+                                struct ec_stripe_head *head,
+                                struct ec_stripe_buf *stripe,
+                                u64 idx)
 {
-       ec_stripes_heap *h = &c->ec_stripes_heap;
-       struct stripe *m;
-       size_t heap_idx;
-       u64 stripe_idx;
-       s64 ret = -1;
-
-       if (may_create_new_stripe(c))
-               return -1;
+       struct bch_fs *c = trans->c;
 
-       mutex_lock(&c->ec_stripes_heap_lock);
-       for (heap_idx = 0; heap_idx < h->nr; heap_idx++) {
-               /* No blocks worth reusing, stripe will just be deleted: */
-               if (!h->data[heap_idx].blocks_nonempty)
-                       continue;
+       struct btree_iter iter;
+       struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter,
+                                         BTREE_ID_stripes, POS(0, idx), 0);
+       int ret = bkey_err(k);
+       if (ret)
+               goto err;
 
-               stripe_idx = h->data[heap_idx].idx;
+       /* We expect write buffer races here */
+       if (k.k->type != KEY_TYPE_stripe)
+               goto out;
 
-               m = genradix_ptr(&c->stripes, stripe_idx);
+       struct bkey_s_c_stripe s = bkey_s_c_to_stripe(k);
+       if (stripe_lru_pos(s.v) <= 1)
+               goto out;
 
-               if (m->disk_label       == head->disk_label &&
-                   m->algorithm        == head->algo &&
-                   m->nr_redundant     == head->redundancy &&
-                   m->sectors          == head->blocksize &&
-                   m->blocks_nonempty  < m->nr_blocks - m->nr_redundant &&
-                   bch2_try_open_stripe(c, head->s, stripe_idx)) {
-                       ret = stripe_idx;
-                       break;
-               }
+       if (s.v->disk_label             == head->disk_label &&
+           s.v->algorithm              == head->algo &&
+           s.v->nr_redundant           == head->redundancy &&
+           le16_to_cpu(s.v->sectors)   == head->blocksize &&
+           bch2_try_open_stripe(c, head->s, idx)) {
+               bkey_reassemble(&stripe->key, k);
+               ret = 1;
        }
-       mutex_unlock(&c->ec_stripes_heap_lock);
+out:
+       bch2_set_btree_iter_dontneed(&iter);
+err:
+       bch2_trans_iter_exit(trans, &iter);
        return ret;
 }
 
@@ -2065,24 +2066,33 @@ static int __bch2_ec_stripe_head_reuse(struct btree_trans *trans, struct ec_stri
                                       struct ec_stripe_new *s)
 {
        struct bch_fs *c = trans->c;
-       s64 idx;
-       int ret;
 
        /*
         * If we can't allocate a new stripe, and there's no stripes with empty
         * blocks for us to reuse, that means we have to wait on copygc:
         */
-       idx = get_existing_stripe(c, h);
-       if (idx < 0)
-               return -BCH_ERR_stripe_alloc_blocked;
+       if (may_create_new_stripe(c))
+               return -1;
 
-       ret = get_stripe_key_trans(trans, idx, &s->existing_stripe);
-       bch2_fs_fatal_err_on(ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart), c,
-                            "reading stripe key: %s", bch2_err_str(ret));
-       if (ret) {
-               bch2_stripe_close(c, s);
-               return ret;
+       struct btree_iter lru_iter;
+       struct bkey_s_c lru_k;
+       int ret = 0;
+
+       for_each_btree_key_max_norestart(trans, lru_iter, BTREE_ID_lru,
+                       lru_pos(BCH_LRU_STRIPE_FRAGMENTATION, 2, 0),
+                       lru_pos(BCH_LRU_STRIPE_FRAGMENTATION, 2, LRU_TIME_MAX),
+                       0, lru_k, ret) {
+               ret = __get_existing_stripe(trans, h, &s->existing_stripe, lru_k.k->p.offset);
+               if (ret)
+                       break;
        }
+       bch2_trans_iter_exit(trans, &lru_iter);
+       if (!ret)
+               ret = -BCH_ERR_stripe_alloc_blocked;
+       if (ret == 1)
+               ret = 0;
+       if (ret)
+               return ret;
 
        return init_new_stripe_from_existing(c, s);
 }
index cd1c837e4933627d2a9d200139cc3177f2a3cc2d..3008d41db12d6078ed29aac8004267365e9becfc 100644 (file)
@@ -99,15 +99,13 @@ static inline u64 stripe_lru_pos(const struct bch_stripe *s)
        if (!s)
                return 0;
 
-       unsigned blocks_empty = 0, blocks_nonempty = 0;
+       unsigned nr_data = s->nr_blocks - s->nr_redundant, blocks_empty = 0;
 
-       for (unsigned i = 0; i < s->nr_blocks; i++) {
-               blocks_empty    +=  !stripe_blockcount_get(s, i);
-               blocks_nonempty += !!stripe_blockcount_get(s, i);
-       }
+       for (unsigned i = 0; i < nr_data; i++)
+               blocks_empty += !stripe_blockcount_get(s, i);
 
        /* Will be picked up by the stripe_delete worker */
-       if (!blocks_nonempty)
+       if (blocks_empty == nr_data)
                return STRIPE_LRU_POS_EMPTY;
 
        if (!blocks_empty)