Commit 7b83601d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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()
parents 6c52d4da 3726a197
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -168,6 +168,9 @@ static inline bool data_type_movable(enum bch_data_type type)
static inline u64 alloc_lru_idx_fragmentation(struct bch_alloc_v4 a,
					      struct bch_dev *ca)
{
	if (a.data_type >= BCH_DATA_NR)
		return 0;

	if (!data_type_movable(a.data_type) ||
	    !bch2_bucket_sectors_fragmented(ca, a))
		return 0;
+16 −3
Original line number Diff line number Diff line
@@ -162,6 +162,10 @@ static void open_bucket_free_unused(struct bch_fs *c, struct open_bucket *ob)
	       ARRAY_SIZE(c->open_buckets_partial));

	spin_lock(&c->freelist_lock);
	rcu_read_lock();
	bch2_dev_rcu(c, ob->dev)->nr_partial_buckets++;
	rcu_read_unlock();

	ob->on_partial_list = true;
	c->open_buckets_partial[c->open_buckets_partial_nr++] =
		ob - c->open_buckets;
@@ -972,7 +976,7 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
			u64 avail;

			bch2_dev_usage_read_fast(ca, &usage);
			avail = dev_buckets_free(ca, usage, watermark);
			avail = dev_buckets_free(ca, usage, watermark) + ca->nr_partial_buckets;
			if (!avail)
				continue;

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

			rcu_read_lock();
			bch2_dev_rcu(c, ob->dev)->nr_partial_buckets--;
			rcu_read_unlock();

			ret = add_new_bucket(c, ptrs, devs_may_alloc,
					     nr_replicas, nr_effective,
					     have_cache, ob);
@@ -1191,7 +1199,13 @@ void bch2_open_buckets_stop(struct bch_fs *c, struct bch_dev *ca,
			--c->open_buckets_partial_nr;
			swap(c->open_buckets_partial[i],
			     c->open_buckets_partial[c->open_buckets_partial_nr]);

			ob->on_partial_list = false;

			rcu_read_lock();
			bch2_dev_rcu(c, ob->dev)->nr_partial_buckets--;
			rcu_read_unlock();

			spin_unlock(&c->freelist_lock);
			bch2_open_bucket_put(c, ob);
			spin_lock(&c->freelist_lock);
@@ -1610,8 +1624,7 @@ void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c,
	     ob < c->open_buckets + ARRAY_SIZE(c->open_buckets);
	     ob++) {
		spin_lock(&ob->lock);
		if (ob->valid && !ob->on_partial_list &&
		    (!ca || ob->dev == ca->dev_idx))
		if (ob->valid && (!ca || ob->dev == ca->dev_idx))
			bch2_open_bucket_to_text(out, c, ob);
		spin_unlock(&ob->lock);
	}
+1 −0
Original line number Diff line number Diff line
@@ -555,6 +555,7 @@ struct bch_dev {
	u64			alloc_cursor[3];

	unsigned		nr_open_buckets;
	unsigned		nr_partial_buckets;
	unsigned		nr_btree_reserve;

	size_t			inc_gen_needs_gc;
+13 −0
Original line number Diff line number Diff line
@@ -882,6 +882,18 @@ static noinline int btree_node_iter_and_journal_peek(struct btree_trans *trans,
	__bch2_btree_and_journal_iter_init_node_iter(trans, &jiter, l->b, l->iter, path->pos);

	k = bch2_btree_and_journal_iter_peek(&jiter);
	if (!k.k) {
		struct printbuf buf = PRINTBUF;

		prt_str(&buf, "node not found at pos ");
		bch2_bpos_to_text(&buf, path->pos);
		prt_str(&buf, " at btree ");
		bch2_btree_pos_to_text(&buf, c, l->b);

		ret = bch2_fs_topology_error(c, "%s", buf.buf);
		printbuf_exit(&buf);
		goto err;
	}

	bch2_bkey_buf_reassemble(out, c, k);

@@ -889,6 +901,7 @@ static noinline int btree_node_iter_and_journal_peek(struct btree_trans *trans,
	    c->opts.btree_node_prefetch)
		ret = btree_path_prefetch_j(trans, path, &jiter);

err:
	bch2_btree_and_journal_iter_exit(&jiter);
	return ret;
}
+12 −9
Original line number Diff line number Diff line
@@ -236,7 +236,8 @@ static int __bch2_data_update_index_update(struct btree_trans *trans,
			if (((1U << i) & m->data_opts.rewrite_ptrs) &&
			    (ptr = bch2_extent_has_ptr(old, p, bkey_i_to_s(insert))) &&
			    !ptr->cached) {
				bch2_extent_ptr_set_cached(bkey_i_to_s(insert), ptr);
				bch2_extent_ptr_set_cached(c, &m->op.opts,
							   bkey_i_to_s(insert), ptr);
				rewrites_found |= 1U << i;
			}
			i++;
@@ -284,7 +285,8 @@ static int __bch2_data_update_index_update(struct btree_trans *trans,
			    durability - ptr_durability >= m->op.opts.data_replicas) {
				durability -= ptr_durability;

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

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

		ret = bch2_sum_sector_overwrites(trans, &iter, insert,
						 &should_check_enospc,
@@ -558,7 +560,8 @@ void bch2_data_update_to_text(struct printbuf *out, struct data_update *m)
int bch2_extent_drop_ptrs(struct btree_trans *trans,
			  struct btree_iter *iter,
			  struct bkey_s_c k,
			  struct data_update_opts data_opts)
			  struct bch_io_opts *io_opts,
			  struct data_update_opts *data_opts)
{
	struct bch_fs *c = trans->c;
	struct bkey_i *n;
@@ -569,11 +572,11 @@ int bch2_extent_drop_ptrs(struct btree_trans *trans,
	if (ret)
		return ret;

	while (data_opts.kill_ptrs) {
		unsigned i = 0, drop = __fls(data_opts.kill_ptrs);
	while (data_opts->kill_ptrs) {
		unsigned i = 0, drop = __fls(data_opts->kill_ptrs);

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

	/*
@@ -581,7 +584,7 @@ int bch2_extent_drop_ptrs(struct btree_trans *trans,
	 * will do the appropriate thing with it (turning it into a
	 * KEY_TYPE_error key, or just a discard if it was a cached extent)
	 */
	bch2_extent_normalize(c, bkey_i_to_s(n));
	bch2_extent_normalize_by_opts(c, io_opts, bkey_i_to_s(n));

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

Loading