diff options
Diffstat (limited to 'fs/f2fs/super.c')
-rw-r--r-- | fs/f2fs/super.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 9167deb0c417..8bebee8e0186 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -23,6 +23,7 @@ #include <linux/f2fs_fs.h> #include <linux/sysfs.h> #include <linux/quota.h> +#include <linux/unicode.h> #include "f2fs.h" #include "node.h" @@ -222,6 +223,36 @@ void f2fs_printk(struct f2fs_sb_info *sbi, const char *fmt, ...) va_end(args); } +#ifdef CONFIG_UNICODE +static const struct f2fs_sb_encodings { + __u16 magic; + char *name; + char *version; +} f2fs_sb_encoding_map[] = { + {F2FS_ENC_UTF8_12_1, "utf8", "12.1.0"}, +}; + +static int f2fs_sb_read_encoding(const struct f2fs_super_block *sb, + const struct f2fs_sb_encodings **encoding, + __u16 *flags) +{ + __u16 magic = le16_to_cpu(sb->s_encoding); + int i; + + for (i = 0; i < ARRAY_SIZE(f2fs_sb_encoding_map); i++) + if (magic == f2fs_sb_encoding_map[i].magic) + break; + + if (i >= ARRAY_SIZE(f2fs_sb_encoding_map)) + return -EINVAL; + + *encoding = &f2fs_sb_encoding_map[i]; + *flags = le16_to_cpu(sb->s_encoding_flags); + + return 0; +} +#endif + static inline void limit_reserve_root(struct f2fs_sb_info *sbi) { block_t limit = min((sbi->user_block_count << 1) / 1000, @@ -798,6 +829,13 @@ static int parse_options(struct super_block *sb, char *options) return -EINVAL; } #endif +#ifndef CONFIG_UNICODE + if (f2fs_sb_has_casefold(sbi)) { + f2fs_err(sbi, + "Filesystem with casefold feature cannot be mounted without CONFIG_UNICODE"); + return -EINVAL; + } +#endif if (F2FS_IO_SIZE_BITS(sbi) && !test_opt(sbi, LFS)) { f2fs_err(sbi, "Should set mode=lfs with %uKB-sized IO", @@ -1103,6 +1141,9 @@ static void f2fs_put_super(struct super_block *sb) destroy_percpu_info(sbi); for (i = 0; i < NR_PAGE_TYPE; i++) kvfree(sbi->write_io[i]); +#ifdef CONFIG_UNICODE + utf8_unload(sbi->s_encoding); +#endif kvfree(sbi); } @@ -3075,6 +3116,52 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) return 0; } +static int f2fs_setup_casefold(struct f2fs_sb_info *sbi) +{ +#ifdef CONFIG_UNICODE + if (f2fs_sb_has_casefold(sbi) && !sbi->s_encoding) { + const struct f2fs_sb_encodings *encoding_info; + struct unicode_map *encoding; + __u16 encoding_flags; + + if (f2fs_sb_has_encrypt(sbi)) { + f2fs_err(sbi, + "Can't mount with encoding and encryption"); + return -EINVAL; + } + + if (f2fs_sb_read_encoding(sbi->raw_super, &encoding_info, + &encoding_flags)) { + f2fs_err(sbi, + "Encoding requested by superblock is unknown"); + return -EINVAL; + } + + encoding = utf8_load(encoding_info->version); + if (IS_ERR(encoding)) { + f2fs_err(sbi, + "can't mount with superblock charset: %s-%s " + "not supported by the kernel. flags: 0x%x.", + encoding_info->name, encoding_info->version, + encoding_flags); + return PTR_ERR(encoding); + } + f2fs_info(sbi, "Using encoding defined by superblock: " + "%s-%s with flags 0x%hx", encoding_info->name, + encoding_info->version?:"\b", encoding_flags); + + sbi->s_encoding = encoding; + sbi->s_encoding_flags = encoding_flags; + } +#else + if (f2fs_sb_has_casefold(sbi)) { + f2fs_err(sbi, "Filesystem with casefold feature cannot be mounted without CONFIG_UNICODE"); + return -EINVAL; + } +#endif + return 0; +} + static void f2fs_tuning_parameters(struct f2fs_sb_info *sbi) { struct f2fs_sm_info *sm_i = SM_I(sbi); @@ -3171,6 +3258,10 @@ try_onemore: le32_to_cpu(raw_super->log_blocksize); sb->s_max_links = F2FS_LINK_MAX; + err = f2fs_setup_casefold(sbi); + if (err) + goto free_options; + #ifdef CONFIG_QUOTA sb->dq_op = &f2fs_quota_operations; sb->s_qcop = &f2fs_quotactl_ops; @@ -3521,6 +3612,10 @@ free_percpu: free_bio_info: for (i = 0; i < NR_PAGE_TYPE; i++) kvfree(sbi->write_io[i]); + +#ifdef CONFIG_UNICODE + utf8_unload(sbi->s_encoding); +#endif free_options: #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) |