Commit 2bfcee56 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'bcachefs-2025-05-01' of git://evilpiepirate.org/bcachefs

Pull bcachefs fixes from Kent Overstreet:
 "Lots of assorted small fixes...

   - Some repair path fixes, a fix for -ENOMEM when reconstructing lots
     of alloc info on large filesystems, upgrade for ancient 0.14
     filesystems, etc.

   - Various assert tweaks; assert -> ERO, ERO -> log the error in the
     superblock and continue

   - casefolding now uses d_ops like on other casefolding filesystems

   - fix device label create on device add, fix bucket array resize on
     filesystem resize

   - fix xattrs with FORTIFY_SOURCE builds with gcc-15/clang"

* tag 'bcachefs-2025-05-01' of git://evilpiepirate.org/bcachefs: (22 commits)
  bcachefs: Remove incorrect __counted_by annotation
  bcachefs: add missing sched_annotate_sleep()
  bcachefs: Fix __bch2_dev_group_set()
  bcachefs: Kill ERO for i_blocks check in truncate
  bcachefs: check for inode.bi_sectors underflow
  bcachefs: Kill ERO in __bch2_i_sectors_acct()
  bcachefs: readdir fixes
  bcachefs: improve missing journal write device error message
  bcachefs: Topology error after insert is now an ERO
  bcachefs: Use bch2_kvmalloc() for journal keys array
  bcachefs: More informative error message when shutting down due to error
  bcachefs: btree_root_unreadable_and_scan_found_nothing autofix for non data btrees
  bcachefs: btree_node_data_missing is now autofix
  bcachefs: Don't generate alloc updates to invalid buckets
  bcachefs: Improve bch2_dev_bucket_missing()
  bcachefs: fix bch2_dev_buckets_resize()
  bcachefs: Add upgrade table entry from 0.14
  bcachefs: Run BCH_RECOVERY_PASS_reconstruct_snapshots on missing subvol -> snapshot
  bcachefs: Add missing utf8_unload()
  bcachefs: Emit unicode version message on startup
  ...
parents 85951e19 6846100b
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -47,6 +47,27 @@
#define DROP_PREV_NODE		11
#define DID_FILL_FROM_SCAN	12

/*
 * Returns true if it's a btree we can easily reconstruct, or otherwise won't
 * cause data loss if it's missing:
 */
static bool btree_id_important(enum btree_id btree)
{
	if (btree_id_is_alloc(btree))
		return false;

	switch (btree) {
	case BTREE_ID_quotas:
	case BTREE_ID_snapshot_trees:
	case BTREE_ID_logged_ops:
	case BTREE_ID_rebalance_work:
	case BTREE_ID_subvolume_children:
		return false;
	default:
		return true;
	}
}

