Commit 8d5ac187 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Fix casefold opt via xattr interface



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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent cbed8287
Loading
Loading
Loading
Loading
+1 −25
Original line number Diff line number Diff line
@@ -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) {
+36 −0
Original line number Diff line number Diff line
@@ -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;
+3 −1
Original line number Diff line number Diff line
@@ -293,6 +293,8 @@ 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_inode_set_casefold(struct btree_trans *, subvol_inum,
			    struct bch_inode_unpacked *, unsigned);

#include "rebalance.h"

+6 −0
Original line number Diff line number Diff line
@@ -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