]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Fix bch2_fsck_rename_dirent() for casefold
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 31 May 2025 21:00:00 +0000 (17:00 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Wed, 4 Jun 2025 20:45:41 +0000 (16:45 -0400)
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>
fs/bcachefs/fsck.c
fs/bcachefs/str_hash.c
fs/bcachefs/super.c

index dedb80f71049a5e3b7635c282fad470a15482e29..4a72dbdcc0e64cbdeabdf08fbfd0580767c2f0ac 100644 (file)
@@ -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)
index e6ecc8a549ba8ace310b6a76a4f8f0dc225c4f04..7904bf15717bbc5d74c0ec84738bf45e7369fb85 100644 (file)
@@ -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) {
index 21b1b227f89f04d6de4cf4ef779792273bf161b9..397a69da5a7589ca48fa0638fbf6dda65ceba052 100644 (file)
@@ -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);