mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
bcachefs: opts.casefold_disabled
Add an option for completely disabling casefolding on a filesystem, as a workaround for overlayfs. This should only be needed as a temporary workaround, until the overlayfs fix arrives. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
c6e8d51b37
commit
94426e4201
10 changed files with 55 additions and 43 deletions
|
@ -863,9 +863,7 @@ struct bch_fs {
|
|||
DARRAY(enum bcachefs_metadata_version)
|
||||
incompat_versions_requested;
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
struct unicode_map *cf_encoding;
|
||||
#endif
|
||||
|
||||
struct bch_sb_handle disk_sb;
|
||||
|
||||
|
@ -1285,4 +1283,13 @@ static inline bool bch2_discard_opt_enabled(struct bch_fs *c, struct bch_dev *ca
|
|||
: ca->mi.discard;
|
||||
}
|
||||
|
||||
static inline bool bch2_fs_casefold_enabled(struct bch_fs *c)
|
||||
{
|
||||
#ifdef CONFIG_UNICODE
|
||||
return !c->opts.casefold_disabled;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _BCACHEFS_H */
|
||||
|
|
|
@ -18,7 +18,9 @@ int bch2_casefold(struct btree_trans *trans, const struct bch_hash_info *info,
|
|||
{
|
||||
*out_cf = (struct qstr) QSTR_INIT(NULL, 0);
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (!bch2_fs_casefold_enabled(trans->c))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
unsigned char *buf = bch2_trans_kmalloc(trans, BCH_NAME_MAX + 1);
|
||||
int ret = PTR_ERR_OR_ZERO(buf);
|
||||
if (ret)
|
||||
|
@ -30,9 +32,6 @@ int bch2_casefold(struct btree_trans *trans, const struct bch_hash_info *info,
|
|||
|
||||
*out_cf = (struct qstr) QSTR_INIT(buf, ret);
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
|
||||
|
@ -231,7 +230,8 @@ void bch2_dirent_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
|
|||
prt_printf(out, " type %s", bch2_d_type_str(d.v->d_type));
|
||||
}
|
||||
|
||||
int bch2_dirent_init_name(struct bkey_i_dirent *dirent,
|
||||
int bch2_dirent_init_name(struct bch_fs *c,
|
||||
struct bkey_i_dirent *dirent,
|
||||
const struct bch_hash_info *hash_info,
|
||||
const struct qstr *name,
|
||||
const struct qstr *cf_name)
|
||||
|
@ -251,7 +251,9 @@ int bch2_dirent_init_name(struct bkey_i_dirent *dirent,
|
|||
offsetof(struct bch_dirent, d_name) -
|
||||
name->len);
|
||||
} else {
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (!bch2_fs_casefold_enabled(c))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memcpy(&dirent->v.d_cf_name_block.d_names[0], name->name, name->len);
|
||||
|
||||
char *cf_out = &dirent->v.d_cf_name_block.d_names[name->len];
|
||||
|
@ -277,9 +279,6 @@ int bch2_dirent_init_name(struct bkey_i_dirent *dirent,
|
|||
dirent->v.d_cf_name_block.d_cf_name_len = cpu_to_le16(cf_len);
|
||||
|
||||
EBUG_ON(bch2_dirent_get_casefold_name(dirent_i_to_s_c(dirent)).len != cf_len);
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned u64s = dirent_val_u64s(name->len, cf_len);
|
||||
|
@ -313,7 +312,7 @@ struct bkey_i_dirent *bch2_dirent_create_key(struct btree_trans *trans,
|
|||
dirent->v.d_type = type;
|
||||
dirent->v.d_unused = 0;
|
||||
|
||||
int ret = bch2_dirent_init_name(dirent, hash_info, name, cf_name);
|
||||
int ret = bch2_dirent_init_name(trans->c, dirent, hash_info, name, cf_name);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
|
|
@ -59,7 +59,8 @@ static inline void dirent_copy_target(struct bkey_i_dirent *dst,
|
|||
dst->v.d_type = src.v->d_type;
|
||||
}
|
||||
|
||||
int bch2_dirent_init_name(struct bkey_i_dirent *,
|
||||
int bch2_dirent_init_name(struct bch_fs *,
|
||||
struct bkey_i_dirent *,
|
||||
const struct bch_hash_info *,
|
||||
const struct qstr *,
|
||||
const struct qstr *);
|
||||
|
|
|
@ -722,7 +722,6 @@ static struct dentry *bch2_lookup(struct inode *vdir, struct dentry *dentry,
|
|||
if (IS_ERR(inode))
|
||||
inode = NULL;
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (!inode && IS_CASEFOLDED(vdir)) {
|
||||
/*
|
||||
* Do not cache a negative dentry in casefolded directories
|
||||
|
@ -737,7 +736,6 @@ static struct dentry *bch2_lookup(struct inode *vdir, struct dentry *dentry,
|
|||
*/
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return d_splice_alias(&inode->v, dentry);
|
||||
}
|
||||
|
@ -2566,9 +2564,10 @@ got_sb:
|
|||
sb->s_shrink->seeks = 0;
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (bch2_fs_casefold_enabled(c))
|
||||
sb->s_encoding = c->cf_encoding;
|
||||
#endif
|
||||
generic_set_sb_d_ops(sb);
|
||||
#endif
|
||||
|
||||
vinode = bch2_vfs_inode_get(c, BCACHEFS_ROOT_SUBVOL_INUM);
|
||||
ret = PTR_ERR_OR_ZERO(vinode);
|
||||
|
|
|
@ -2302,9 +2302,7 @@ 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);
|
||||
|
|
|
@ -1265,7 +1265,14 @@ int bch2_inode_set_casefold(struct btree_trans *trans, subvol_inum inum,
|
|||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
#ifndef CONFIG_UNICODE
|
||||
bch_err(c, "Cannot use casefolding on a kernel without CONFIG_UNICODE");
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
|
||||
if (c->opts.casefold_disabled)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
int ret = 0;
|
||||
/* Not supported on individual files. */
|
||||
if (!S_ISDIR(bi->bi_mode))
|
||||
|
@ -1289,10 +1296,6 @@ int bch2_inode_set_casefold(struct btree_trans *trans, subvol_inum inum,
|
|||
bi->bi_fields_set |= BIT(Inode_opt_casefold);
|
||||
|
||||
return bch2_maybe_propagate_has_case_insensitive(trans, inum, bi);
|
||||
#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)
|
||||
|
|
|
@ -234,6 +234,11 @@ enum fsck_err_opts {
|
|||
OPT_BOOL(), \
|
||||
BCH_SB_CASEFOLD, false, \
|
||||
NULL, "Dirent lookups are casefolded") \
|
||||
x(casefold_disabled, u8, \
|
||||
OPT_FS|OPT_MOUNT, \
|
||||
OPT_BOOL(), \
|
||||
BCH2_NO_SB_OPT, false, \
|
||||
NULL, "Disable casefolding filesystem wide") \
|
||||
x(inodes_32bit, u8, \
|
||||
OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
|
||||
OPT_BOOL(), \
|
||||
|
|
|
@ -38,6 +38,7 @@ static int bch2_fsck_rename_dirent(struct btree_trans *trans,
|
|||
struct bkey_s_c_dirent old,
|
||||
bool *updated_before_k_pos)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct qstr old_name = bch2_dirent_get_name(old);
|
||||
struct bkey_i_dirent *new = bch2_trans_kmalloc(trans, BKEY_U64s_MAX * sizeof(u64));
|
||||
int ret = PTR_ERR_OR_ZERO(new);
|
||||
|
@ -60,7 +61,7 @@ static int bch2_fsck_rename_dirent(struct btree_trans *trans,
|
|||
sprintf(renamed_buf, "%.*s.fsck_renamed-%u",
|
||||
old_name.len, old_name.name, i));
|
||||
|
||||
ret = bch2_dirent_init_name(new, hash_info, &renamed_name, NULL);
|
||||
ret = bch2_dirent_init_name(c, new, hash_info, &renamed_name, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -79,7 +80,7 @@ static int bch2_fsck_rename_dirent(struct btree_trans *trans,
|
|||
}
|
||||
|
||||
ret = ret ?: bch2_fsck_update_backpointers(trans, s, desc, hash_info, &new->k_i);
|
||||
bch_err_fn(trans->c, ret);
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,7 @@ bch2_hash_info_init(struct bch_fs *c, const struct bch_inode_unpacked *bi)
|
|||
struct bch_hash_info info = {
|
||||
.inum_snapshot = bi->bi_snapshot,
|
||||
.type = INODE_STR_HASH(bi),
|
||||
#ifdef CONFIG_UNICODE
|
||||
.cf_encoding = bch2_inode_casefold(c, bi) ? c->cf_encoding : NULL,
|
||||
#endif
|
||||
.siphash_key = { .k0 = bi->bi_hash_seed }
|
||||
};
|
||||
|
||||
|
|
|
@ -1025,6 +1025,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts *opts,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (bch2_fs_casefold_enabled(c)) {
|
||||
/* Default encoding until we can potentially have more as an option. */
|
||||
c->cf_encoding = utf8_load(BCH_FS_DEFAULT_UTF8_ENCODING);
|
||||
if (IS_ERR(c->cf_encoding)) {
|
||||
|
@ -1035,6 +1036,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts *opts,
|
|||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (c->sb.features & BIT_ULL(BCH_FEATURE_casefolding)) {
|
||||
printk(KERN_ERR "Cannot mount a filesystem with casefolding on a kernel without CONFIG_UNICODE\n");
|
||||
|
@ -1160,12 +1162,11 @@ int bch2_fs_start(struct bch_fs *c)
|
|||
|
||||
print_mount_opts(c);
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (c->cf_encoding)
|
||||
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue