]> www.infradead.org Git - users/hch/xfs.git/commitdiff
bcachefs: Handle cached data LRU wraparound
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 17 Jun 2024 17:15:16 +0000 (13:15 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Wed, 19 Jun 2024 22:27:24 +0000 (18:27 -0400)
We only have 48 bits for the LRU time field, which is insufficient to
prevent wraparound.

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

index e258de70457893a2e8610e88bda4826ecd7af2cd..7b5909764d148170c0acf52ce75d3bb1bde7fee3 100644 (file)
@@ -2019,6 +2019,21 @@ err:
        goto out;
 }
 
+static struct bkey_s_c next_lru_key(struct btree_trans *trans, struct btree_iter *iter,
+                                   struct bch_dev *ca, bool *wrapped)
+{
+       struct bkey_s_c k;
+again:
+       k = bch2_btree_iter_peek_upto(iter, lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX));
+       if (!k.k && !*wrapped) {
+               bch2_btree_iter_set_pos(iter, lru_pos(ca->dev_idx, 0, 0));
+               *wrapped = true;
+               goto again;
+       }
+
+       return k;
+}
+
 static void bch2_do_invalidates_work(struct work_struct *work)
 {
        struct bch_fs *c = container_of(work, struct bch_fs, invalidate_work);
@@ -2032,12 +2047,33 @@ static void bch2_do_invalidates_work(struct work_struct *work)
        for_each_member_device(c, ca) {
                s64 nr_to_invalidate =
                        should_invalidate_buckets(ca, bch2_dev_usage_read(ca));
+               struct btree_iter iter;
+               bool wrapped = false;
+
+               bch2_trans_iter_init(trans, &iter, BTREE_ID_lru,
+                                    lru_pos(ca->dev_idx, 0,
+                                            ((bch2_current_io_time(c, READ) + U32_MAX) &
+                                             LRU_TIME_MAX)), 0);
 
-               ret = for_each_btree_key_upto(trans, iter, BTREE_ID_lru,
-                               lru_pos(ca->dev_idx, 0, 0),
-                               lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX),
-                               BTREE_ITER_intent, k,
-                       invalidate_one_bucket(trans, &iter, k, &nr_to_invalidate));
+               while (true) {
+                       bch2_trans_begin(trans);
+
+                       struct bkey_s_c k = next_lru_key(trans, &iter, ca, &wrapped);
+                       ret = bkey_err(k);
+                       if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
+                               continue;
+                       if (ret)
+                               break;
+                       if (!k.k)
+                               break;
+
+                       ret = invalidate_one_bucket(trans, &iter, k, &nr_to_invalidate);
+                       if (ret)
+                               break;
+
+                       bch2_btree_iter_advance(&iter);
+               }
+               bch2_trans_iter_exit(trans, &iter);
 
                if (ret < 0) {
                        bch2_dev_put(ca);