Commit 040c0f6a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull bcachefs fixes from Kent Overstreet:
 "Small stuff, main ones users will be interested in:

   - Couple more casefolding fixes; we can now detect and repair
     casefolded dirents in non-casefolded dir and vice versa

   - Fix for massive write inflation with mmapped io, which hit certain
     databases"

* tag 'bcachefs-2025-05-22' of git://evilpiepirate.org/bcachefs:
  bcachefs: Check for casefolded dirents in non casefolded dirs
  bcachefs: Fix bch2_dirent_create_snapshot() for casefolding
  bcachefs: Fix casefold opt via xattr interface
  bcachefs: mkwrite() now only dirties one page
  bcachefs: fix extent_has_stripe_ptr()
  bcachefs: Fix bch2_btree_path_traverse_cached() when paths realloced
parents 94305e83 010c8946
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1162,7 +1162,7 @@ int bch2_btree_path_traverse_one(struct btree_trans *trans,
	}

	if (path->cached) {
		ret = bch2_btree_path_traverse_cached(trans, path, flags);
		ret = bch2_btree_path_traverse_cached(trans, path_idx, flags);
		goto out;
	}

+17 −8
Original line number Diff line number Diff line
@@ -301,9 +301,11 @@ static noinline_for_stack void do_trace_key_cache_fill(struct btree_trans *trans
}

