Skip to content

Commit 7b83601

Browse files
committed
Merge tag 'bcachefs-2024-10-31' of git://evilpiepirate.org/bcachefs
Pull bcachefs fixes from Kent Overstreet: "Various syzbot fixes, and the more notable ones: - Fix for pointers in an extent overflowing the max (16) on a filesystem with many devices: we were creating too many cached copies when moving data around. Now, we only create at most one cached copy if there's a promote target set. Caching will be a bit broken for reflinked data until 6.13: I have larger series queued up which significantly improves the plumbing for data options down into the extent (bch_extent_rebalance) to fix this. - Fix for deadlock on -ENOSPC on tiny filesystems Allocation from the partial open_bucket list wasn't correctly accounting partial open_buckets as free: this fixes the main cause of tests timing out in the automated tests" * tag 'bcachefs-2024-10-31' of git://evilpiepirate.org/bcachefs: bcachefs: Fix NULL ptr dereference in btree_node_iter_and_journal_peek bcachefs: fix possible null-ptr-deref in __bch2_ec_stripe_head_get() bcachefs: Fix deadlock on -ENOSPC w.r.t. partial open buckets bcachefs: Don't filter partial list buckets in open_buckets_to_text() bcachefs: Don't keep tons of cached pointers around bcachefs: init freespace inited bits to 0 in bch2_fs_initialize bcachefs: Fix unhandled transaction restart in fallocate bcachefs: Fix UAF in bch2_reconstruct_alloc() bcachefs: fix null-ptr-deref in have_stripes() bcachefs: fix shift oob in alloc_lru_idx_fragmentation bcachefs: Fix invalid shift in validate_sb_layout()
2 parents 6c52d4d + 3726a19 commit 7b83601

15 files changed

+160
-38
lines changed

fs/bcachefs/alloc_background.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ static inline bool data_type_movable(enum bch_data_type type)
168168
static inline u64 alloc_lru_idx_fragmentation(struct bch_alloc_v4 a,
169169
struct bch_dev *ca)
170170
{
171+
if (a.data_type >= BCH_DATA_NR)
172+
return 0;
173+
171174
if (!data_type_movable(a.data_type) ||
172175
!bch2_bucket_sectors_fragmented(ca, a))
173176
return 0;

fs/bcachefs/alloc_foreground.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ static void open_bucket_free_unused(struct bch_fs *c, struct open_bucket *ob)
162162
ARRAY_SIZE(c->open_buckets_partial));
163163

164164
spin_lock(&c->freelist_lock);
165+
rcu_read_lock();
166+
bch2_dev_rcu(c, ob->dev)->nr_partial_buckets++;
167+
rcu_read_unlock();
168+
165169
ob->on_partial_list = true;
166170
c->open_buckets_partial[c->open_buckets_partial_nr++] =
167171
ob - c->open_buckets;
@@ -972,7 +976,7 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
972976
u64 avail;
973977

974978
bch2_dev_usage_read_fast(ca, &usage);
975-
avail = dev_buckets_free(ca, usage, watermark);
979+
avail = dev_buckets_free(ca, usage, watermark) + ca->nr_partial_buckets;
976980
if (!avail)
977981
continue;
978982

@@ -981,6 +985,10 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
981985
i);
982986
ob->on_partial_list = false;
983987

988+
rcu_read_lock();
989+
bch2_dev_rcu(c, ob->dev)->nr_partial_buckets--;
990+
rcu_read_unlock();
991+
984992
ret = add_new_bucket(c, ptrs, devs_may_alloc,
985993
nr_replicas, nr_effective,
986994
have_cache, ob);
@@ -1191,7 +1199,13 @@ void bch2_open_buckets_stop(struct bch_fs *c, struct bch_dev *ca,
11911199
--c->open_buckets_partial_nr;
11921200
swap(c->open_buckets_partial[i],
11931201
c->open_buckets_partial[c->open_buckets_partial_nr]);
1202+
11941203
ob->on_partial_list = false;
1204+
1205+
rcu_read_lock();
1206+
bch2_dev_rcu(c, ob->dev)->nr_partial_buckets--;
1207+
rcu_read_unlock();
1208+
11951209
spin_unlock(&c->freelist_lock);
11961210
bch2_open_bucket_put(c, ob);
11971211
spin_lock(&c->freelist_lock);
@@ -1610,8 +1624,7 @@ void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c,
16101624
ob < c->open_buckets + ARRAY_SIZE(c->open_buckets);
16111625
ob++) {
16121626
spin_lock(&ob->lock);
1613-
if (ob->valid && !ob->on_partial_list &&
1614-
(!ca || ob->dev == ca->dev_idx))
1627+
if (ob->valid && (!ca || ob->dev == ca->dev_idx))
16151628
bch2_open_bucket_to_text(out, c, ob);
16161629
spin_unlock(&ob->lock);
16171630
}

