]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: add check for missing fragmentation in check_alloc_to_lru_ref()
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 29 Jun 2024 22:35:18 +0000 (18:35 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 29 Jun 2024 22:35:18 +0000 (18:35 -0400)
We need to make sure we're not missing any fragmenation entries in the
LRU BTREE after repairing ALLOC BTREE

Also, use the new bch2_btree_write_buffer_maybe_flush() helper; this was
only working without it before since bucket invalidation (usually)
wasn't happening while fsck was running.

Co-developed-by: Daniel Hill <daniel@gluo.nz>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/lru.c
fs/bcachefs/lru.h

index 1de9fac3bcf4f77f627028bc9cb0a586b039a518..658f11aebda1f6f17e77ee2e1cb9fabae3f4522c 100644 (file)
@@ -3,6 +3,7 @@
 #include "alloc_background.h"
 #include "alloc_foreground.h"
 #include "backpointers.h"
+#include "bkey_buf.h"
 #include "btree_cache.h"
 #include "btree_io.h"
 #include "btree_key_cache.h"
@@ -1553,13 +1554,13 @@ err:
 }
 
 static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
-                                      struct btree_iter *alloc_iter)
+                                      struct btree_iter *alloc_iter,
+                                      struct bkey_buf *last_flushed)
 {
        struct bch_fs *c = trans->c;
-       struct btree_iter lru_iter;
        struct bch_alloc_v4 a_convert;
        const struct bch_alloc_v4 *a;
-       struct bkey_s_c alloc_k, lru_k;
+       struct bkey_s_c alloc_k;
        struct printbuf buf = PRINTBUF;
        int ret;
 
@@ -1573,6 +1574,14 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
 
        a = bch2_alloc_to_v4(alloc_k, &a_convert);
 
+       if (a->fragmentation_lru) {
+               ret = bch2_lru_check_set(trans, BCH_LRU_FRAGMENTATION_START,
+                                        a->fragmentation_lru,
+                                        alloc_k, last_flushed);
+               if (ret)
+                       return ret;
+       }
+
        if (a->data_type != BCH_DATA_cached)
                return 0;
 
@@ -1597,41 +1606,30 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
                a = &a_mut->v;
        }
 
-       lru_k = bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
-                            lru_pos(alloc_k.k->p.inode,
-                                    bucket_to_u64(alloc_k.k->p),
-                                    a->io_time[READ]), 0);
-       ret = bkey_err(lru_k);
+       ret = bch2_lru_check_set(trans, alloc_k.k->p.inode, a->io_time[READ],
+                                alloc_k, last_flushed);
        if (ret)
-               return ret;
-
-       if (fsck_err_on(lru_k.k->type != KEY_TYPE_set, c,
-                       alloc_key_to_missing_lru_entry,
-                       "missing lru entry\n"
-                       "  %s",
-                       (printbuf_reset(&buf),
-                        bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
-               ret = bch2_lru_set(trans,
-                                  alloc_k.k->p.inode,
-                                  bucket_to_u64(alloc_k.k->p),
-                                  a->io_time[READ]);
-               if (ret)
-                       goto err;
-       }
+               goto err;
 err:
 fsck_err:
-       bch2_trans_iter_exit(trans, &lru_iter);
        printbuf_exit(&buf);
        return ret;
 }
 
 int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
 {
+       struct bkey_buf last_flushed;
+
+       bch2_bkey_buf_init(&last_flushed);
+       bkey_init(&last_flushed.k->k);
+
        int ret = bch2_trans_run(c,
                for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
                                POS_MIN, BTREE_ITER_prefetch, k,
                                NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
-                       bch2_check_alloc_to_lru_ref(trans, &iter)));
+                       bch2_check_alloc_to_lru_ref(trans, &iter, &last_flushed)));
+
+       bch2_bkey_buf_exit(&last_flushed, c);
        bch_err_fn(c, ret);
        return ret;
 }
index a40d116224edd9f3ef71464b4756b51262fb143e..b12894ef44f302887df2084a3c0d1c02eec56fb3 100644 (file)
@@ -77,6 +77,45 @@ static const char * const bch2_lru_types[] = {
        NULL
 };
 
+int bch2_lru_check_set(struct btree_trans *trans,
+                      u16 lru_id, u64 time,
+                      struct bkey_s_c referring_k,
+                      struct bkey_buf *last_flushed)
+{
+       struct bch_fs *c = trans->c;
+       struct printbuf buf = PRINTBUF;
+       struct btree_iter lru_iter;
+       struct bkey_s_c lru_k =
+               bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
+                                  lru_pos(lru_id,
+                                          bucket_to_u64(referring_k.k->p),
+                                          time), 0);
+       int ret = bkey_err(lru_k);
+       if (ret)
+               return ret;
+
+       if (lru_k.k->type != KEY_TYPE_set) {
+               ret = bch2_btree_write_buffer_maybe_flush(trans, referring_k, last_flushed);
+               if (ret)
+                       goto err;
+
+               if (fsck_err(c, alloc_key_to_missing_lru_entry,
+                            "missing %s lru entry\n"
+                            "  %s",
+                            bch2_lru_types[lru_type(lru_k)],
+                            (bch2_bkey_val_to_text(&buf, c, referring_k), buf.buf))) {
+                       ret = bch2_lru_set(trans, lru_id, bucket_to_u64(referring_k.k->p), time);
+                       if (ret)
+                               goto err;
+               }
+       }
+err:
+fsck_err:
+       bch2_trans_iter_exit(trans, &lru_iter);
+       printbuf_exit(&buf);
+       return ret;
+}
+
 static int bch2_check_lru_key(struct btree_trans *trans,
                              struct btree_iter *lru_iter,
                              struct bkey_s_c lru_k,
index bd71ba77de078a326f8af30a9334a339ec4fe95b..ed75bcf59d4786d7dd34a92fd2f1345fdec8a016 100644 (file)
@@ -61,6 +61,9 @@ int bch2_lru_del(struct btree_trans *, u16, u64, u64);
 int bch2_lru_set(struct btree_trans *, u16, u64, u64);
 int bch2_lru_change(struct btree_trans *, u16, u64, u64, u64);
 
+struct bkey_buf;
+int bch2_lru_check_set(struct btree_trans *, u16, u64, struct bkey_s_c, struct bkey_buf *);
+
 int bch2_check_lrus(struct bch_fs *);
 
 #endif /* _BCACHEFS_LRU_H */