static const char * const bch2_gc_phase_strs[] = {
#define x(n)	#n,
	GC_PHASES()
@@ -534,7 +555,9 @@ int bch2_check_topology(struct bch_fs *c)
			r->error = 0;

			if (!bch2_btree_has_scanned_nodes(c, i)) {
				mustfix_fsck_err(trans, btree_root_unreadable_and_scan_found_nothing,
				__fsck_err(trans,
					   FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0),
					   btree_root_unreadable_and_scan_found_nothing,
					   "no nodes found for btree %s, continue?", buf.buf);
				bch2_btree_root_alloc_fake_trans(trans, i, 0);
			} else {
+1 −1
Original line number Diff line number Diff line
@@ -288,7 +288,7 @@ int bch2_journal_key_insert_take(struct bch_fs *c, enum btree_id id,
			.size			= max_t(size_t, keys->size, 8) * 2,
		};

		new_keys.data = kvmalloc_array(new_keys.size, sizeof(new_keys.data[0]), GFP_KERNEL);
		new_keys.data = bch2_kvmalloc(new_keys.size * sizeof(new_keys.data[0]), GFP_KERNEL);
		if (!new_keys.data) {
			bch_err(c, "%s: error allocating new key array (size %zu)",
				__func__, new_keys.size);
+32 −17
Original line number Diff line number Diff line
@@ -1389,7 +1389,7 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as,
	printbuf_exit(&buf);
}

static void
static int
bch2_btree_insert_keys_interior(struct btree_update *as,
				struct btree_trans *trans,
				struct btree_path *path,
@@ -1411,7 +1411,8 @@ bch2_btree_insert_keys_interior(struct btree_update *as,
	     insert = bkey_next(insert))
		bch2_insert_fixup_btree_ptr(as, trans, path, b, &node_iter, insert);

	if (bch2_btree_node_check_topology(trans, b)) {
	int ret = bch2_btree_node_check_topology(trans, b);
	if (ret) {
		struct printbuf buf = PRINTBUF;

		for (struct bkey_i *k = keys->keys;
@@ -1421,11 +1422,15 @@ bch2_btree_insert_keys_interior(struct btree_update *as,
			prt_newline(&buf);
		}

		panic("%s(): check_topology error: inserted keys\n%s", __func__, buf.buf);
		bch2_fs_fatal_error(as->c, "%ps -> %s(): check_topology error %s: inserted keys\n%s",
				    (void *) _RET_IP_, __func__, bch2_err_str(ret), buf.buf);
		dump_stack();
		return ret;
	}

	memmove_u64s_down(keys->keys, insert, keys->top_p - insert->_data);
	keys->top_p -= insert->_data - keys->keys_p;
	return 0;
}

static bool key_deleted_in_insert(struct keylist *insert_keys, struct bpos pos)
@@ -1559,7 +1564,7 @@ static void __btree_split_node(struct btree_update *as,
 * nodes that were coalesced, and thus in the middle of a child node post
 * coalescing:
 */
static void btree_split_insert_keys(struct btree_update *as,
static int btree_split_insert_keys(struct btree_update *as,
				   struct btree_trans *trans,
				   btree_path_idx_t path_idx,
				   struct btree *b,
@@ -1573,8 +1578,12 @@ static void btree_split_insert_keys(struct btree_update *as,

		bch2_btree_node_iter_init(&node_iter, b, &bch2_keylist_front(keys)->k.p);

		bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys);
		int ret = bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys);
		if (ret)
			return ret;
	}

	return 0;
}

static int btree_split(struct btree_update *as, struct btree_trans *trans,
@@ -1607,8 +1616,10 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
		__btree_split_node(as, trans, b, n, keys);

		if (keys) {
			btree_split_insert_keys(as, trans, path, n1, keys);
			ret =   btree_split_insert_keys(as, trans, path, n1, keys) ?:
				btree_split_insert_keys(as, trans, path, n2, keys);
			if (ret)
				goto err;
			BUG_ON(!bch2_keylist_empty(keys));
		}

@@ -1654,7 +1665,9 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
			n3->sib_u64s[0] = U16_MAX;
			n3->sib_u64s[1] = U16_MAX;

			btree_split_insert_keys(as, trans, path, n3, &as->parent_keys);
			ret = btree_split_insert_keys(as, trans, path, n3, &as->parent_keys);
			if (ret)
				goto err;
		}
	} else {
		trace_and_count(c, btree_node_compact, trans, b);
@@ -1662,7 +1675,9 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
		n1 = bch2_btree_node_alloc_replacement(as, trans, b);

		if (keys) {
			btree_split_insert_keys(as, trans, path, n1, keys);
			ret = btree_split_insert_keys(as, trans, path, n1, keys);
			if (ret)
				goto err;
			BUG_ON(!bch2_keylist_empty(keys));
		}

@@ -1809,15 +1824,15 @@ static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *t
		goto split;
	}

	ret = bch2_btree_node_check_topology(trans, b);

	ret =   bch2_btree_node_check_topology(trans, b) ?:
		bch2_btree_insert_keys_interior(as, trans, path, b,
					path->l[b->c.level].iter, keys);
	if (ret) {
		bch2_btree_node_unlock_write(trans, path, b);
		return ret;
	}

	bch2_btree_insert_keys_interior(as, trans, path, b,
					path->l[b->c.level].iter, keys);

	trans_for_each_path_with_node(trans, b, linked, i)
		bch2_btree_node_iter_peek(&linked->l[b->c.level].iter, b);

+10 −5
Original line number Diff line number Diff line
@@ -604,6 +604,13 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
	}

	struct bpos bucket = PTR_BUCKET_POS(ca, &p.ptr);
	if (!bucket_valid(ca, bucket.offset)) {
		if (insert) {
			bch2_dev_bucket_missing(ca, bucket.offset);
			ret = -BCH_ERR_trigger_pointer;
		}
		goto err;
	}

	if (flags & BTREE_TRIGGER_transactional) {
		struct bkey_i_alloc_v4 *a = bch2_trans_start_alloc_update(trans, bucket, 0);
@@ -1307,13 +1314,11 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
	old_bucket_gens = rcu_dereference_protected(ca->bucket_gens, 1);

	if (resize) {
		bucket_gens->nbuckets = min(bucket_gens->nbuckets,
		u64 copy = min(bucket_gens->nbuckets,
			       old_bucket_gens->nbuckets);
		bucket_gens->nbuckets_minus_first =
			bucket_gens->nbuckets - bucket_gens->first_bucket;
		memcpy(bucket_gens->b,
		       old_bucket_gens->b,
		       bucket_gens->nbuckets);
		       sizeof(bucket_gens->b[0]) * copy);
	}

	rcu_assign_pointer(ca->bucket_gens, bucket_gens);
+2 −2
Original line number Diff line number Diff line
@@ -685,7 +685,7 @@ static int bch2_dir_emit(struct dir_context *ctx, struct bkey_s_c_dirent d, subv
		      vfs_d_type(d.v->d_type));
	if (ret)
		ctx->pos = d.k->p.offset + 1;
	return ret;
	return !ret;
}

int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
@@ -710,7 +710,7 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
			if (ret2 > 0)
				continue;

			ret2 ?: drop_locks_do(trans, bch2_dir_emit(ctx, dirent, target));
			ret2 ?: (bch2_trans_unlock(trans), bch2_dir_emit(ctx, dirent, target));
		})));

	bch2_bkey_buf_exit(&sk, c);
Loading