fs/bcachefs/bcachefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ struct bch_dev {
555555
u64 alloc_cursor[3];
556556

557557
unsigned nr_open_buckets;
558+
unsigned nr_partial_buckets;
558559
unsigned nr_btree_reserve;
559560

560561
size_t inc_gen_needs_gc;

fs/bcachefs/btree_iter.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,13 +882,26 @@ static noinline int btree_node_iter_and_journal_peek(struct btree_trans *trans,
882882
__bch2_btree_and_journal_iter_init_node_iter(trans, &jiter, l->b, l->iter, path->pos);
883883

884884
k = bch2_btree_and_journal_iter_peek(&jiter);
885+
if (!k.k) {
886+
struct printbuf buf = PRINTBUF;
887+
888+
prt_str(&buf, "node not found at pos ");
889+
bch2_bpos_to_text(&buf, path->pos);
890+
prt_str(&buf, " at btree ");
891+
bch2_btree_pos_to_text(&buf, c, l->b);
892+
893+
ret = bch2_fs_topology_error(c, "%s", buf.buf);
894+
printbuf_exit(&buf);
895+
goto err;
896+
}
885897

886898
bch2_bkey_buf_reassemble(out, c, k);
887899

888900
if ((flags & BTREE_ITER_prefetch) &&
889901
c->opts.btree_node_prefetch)
890902
ret = btree_path_prefetch_j(trans, path, &jiter);
891903

904+
err:
892905
bch2_btree_and_journal_iter_exit(&jiter);
893906
return ret;
894907
}

fs/bcachefs/data_update.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ static int __bch2_data_update_index_update(struct btree_trans *trans,
236236
if (((1U << i) & m->data_opts.rewrite_ptrs) &&
237237
(ptr = bch2_extent_has_ptr(old, p, bkey_i_to_s(insert))) &&
238238
!ptr->cached) {
239-
bch2_extent_ptr_set_cached(bkey_i_to_s(insert), ptr);
239+
bch2_extent_ptr_set_cached(c, &m->op.opts,
240+
bkey_i_to_s(insert), ptr);
240241
rewrites_found |= 1U << i;
241242
}
242243
i++;
@@ -284,7 +285,8 @@ static int __bch2_data_update_index_update(struct btree_trans *trans,
284285
durability - ptr_durability >= m->op.opts.data_replicas) {
285286
durability -= ptr_durability;
286287

287-
bch2_extent_ptr_set_cached(bkey_i_to_s(insert), &entry->ptr);
288+
bch2_extent_ptr_set_cached(c, &m->op.opts,
289+
bkey_i_to_s(insert), &entry->ptr);
288290
goto restart_drop_extra_replicas;
289291
}
290292
}
@@ -295,7 +297,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans,
295297
bch2_extent_ptr_decoded_append(insert, &p);
296298

297299
bch2_bkey_narrow_crcs(insert, (struct bch_extent_crc_unpacked) { 0 });
298-
bch2_extent_normalize(c, bkey_i_to_s(insert));
300+
bch2_extent_normalize_by_opts(c, &m->op.opts, bkey_i_to_s(insert));
299301

300302
ret = bch2_sum_sector_overwrites(trans, &iter, insert,
301303
&should_check_enospc,
@@ -558,7 +560,8 @@ void bch2_data_update_to_text(struct printbuf *out, struct data_update *m)
558560
int bch2_extent_drop_ptrs(struct btree_trans *trans,
559561
struct btree_iter *iter,
560562
struct bkey_s_c k,
561-
struct data_update_opts data_opts)
563+
struct bch_io_opts *io_opts,
564+
struct data_update_opts *data_opts)
562565
{
563566
struct bch_fs *c = trans->c;
564567
struct bkey_i *n;
@@ -569,19 +572,19 @@ int bch2_extent_drop_ptrs(struct btree_trans *trans,
569572
if (ret)
570573
return ret;
571574

572-
while (data_opts.kill_ptrs) {
573-
unsigned i = 0, drop = __fls(data_opts.kill_ptrs);
575+
while (data_opts->kill_ptrs) {
576+
unsigned i = 0, drop = __fls(data_opts->kill_ptrs);
574577

575578
bch2_bkey_drop_ptrs_noerror(bkey_i_to_s(n), ptr, i++ == drop);
576-
data_opts.kill_ptrs ^= 1U << drop;
579+
data_opts->kill_ptrs ^= 1U << drop;
577580
}
578581

579582
/*
580583
* If the new extent no longer has any pointers, bch2_extent_normalize()
581584
* will do the appropriate thing with it (turning it into a
582585
* KEY_TYPE_error key, or just a discard if it was a cached extent)
583586
*/
584-
bch2_extent_normalize(c, bkey_i_to_s(n));
587+
bch2_extent_normalize_by_opts(c, io_opts, bkey_i_to_s(n));
585588

586589
/*
587590
* Since we're not inserting through an extent iterator
@@ -720,7 +723,7 @@ int bch2_data_update_init(struct btree_trans *trans,
720723
m->data_opts.rewrite_ptrs = 0;
721724
/* if iter == NULL, it's just a promote */
722725
if (iter)
723-
ret = bch2_extent_drop_ptrs(trans, iter, k, m->data_opts);
726+
ret = bch2_extent_drop_ptrs(trans, iter, k, &io_opts, &m->data_opts);
724727
goto out;
725728
}
726729

fs/bcachefs/data_update.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ void bch2_data_update_read_done(struct data_update *,
4040
int bch2_extent_drop_ptrs(struct btree_trans *,
4141
struct btree_iter *,
4242
struct bkey_s_c,
43-
struct data_update_opts);
43+
struct bch_io_opts *,
44+
struct data_update_opts *);
4445

4546
void bch2_data_update_exit(struct data_update *);
4647
int bch2_data_update_init(struct btree_trans *, struct btree_iter *,

fs/bcachefs/ec.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,10 @@ __bch2_ec_stripe_head_get(struct btree_trans *trans,
18701870
}
18711871

18721872
h = ec_new_stripe_head_alloc(c, disk_label, algo, redundancy, watermark);
1873+
if (!h) {
1874+
h = ERR_PTR(-BCH_ERR_ENOMEM_stripe_head_alloc);
1875+
goto err;
1876+
}
18731877
found:
18741878
if (h->rw_devs_change_count != c->rw_devs_change_count)
18751879
ec_stripe_head_devs_update(c, h);

fs/bcachefs/errcode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
x(ENOMEM, ENOMEM_fs_other_alloc) \
8484
x(ENOMEM, ENOMEM_dev_alloc) \
8585
x(ENOMEM, ENOMEM_disk_accounting) \
86+
x(ENOMEM, ENOMEM_stripe_head_alloc) \
8687
x(ENOSPC, ENOSPC_disk_reservation) \
8788
x(ENOSPC, ENOSPC_bucket_alloc) \
8889
x(ENOSPC, ENOSPC_disk_label_add) \
@@ -222,6 +223,7 @@
222223
x(BCH_ERR_invalid_sb_layout, invalid_sb_layout_type) \
223224
x(BCH_ERR_invalid_sb_layout, invalid_sb_layout_nr_superblocks) \
224225
x(BCH_ERR_invalid_sb_layout, invalid_sb_layout_superblocks_overlap) \
226+
x(BCH_ERR_invalid_sb_layout, invalid_sb_layout_sb_max_size_bits) \
225227
x(BCH_ERR_invalid_sb, invalid_sb_members_missing) \
226228
x(BCH_ERR_invalid_sb, invalid_sb_members) \
227229
x(BCH_ERR_invalid_sb, invalid_sb_disk_groups) \

fs/bcachefs/extents.c

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -978,31 +978,54 @@ bch2_extent_has_ptr(struct bkey_s_c k1, struct extent_ptr_decoded p1, struct bke
978978
return NULL;
979979
}
980980

981-
void bch2_extent_ptr_set_cached(struct bkey_s k, struct bch_extent_ptr *ptr)
981+
static bool want_cached_ptr(struct bch_fs *c, struct bch_io_opts *opts,
982+
struct bch_extent_ptr *ptr)
983+
{
984+
if (!opts->promote_target ||
985+
!bch2_dev_in_target(c, ptr->dev, opts->promote_target))
986+
return false;
987+
988+
struct bch_dev *ca = bch2_dev_rcu_noerror(c, ptr->dev);
989+
990+
return ca && bch2_dev_is_readable(ca) && !dev_ptr_stale_rcu(ca, ptr);
991+
}
992+
993+
void bch2_extent_ptr_set_cached(struct bch_fs *c,
994+
struct bch_io_opts *opts,
995+
struct bkey_s k,
996+
struct bch_extent_ptr *ptr)
982997
{
983998
struct bkey_ptrs ptrs = bch2_bkey_ptrs(k);
984999
union bch_extent_entry *entry;
985-
union bch_extent_entry *ec = NULL;
1000+
struct extent_ptr_decoded p;
9861001

987-
bkey_extent_entry_for_each(ptrs, entry) {
1002+
rcu_read_lock();
1003+
if (!want_cached_ptr(c, opts, ptr)) {
1004+
bch2_bkey_drop_ptr_noerror(k, ptr);
1005+
goto out;
1006+
}
1007+
1008+
/*
1009+
* Stripes can't contain cached data, for - reasons.
1010+
*
1011+
* Possibly something we can fix in the future?
1012+
*/
1013+
bkey_for_each_ptr_decode(k.k, ptrs, p, entry)
9881014
if (&entry->ptr == ptr) {
989-
ptr->cached = true;
990-
if (ec)
991-
extent_entry_drop(k, ec);
992-
return;
1015+
if (p.has_ec)
1016+
bch2_bkey_drop_ptr_noerror(k, ptr);
1017+
else
1018+
ptr->cached = true;
1019+
goto out;
9931020
}
9941021

995-
if (extent_entry_is_stripe_ptr(entry))
996-
ec = entry;
997-
else if (extent_entry_is_ptr(entry))
998-
ec = NULL;
999-
}
1000-
10011022
BUG();
1023+
out:
1024+
rcu_read_unlock();
10021025
}
10031026

10041027
/*
1005-
* bch_extent_normalize - clean up an extent, dropping stale pointers etc.
1028+
* bch2_extent_normalize - clean up an extent, dropping stale pointers etc.
10061029
*
10071030
* Returns true if @k should be dropped entirely
10081031
*
@@ -1016,8 +1039,39 @@ bool bch2_extent_normalize(struct bch_fs *c, struct bkey_s k)
10161039
rcu_read_lock();
10171040
bch2_bkey_drop_ptrs(k, ptr,
10181041
ptr->cached &&
1019-
(ca = bch2_dev_rcu(c, ptr->dev)) &&
1020-
dev_ptr_stale_rcu(ca, ptr) > 0);
1042+
(!(ca = bch2_dev_rcu(c, ptr->dev)) ||
1043+
dev_ptr_stale_rcu(ca, ptr) > 0));
1044+
rcu_read_unlock();
1045+
1046+
return bkey_deleted(k.k);
1047+
}
1048+
1049+
/*
1050+
* bch2_extent_normalize_by_opts - clean up an extent, dropping stale pointers etc.
1051+
*
1052+
* Like bch2_extent_normalize(), but also only keeps a single cached pointer on
1053+
* the promote target.
1054+
*/
1055+
bool bch2_extent_normalize_by_opts(struct bch_fs *c,
1056+
struct bch_io_opts *opts,
1057+
struct bkey_s k)
1058+
{
1059+
struct bkey_ptrs ptrs;
1060+
bool have_cached_ptr;
1061+
1062+
rcu_read_lock();
1063+
restart_drop_ptrs:
1064+
ptrs = bch2_bkey_ptrs(k);
1065+
have_cached_ptr = false;
1066+
1067+
bkey_for_each_ptr(ptrs, ptr)
1068+
if (ptr->cached) {
1069+
if (have_cached_ptr || !want_cached_ptr(c, opts, ptr)) {
1070+
bch2_bkey_drop_ptr(k, ptr);
1071+
goto restart_drop_ptrs;
1072+
}
1073+
have_cached_ptr = true;
1074+
}
10211075
rcu_read_unlock();
10221076

10231077
return bkey_deleted(k.k);

fs/bcachefs/extents.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,9 +686,12 @@ bool bch2_extents_match(struct bkey_s_c, struct bkey_s_c);
686686
struct bch_extent_ptr *
687687
bch2_extent_has_ptr(struct bkey_s_c, struct extent_ptr_decoded, struct bkey_s);
688688

689-
void bch2_extent_ptr_set_cached(struct bkey_s, struct bch_extent_ptr *);
689+
void bch2_extent_ptr_set_cached(struct bch_fs *, struct bch_io_opts *,
690+
struct bkey_s, struct bch_extent_ptr *);
690691

692+
bool bch2_extent_normalize_by_opts(struct bch_fs *, struct bch_io_opts *, struct bkey_s);
691693
bool bch2_extent_normalize(struct bch_fs *, struct bkey_s);
694+
692695
void bch2_extent_ptr_to_text(struct printbuf *out, struct bch_fs *, const struct bch_extent_ptr *);
693696
void bch2_bkey_ptrs_to_text(struct printbuf *, struct bch_fs *,
694697
struct bkey_s_c);

0 commit comments

Comments
 (0)