bcachefs: Fix bch2_dirent_create_snapshot() for casefolding
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 21 May 2025 04:41:07 +0000 (00:41 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 May 2025 00:13:13 +0000 (20:13 -0400)
bch2_dirent_create_snapshot(), used in fsck, neglected to create a
casefolded dirent.

Just move this into dirent_create_key().

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/dirent.c
fs/bcachefs/dirent.h
fs/bcachefs/fsck.c
fs/bcachefs/namei.c

index 8a680e52c1ed12c06f2692c4c220b1f21312cf18..a5119508822789a0a561a110cddc35a3db1ac8d7 100644 (file)
@@ -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)
index 9838a7ba7ed1b5679b968666edcf09684beebc79..d3e7ae669575a6d3cf7e13657b4b1564f4e78cf6 100644 (file)
@@ -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)
index 71d428f376a5f8873cbeb751e2e2aeeb07be3ef6..0cf9fd4c17bc010786641158face412a6acc6437 100644 (file)
@@ -306,6 +306,7 @@ create_lostfound:
                                &lostfound_str,
                                lostfound->bi_inum,
                                &lostfound->bi_dir_offset,
+                               BTREE_UPDATE_internal_snapshot_node|
                                STR_HASH_must_create) ?:
                bch2_inode_write_flags(trans, &lostfound_iter, lostfound,
                                       BTREE_UPDATE_internal_snapshot_node);
@@ -431,6 +432,7 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked *
                                &name,
                                inode->bi_subvol ?: inode->bi_inum,
                                &inode->bi_dir_offset,
+                               BTREE_UPDATE_internal_snapshot_node|
                                STR_HASH_must_create);
        if (ret) {
                bch_err_msg(c, ret, "error creating dirent");
index 52c58c6d53d243e838934d1ef9f7c7c25884d64c..9136a90977893c6f3944f354bda3f230407f1dab 100644 (file)
@@ -158,7 +158,6 @@ int bch2_create_trans(struct btree_trans *trans,
                                           name,
                                           dir_target,
                                           &dir_offset,
-                                          &dir_u->bi_size,
                                           STR_HASH_must_create|BTREE_ITER_with_updates) ?:
                        bch2_inode_write(trans, &dir_iter, dir_u);
                if (ret)
@@ -225,7 +224,6 @@ int bch2_link_trans(struct btree_trans *trans,
                                 mode_to_type(inode_u->bi_mode),
                                 name, inum.inum,
                                 &dir_offset,
-                                &dir_u->bi_size,
                                 STR_HASH_must_create);
        if (ret)
                goto err;