bcachefs: Fix ca->oldest_gen allocation
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 20 Oct 2023 16:24:36 +0000 (12:24 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Tue, 31 Oct 2023 16:18:37 +0000 (12:18 -0400)
The ca->oldest_gen array needs to be the same size as the bucket_gens
array; ca->mi.nbuckets is updated with only state_lock held, not
gc_lock, so bch2_gc_gens() could race with device resize and allocate
too small of an oldest_gens array.

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

index 8cfd2edd1b08f3734f1b36c2713e959fc5cc4a06..53d1d1da26400c42490044ca65a8630fc91d1042 100644 (file)
@@ -1954,19 +1954,17 @@ int bch2_gc_gens(struct bch_fs *c)
        trans = bch2_trans_get(c);
 
        for_each_member_device(ca, c, i) {
-               struct bucket_gens *gens;
+               struct bucket_gens *gens = bucket_gens(ca);
 
                BUG_ON(ca->oldest_gen);
 
-               ca->oldest_gen = kvmalloc(ca->mi.nbuckets, GFP_KERNEL);
+               ca->oldest_gen = kvmalloc(gens->nbuckets, GFP_KERNEL);
                if (!ca->oldest_gen) {
                        percpu_ref_put(&ca->ref);
                        ret = -BCH_ERR_ENOMEM_gc_gens;
                        goto err;
                }
 
-               gens = bucket_gens(ca);
-
                for (b = gens->first_bucket;
                     b < gens->nbuckets; b++)
                        ca->oldest_gen[b] = gens->b[b];