diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2025-05-31 17:00:00 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2025-06-04 16:45:41 -0400 |
commit | b938d3c970175b2f3d22865dc077482fc6137828 (patch) | |
tree | a516ed8790f94507e69da8c7a6c655d37ffbaeee | |
parent | 35c1f131bc5ff9d6fb9599b3ae5a15dd83a27e31 (diff) |
bcachefs: Fix bch2_fsck_rename_dirent() for casefold
bch2_fsck_renamed_dirent was creating bch_dirent keys open-coded - but
we need to use the appropriate helper, if the directory is casefolded.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/fsck.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/str_hash.c | 23 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 11 |
3 files changed, 25 insertions, 13 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index dedb80f71049..4a72dbdcc0e6 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -2184,6 +2184,10 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, *hash_info = bch2_hash_info_init(c, &i->inode); dir->first_this_inode = false; +#ifdef CONFIG_UNICODE + hash_info->cf_encoding = bch2_inode_casefold(c, &i->inode) ? c->cf_encoding : NULL; +#endif + ret = bch2_str_hash_check_key(trans, s, &bch2_dirent_hash_desc, hash_info, iter, k, need_second_pass); if (ret < 0) diff --git a/fs/bcachefs/str_hash.c b/fs/bcachefs/str_hash.c index e6ecc8a549ba..7904bf15717b 100644 --- a/fs/bcachefs/str_hash.c +++ b/fs/bcachefs/str_hash.c @@ -39,7 +39,7 @@ static noinline int fsck_rename_dirent(struct btree_trans *trans, bool *updated_before_k_pos) { struct qstr old_name = bch2_dirent_get_name(old); - struct bkey_i_dirent *new = bch2_trans_kmalloc(trans, bkey_bytes(old.k) + 32); + struct bkey_i_dirent *new = bch2_trans_kmalloc(trans, BKEY_U64s_MAX * sizeof(u64)); int ret = PTR_ERR_OR_ZERO(new); if (ret) return ret; @@ -48,20 +48,27 @@ static noinline int fsck_rename_dirent(struct btree_trans *trans, dirent_copy_target(new, old); new->k.p = old.k->p; + char *renamed_buf = bch2_trans_kmalloc(trans, old_name.len + 20); + ret = PTR_ERR_OR_ZERO(renamed_buf); + if (ret) + return ret; + for (unsigned i = 0; i < 1000; i++) { - unsigned len = sprintf(new->v.d_name, "%.*s.fsck_renamed-%u", - old_name.len, old_name.name, i); - unsigned u64s = BKEY_U64s + dirent_val_u64s(len, 0); + new->k.u64s = BKEY_U64s_MAX; - if (u64s > U8_MAX) - return -EINVAL; + struct qstr renamed_name = (struct qstr) QSTR_INIT(renamed_buf, + sprintf(renamed_buf, "%.*s.fsck_renamed-%u", + old_name.len, old_name.name, i)); - new->k.u64s = u64s; + ret = bch2_dirent_init_name(new, hash_info, &renamed_name, NULL); + if (ret) + return ret; ret = bch2_hash_set_in_snapshot(trans, bch2_dirent_hash_desc, hash_info, (subvol_inum) { 0, old.k->p.inode }, old.k->p.snapshot, &new->k_i, - BTREE_UPDATE_internal_snapshot_node); + BTREE_UPDATE_internal_snapshot_node| + STR_HASH_must_create); if (ret && !bch2_err_matches(ret, EEXIST)) break; if (!ret) { diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 21b1b227f89f..397a69da5a75 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -1148,11 +1148,12 @@ int bch2_fs_start(struct bch_fs *c) print_mount_opts(c); - if (IS_ENABLED(CONFIG_UNICODE)) - bch_info(c, "Using encoding defined by superblock: utf8-%u.%u.%u", - unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING), - unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING), - unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING)); +#ifdef CONFIG_UNICODE + bch_info(c, "Using encoding defined by superblock: utf8-%u.%u.%u", + unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING), + unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING), + unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING)); +#endif if (!bch2_fs_may_start(c)) return bch_err_throw(c, insufficient_devices_to_start); |