bcachefs: Kill alloc_v4.fragmentation_lru
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 1 Oct 2024 23:08:37 +0000 (19:08 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 5 Oct 2024 00:25:32 +0000 (20:25 -0400)
The fragmentation_lru field hasn't been needed since we reworked the LRU
btrees to use the btree write buffer; previously it was used to resolve
collisions, but the revised LRU btree uses the backpointer (the bucket)
as part of the key.

It should have been deleted at the time of the LRU rework; since it
wasn't, that left places for bugs to hide, in check/repair.

This fixes LRU fsck on a filesystem image helpfully provided by a user
who disappeared before I could get his name for the reported-by.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/alloc_background_format.h
fs/bcachefs/btree_gc.c
fs/bcachefs/lru.c
fs/bcachefs/move.c
fs/bcachefs/movinggc.c
fs/bcachefs/sb-errors_format.h

index 645b5ed..4e4a448 100644 (file)
@@ -332,7 +332,6 @@ void bch2_alloc_v4_swab(struct bkey_s k)
        a->io_time[1]           = swab64(a->io_time[1]);
        a->stripe               = swab32(a->stripe);
        a->nr_external_backpointers = swab32(a->nr_external_backpointers);
-       a->fragmentation_lru    = swab64(a->fragmentation_lru);
        a->stripe_sectors       = swab32(a->stripe_sectors);
 
        bps = alloc_v4_backpointers(a);
@@ -347,6 +346,7 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
 {
        struct bch_alloc_v4 _a;
        const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &_a);
+       struct bch_dev *ca = c ? bch2_dev_bucket_tryget_noerror(c, k.k->p) : NULL;
 
        prt_newline(out);
        printbuf_indent_add(out, 2);
@@ -364,9 +364,13 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
        prt_printf(out, "stripe_redundancy %u\n",       a->stripe_redundancy);
        prt_printf(out, "io_time[READ]     %llu\n",     a->io_time[READ]);
        prt_printf(out, "io_time[WRITE]    %llu\n",     a->io_time[WRITE]);
-       prt_printf(out, "fragmentation     %llu\n",     a->fragmentation_lru);
+
+       if (ca)
+               prt_printf(out, "fragmentation     %llu\n",     alloc_lru_idx_fragmentation(*a, ca));
        prt_printf(out, "bp_start          %llu\n", BCH_ALLOC_V4_BACKPOINTERS_START(a));
        printbuf_indent_sub(out, 2);
+
+       bch2_dev_put(ca);
 }
 
 void __bch2_alloc_to_v4(struct bkey_s_c k, struct bch_alloc_v4 *out)
@@ -882,12 +886,13 @@ int bch2_trigger_alloc(struct btree_trans *trans,
                                goto err;
                }
 
-               new_a->fragmentation_lru = alloc_lru_idx_fragmentation(*new_a, ca);
-               if (old_a->fragmentation_lru != new_a->fragmentation_lru) {
+               old_lru = alloc_lru_idx_fragmentation(*old_a, ca);
+               new_lru = alloc_lru_idx_fragmentation(*new_a, ca);
+               if (old_lru != new_lru) {
                        ret = bch2_lru_change(trans,
                                        BCH_LRU_FRAGMENTATION_START,
                                        bucket_to_u64(new.k->p),
-                                       old_a->fragmentation_lru, new_a->fragmentation_lru);
+                                       old_lru, new_lru);
                        if (ret)
                                goto err;
                }
@@ -1629,18 +1634,22 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
        if (ret)
                return ret;
 
+       struct bch_dev *ca = bch2_dev_tryget_noerror(c, alloc_k.k->p.inode);
+       if (!ca)
+               return 0;
+
        a = bch2_alloc_to_v4(alloc_k, &a_convert);
 
-       if (a->fragmentation_lru) {
+       u64 lru_idx = alloc_lru_idx_fragmentation(*a, ca);
+       if (lru_idx) {
                ret = bch2_lru_check_set(trans, BCH_LRU_FRAGMENTATION_START,
-                                        a->fragmentation_lru,
-                                        alloc_k, last_flushed);
+                                        lru_idx, alloc_k, last_flushed);
                if (ret)
-                       return ret;
+                       goto err;
        }
 
        if (a->data_type != BCH_DATA_cached)
-               return 0;
+               goto err;
 
        if (fsck_err_on(!a->io_time[READ],
                        trans, alloc_key_cached_but_read_time_zero,
@@ -1669,6 +1678,7 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
                goto err;
 err:
 fsck_err:
+       bch2_dev_put(ca);
        printbuf_exit(&buf);
        return ret;
 }
index f754a29..befdaa9 100644 (file)
@@ -70,7 +70,7 @@ struct bch_alloc_v4 {
        __u32                   stripe;
        __u32                   nr_external_backpointers;
        /* end of fields in original version of alloc_v4 */
-       __u64                   fragmentation_lru;
+       __u64                   _fragmentation_lru; /* obsolete */
        __u32                   stripe_sectors;
        __u32                   pad;
 } __packed __aligned(8);
index 660d2fa..771154e 100644 (file)
@@ -828,8 +828,6 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
                        return ret;
        }
 