static noinline int btree_key_cache_fill(struct btree_trans *trans,
					 struct btree_path *ck_path,
					 btree_path_idx_t ck_path_idx,
					 unsigned flags)
{
	struct btree_path *ck_path = trans->paths + ck_path_idx;

	if (flags & BTREE_ITER_cached_nofill) {
		ck_path->l[0].b = NULL;
		return 0;
@@ -325,6 +327,7 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans,
		goto err;

	/* Recheck after btree lookup, before allocating: */
	ck_path = trans->paths + ck_path_idx;
	ret = bch2_btree_key_cache_find(c, ck_path->btree_id, ck_path->pos) ? -EEXIST : 0;
	if (unlikely(ret))
		goto out;
@@ -344,10 +347,11 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans,
}

static inline int btree_path_traverse_cached_fast(struct btree_trans *trans,
						  struct btree_path *path)
						  btree_path_idx_t path_idx)
{
	struct bch_fs *c = trans->c;
	struct bkey_cached *ck;
	struct btree_path *path = trans->paths + path_idx;
retry:
	ck = bch2_btree_key_cache_find(c, path->btree_id, path->pos);
	if (!ck)
@@ -373,27 +377,32 @@ static inline int btree_path_traverse_cached_fast(struct btree_trans *trans,
	return 0;
}

int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path *path,
int bch2_btree_path_traverse_cached(struct btree_trans *trans,
				    btree_path_idx_t path_idx,
				    unsigned flags)
{
	EBUG_ON(path->level);

	path->l[1].b = NULL;
	EBUG_ON(trans->paths[path_idx].level);

	int ret;
	do {
		ret = btree_path_traverse_cached_fast(trans, path);
		ret = btree_path_traverse_cached_fast(trans, path_idx);
		if (unlikely(ret == -ENOENT))
			ret = btree_key_cache_fill(trans, path, flags);
			ret = btree_key_cache_fill(trans, path_idx, flags);
	} while (ret == -EEXIST);

	struct btree_path *path = trans->paths + path_idx;

	if (unlikely(ret)) {
		path->uptodate = BTREE_ITER_NEED_TRAVERSE;
		if (!bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
			btree_node_unlock(trans, path, 0);
			path->l[0].b = ERR_PTR(ret);
		}
	} else {
		BUG_ON(path->uptodate);
		BUG_ON(!path->nodes_locked);
	}

	return ret;
}

+1 −2
Original line number Diff line number Diff line
@@ -40,8 +40,7 @@ int bch2_btree_key_cache_journal_flush(struct journal *,
struct bkey_cached *
bch2_btree_key_cache_find(struct bch_fs *, enum btree_id, struct bpos);

int bch2_btree_path_traverse_cached(struct btree_trans *, struct btree_path *,
				    unsigned);
int bch2_btree_path_traverse_cached(struct btree_trans *, btree_path_idx_t, unsigned);

bool bch2_btree_insert_key_cached(struct btree_trans *, unsigned,
			struct btree_insert_entry *);
+15 −18
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ static void dirent_init_casefolded_name(struct bkey_i_dirent *dirent,
}

static struct bkey_i_dirent *dirent_create_key(struct btree_trans *trans,
				const struct bch_hash_info *hash_info,
				subvol_inum dir,
				u8 type,
				const struct qstr *name,
@@ -295,10 +296,19 @@ static struct bkey_i_dirent *dirent_create_key(struct btree_trans *trans,
				u64 dst)
{
	struct bkey_i_dirent *dirent;
	struct qstr _cf_name;

	if (name->len > BCH_NAME_MAX)
		return ERR_PTR(-ENAMETOOLONG);

	if (hash_info->cf_encoding && !cf_name) {
		int ret = bch2_casefold(trans, hash_info, name, &_cf_name);
		if (ret)
			return ERR_PTR(ret);

		cf_name = &_cf_name;
	}

	dirent = dirent_alloc_key(trans, dir, type, name->len, cf_name ? cf_name->len : 0, dst);
	if (IS_ERR(dirent))
		return dirent;
@@ -324,7 +334,7 @@ int bch2_dirent_create_snapshot(struct btree_trans *trans,
	struct bkey_i_dirent *dirent;
	int ret;

	dirent = dirent_create_key(trans, dir_inum, type, name, NULL, dst_inum);
	dirent = dirent_create_key(trans, hash_info, dir_inum, type, name, NULL, dst_inum);
	ret = PTR_ERR_OR_ZERO(dirent);
	if (ret)
		return ret;
@@ -333,8 +343,7 @@ int bch2_dirent_create_snapshot(struct btree_trans *trans,
	dirent->k.p.snapshot	= snapshot;

	ret = bch2_hash_set_in_snapshot(trans, bch2_dirent_hash_desc, hash_info,
					dir_inum, snapshot, &dirent->k_i,
					flags|BTREE_UPDATE_internal_snapshot_node);
					dir_inum, snapshot, &dirent->k_i, flags);
	*dir_offset = dirent->k.p.offset;

	return ret;
@@ -344,28 +353,16 @@ int bch2_dirent_create(struct btree_trans *trans, subvol_inum dir,
		       const struct bch_hash_info *hash_info,
		       u8 type, const struct qstr *name, u64 dst_inum,
		       u64 *dir_offset,
		       u64 *i_size,
		       enum btree_iter_update_trigger_flags flags)
{
	struct bkey_i_dirent *dirent;
	int ret;

	if (hash_info->cf_encoding) {
		struct qstr cf_name;
		ret = bch2_casefold(trans, hash_info, name, &cf_name);
		if (ret)
			return ret;
		dirent = dirent_create_key(trans, dir, type, name, &cf_name, dst_inum);
	} else {
		dirent = dirent_create_key(trans, dir, type, name, NULL, dst_inum);
	}

	dirent = dirent_create_key(trans, hash_info, dir, type, name, NULL, dst_inum);
	ret = PTR_ERR_OR_ZERO(dirent);
	if (ret)
		return ret;

	*i_size += bkey_bytes(&dirent->k);

	ret = bch2_hash_set(trans, bch2_dirent_hash_desc, hash_info,
			    dir, &dirent->k_i, flags);
	*dir_offset = dirent->k.p.offset;
@@ -466,7 +463,7 @@ int bch2_dirent_rename(struct btree_trans *trans,
		*src_offset = dst_iter.pos.offset;

	/* Create new dst key: */
	new_dst = dirent_create_key(trans, dst_dir, 0, dst_name,
	new_dst = dirent_create_key(trans, dst_hash, dst_dir, 0, dst_name,
				    dst_hash->cf_encoding ? &dst_name_lookup : NULL, 0);
	ret = PTR_ERR_OR_ZERO(new_dst);
	if (ret)
@@ -477,7 +474,7 @@ int bch2_dirent_rename(struct btree_trans *trans,

	/* Create new src key: */
	if (mode == BCH_RENAME_EXCHANGE) {
		new_src = dirent_create_key(trans, src_dir, 0, src_name,
		new_src = dirent_create_key(trans, src_hash, src_dir, 0, src_name,
					    src_hash->cf_encoding ? &src_name_lookup : NULL, 0);
		ret = PTR_ERR_OR_ZERO(new_src);
		if (ret)
+1 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ int bch2_dirent_create_snapshot(struct btree_trans *, u32, u64, u32,
			enum btree_iter_update_trigger_flags);
int bch2_dirent_create(struct btree_trans *, subvol_inum,
		       const struct bch_hash_info *, u8,
		       const struct qstr *, u64, u64 *, u64 *,
		       const struct qstr *, u64, u64 *,
		       enum btree_iter_update_trigger_flags);

static inline unsigned vfs_d_type(unsigned type)
Loading