bcachefs: Fix casefold opt via xattr interface
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 21 May 2025 00:05:45 +0000 (20:05 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 May 2025 00:13:09 +0000 (20:13 -0400)
Changing the casefold option requires extra checks/work - factor out a
helper from bch2_fileattr_set() for the xattr code to use.

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

index 4b742e62255bb788229c61378082abeaf0d57a6d..47f1a64c5c8d838b1415293ce604a2ac2498336a 100644 (file)
@@ -1664,33 +1664,9 @@ static int fssetxattr_inode_update_fn(struct btree_trans *trans,
                return -EINVAL;
 
        if (s->casefold != bch2_inode_casefold(c, bi)) {
-#ifdef CONFIG_UNICODE
-               int ret = 0;
-               /* Not supported on individual files. */
-               if (!S_ISDIR(bi->bi_mode))
-                       return -EOPNOTSUPP;
-
-               /*
-                * Make sure the dir is empty, as otherwise we'd need to
-                * rehash everything and update the dirent keys.
-                */
-               ret = bch2_empty_dir_trans(trans, inode_inum(inode));
-               if (ret < 0)
-                       return ret;
-
-               ret = bch2_request_incompat_feature(c, bcachefs_metadata_version_casefolding);
+               int ret = bch2_inode_set_casefold(trans, inode_inum(inode), bi, s->casefold);
                if (ret)
                        return ret;
-
-               bch2_check_set_feature(c, BCH_FEATURE_casefolding);
-
-               bi->bi_casefold = s->casefold + 1;
-               bi->bi_fields_set |= BIT(Inode_opt_casefold);
-
-#else
-               printk(KERN_ERR "Cannot use casefolding on a kernel without CONFIG_UNICODE\n");
-               return -EOPNOTSUPP;
-#endif
        }
 
        if (s->set_project) {
index b51d98cf8a80d584c3fe620dbfc73b855bcbd42b..490b85841de96083a500a2981976197501a46dc1 100644 (file)
@@ -14,6 +14,7 @@
 #include "extent_update.h"
 #include "fs.h"
 #include "inode.h"
+#include "namei.h"
 #include "opts.h"
 #include "str_hash.h"
 #include "snapshot.h"
@@ -1204,6 +1205,41 @@ int bch2_inum_opts_get(struct btree_trans *trans, subvol_inum inum, struct bch_i
        return 0;
 }
 
+int bch2_inode_set_casefold(struct btree_trans *trans, subvol_inum inum,
+                           struct bch_inode_unpacked *bi, unsigned v)
+{
+       struct bch_fs *c = trans->c;
+
+#ifdef CONFIG_UNICODE
+       int ret = 0;
+       /* Not supported on individual files. */
+       if (!S_ISDIR(bi->bi_mode))
+               return -EOPNOTSUPP;
+
+       /*
+        * Make sure the dir is empty, as otherwise we'd need to
+        * rehash everything and update the dirent keys.
+        */
+       ret = bch2_empty_dir_trans(trans, inum);
+       if (ret < 0)
+               return ret;
+
+       ret = bch2_request_incompat_feature(c, bcachefs_metadata_version_casefolding);
+       if (ret)
+               return ret;
+
+       bch2_check_set_feature(c, BCH_FEATURE_casefolding);
+
+       bi->bi_casefold = v + 1;
+       bi->bi_fields_set |= BIT(Inode_opt_casefold);
+
+       return 0;
+#else
+       bch_err(c, "Cannot use casefolding on a kernel without CONFIG_UNICODE");
+       return -EOPNOTSUPP;
+#endif
+}
+
 static noinline int __bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot)
 {
        struct bch_fs *c = trans->c;
index c74af15b14f2817a5b98c264950c0ae9e02dda60..5cfba9e98966d56efe534a2dace75ab522162464 100644 (file)
@@ -292,7 +292,9 @@ static inline bool bch2_inode_should_have_single_bp(struct bch_inode_unpacked *i
 struct bch_opts bch2_inode_opts_to_opts(struct bch_inode_unpacked *);
 void bch2_inode_opts_get(struct bch_io_opts *, struct bch_fs *,
                         struct bch_inode_unpacked *);
-int bch2_inum_opts_get(struct btree_trans*, subvol_inum, struct bch_io_opts *);
+int bch2_inum_opts_get(struct btree_trans *, subvol_inum, struct bch_io_opts *);
+int bch2_inode_set_casefold(struct btree_trans *, subvol_inum,
+                           struct bch_inode_unpacked *, unsigned);
 
 #include "rebalance.h"
 
index 651da52b2cbcc004c70b8cc19bea1f352b273931..e6be32003f3b4c4379ac335f56698d9057bd40e1 100644 (file)
@@ -473,6 +473,12 @@ static int inode_opt_set_fn(struct btree_trans *trans,
 {
        struct inode_opt_set *s = p;
 
+       if (s->id == Inode_opt_casefold) {
+               int ret = bch2_inode_set_casefold(trans, inode_inum(inode), bi, s->v);
+               if (ret)
+                       return ret;
+       }
+
        if (s->defined)
                bi->bi_fields_set |= 1U << s->id;
        else