-       gc.fragmentation_lru = alloc_lru_idx_fragmentation(gc, ca);
-
        if (fsck_err_on(new.data_type != gc.data_type,
                        trans, alloc_key_data_type_wrong,
                        "bucket %llu:%llu gen %u has wrong data_type"
@@ -857,7 +855,6 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
        copy_bucket_field(alloc_key_cached_sectors_wrong,       cached_sectors);
        copy_bucket_field(alloc_key_stripe_wrong,               stripe);
        copy_bucket_field(alloc_key_stripe_redundancy_wrong,    stripe_redundancy);
-       copy_bucket_field(alloc_key_fragmentation_lru_wrong,    fragmentation_lru);
 #undef copy_bucket_field
 
        if (!bch2_alloc_v4_cmp(*old, new))
index dd5df66..10857ec 100644 (file)
@@ -133,7 +133,9 @@ static int bch2_check_lru_key(struct btree_trans *trans,
        u64 idx;
        int ret;
 
-       if (fsck_err_on(!bch2_dev_bucket_exists(c, alloc_pos),
+       struct bch_dev *ca = bch2_dev_bucket_tryget_noerror(c, alloc_pos);
+
+       if (fsck_err_on(!ca,
                        trans, lru_entry_to_invalid_bucket,
                        "lru key points to nonexistent device:bucket %llu:%llu",
                        alloc_pos.inode, alloc_pos.offset))
@@ -151,7 +153,7 @@ static int bch2_check_lru_key(struct btree_trans *trans,
                idx = alloc_lru_idx_read(*a);
                break;
        case BCH_LRU_fragmentation:
-               idx = a->fragmentation_lru;
+               idx = alloc_lru_idx_fragmentation(*a, ca);
                break;
        }
 
@@ -174,6 +176,7 @@ static int bch2_check_lru_key(struct btree_trans *trans,
 err:
 fsck_err:
        bch2_trans_iter_exit(trans, &iter);
+       bch2_dev_put(ca);
        printbuf_exit(&buf2);
        printbuf_exit(&buf1);
        return ret;
index 7d3920e..8c456d8 100644 (file)
@@ -692,7 +692,7 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
        a = bch2_alloc_to_v4(k, &a_convert);
        dirty_sectors = bch2_bucket_sectors_dirty(*a);
        bucket_size = ca->mi.bucket_size;
-       fragmentation = a->fragmentation_lru;
+       fragmentation = alloc_lru_idx_fragmentation(*a, ca);
 
        ret = bch2_btree_write_buffer_tryflush(trans);
        bch_err_msg(c, ret, "flushing btree write buffer");
index d86565b..d658be9 100644 (file)
@@ -73,6 +73,7 @@ move_bucket_in_flight_add(struct buckets_in_flight *list, struct move_bucket b)
 static int bch2_bucket_is_movable(struct btree_trans *trans,
                                  struct move_bucket *b, u64 time)
 {
+       struct bch_fs *c = trans->c;
        struct btree_iter iter;
        struct bkey_s_c k;
        struct bch_alloc_v4 _a;
@@ -90,14 +91,19 @@ static int bch2_bucket_is_movable(struct btree_trans *trans,
        if (ret)
                return ret;
 
+       struct bch_dev *ca = bch2_dev_tryget(c, k.k->p.inode);
+       if (!ca)
+               goto out;
+
        a = bch2_alloc_to_v4(k, &_a);
        b->k.gen        = a->gen;
        b->sectors      = bch2_bucket_sectors_dirty(*a);
+       u64 lru_idx     = alloc_lru_idx_fragmentation(*a, ca);
 
-       ret = data_type_movable(a->data_type) &&
-               a->fragmentation_lru &&
-               a->fragmentation_lru <= time;
+       ret = lru_idx && lru_idx <= time;
 
+       bch2_dev_put(ca);
+out:
        bch2_trans_iter_exit(trans, &iter);
        return ret;
 }
index 6a63d24..b402487 100644 (file)
@@ -115,8 +115,8 @@ enum bch_fsck_flags {
        x(alloc_key_data_type_inconsistency,                    101,    0)              \
        x(alloc_key_to_missing_dev_bucket,                      102,    0)              \
        x(alloc_key_cached_inconsistency,                       103,    0)              \
-       x(alloc_key_cached_but_read_time_zero,                  104,    0)              \
-       x(alloc_key_to_missing_lru_entry,                       105,    0)              \
+       x(alloc_key_cached_but_read_time_zero,                  104,    FSCK_AUTOFIX)   \
+       x(alloc_key_to_missing_lru_entry,                       105,    FSCK_AUTOFIX)   \
        x(alloc_key_data_type_wrong,                            106,    FSCK_AUTOFIX)   \
        x(alloc_key_gen_wrong,                                  107,    FSCK_AUTOFIX)   \
        x(alloc_key_dirty_sectors_wrong,                        108,    FSCK_AUTOFIX)   \