|
42 | 42 | #include <linux/cleancache.h>
|
43 | 43 | #include <linux/uaccess.h>
|
44 | 44 | #include <linux/iversion.h>
|
| 45 | +#include <linux/unicode.h> |
45 | 46 |
|
46 | 47 | #include <linux/kthread.h>
|
47 | 48 | #include <linux/freezer.h>
|
@@ -1054,6 +1055,9 @@ static void ext4_put_super(struct super_block *sb)
|
1054 | 1055 | crypto_free_shash(sbi->s_chksum_driver);
|
1055 | 1056 | kfree(sbi->s_blockgroup_lock);
|
1056 | 1057 | fs_put_dax(sbi->s_daxdev);
|
| 1058 | +#ifdef CONFIG_UNICODE |
| 1059 | + utf8_unload(sbi->s_encoding); |
| 1060 | +#endif |
1057 | 1061 | kfree(sbi);
|
1058 | 1062 | }
|
1059 | 1063 |
|
@@ -1750,6 +1754,36 @@ static const struct mount_opts {
|
1750 | 1754 | {Opt_err, 0, 0}
|
1751 | 1755 | };
|
1752 | 1756 |
|
| 1757 | +#ifdef CONFIG_UNICODE |
| 1758 | +static const struct ext4_sb_encodings { |
| 1759 | + __u16 magic; |
| 1760 | + char *name; |
| 1761 | + char *version; |
| 1762 | +} ext4_sb_encoding_map[] = { |
| 1763 | + {EXT4_ENC_UTF8_12_1, "utf8", "12.1.0"}, |
| 1764 | +}; |
| 1765 | + |
| 1766 | +static int ext4_sb_read_encoding(const struct ext4_super_block *es, |
| 1767 | + const struct ext4_sb_encodings **encoding, |
| 1768 | + __u16 *flags) |
| 1769 | +{ |
| 1770 | + __u16 magic = le16_to_cpu(es->s_encoding); |
| 1771 | + int i; |
| 1772 | + |
| 1773 | + for (i = 0; i < ARRAY_SIZE(ext4_sb_encoding_map); i++) |
| 1774 | + if (magic == ext4_sb_encoding_map[i].magic) |
| 1775 | + break; |
| 1776 | + |
| 1777 | + if (i >= ARRAY_SIZE(ext4_sb_encoding_map)) |
| 1778 | + return -EINVAL; |
| 1779 | + |
| 1780 | + *encoding = &ext4_sb_encoding_map[i]; |
| 1781 | + *flags = le16_to_cpu(es->s_encoding_flags); |
| 1782 | + |
| 1783 | + return 0; |
| 1784 | +} |
| 1785 | +#endif |
| 1786 | + |
1753 | 1787 | static int handle_mount_opt(struct super_block *sb, char *opt, int token,
|
1754 | 1788 | substring_t *args, unsigned long *journal_devnum,
|
1755 | 1789 | unsigned int *journal_ioprio, int is_remount)
|
@@ -2880,6 +2914,15 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
|
2880 | 2914 | return 0;
|
2881 | 2915 | }
|
2882 | 2916 |
|
| 2917 | +#ifndef CONFIG_UNICODE |
| 2918 | + if (ext4_has_feature_casefold(sb)) { |
| 2919 | + ext4_msg(sb, KERN_ERR, |
| 2920 | + "Filesystem with casefold feature cannot be " |
| 2921 | + "mounted without CONFIG_UNICODE"); |
| 2922 | + return 0; |
| 2923 | + } |
| 2924 | +#endif |
| 2925 | + |
2883 | 2926 | if (readonly)
|
2884 | 2927 | return 1;
|
2885 | 2928 |
|
@@ -3770,6 +3813,43 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
3770 | 3813 | &journal_ioprio, 0))
|
3771 | 3814 | goto failed_mount;
|
3772 | 3815 |
|
| 3816 | +#ifdef CONFIG_UNICODE |
| 3817 | + if (ext4_has_feature_casefold(sb) && !sbi->s_encoding) { |
| 3818 | + const struct ext4_sb_encodings *encoding_info; |
| 3819 | + struct unicode_map *encoding; |
| 3820 | + __u16 encoding_flags; |
| 3821 | + |
| 3822 | + if (ext4_has_feature_encrypt(sb)) { |
| 3823 | + ext4_msg(sb, KERN_ERR, |
| 3824 | + "Can't mount with encoding and encryption"); |
| 3825 | + goto failed_mount; |
| 3826 | + } |
| 3827 | + |
| 3828 | + if (ext4_sb_read_encoding(es, &encoding_info, |
| 3829 | + &encoding_flags)) { |
| 3830 | + ext4_msg(sb, KERN_ERR, |
| 3831 | + "Encoding requested by superblock is unknown"); |
| 3832 | + goto failed_mount; |
| 3833 | + } |
| 3834 | + |
| 3835 | + encoding = utf8_load(encoding_info->version); |
| 3836 | + if (IS_ERR(encoding)) { |
| 3837 | + ext4_msg(sb, KERN_ERR, |
| 3838 | + "can't mount with superblock charset: %s-%s " |
| 3839 | + "not supported by the kernel. flags: 0x%x.", |
| 3840 | + encoding_info->name, encoding_info->version, |
| 3841 | + encoding_flags); |
| 3842 | + goto failed_mount; |
| 3843 | + } |
| 3844 | + ext4_msg(sb, KERN_INFO,"Using encoding defined by superblock: " |
| 3845 | + "%s-%s with flags 0x%hx", encoding_info->name, |
| 3846 | + encoding_info->version?:"\b", encoding_flags); |
| 3847 | + |
| 3848 | + sbi->s_encoding = encoding; |
| 3849 | + sbi->s_encoding_flags = encoding_flags; |
| 3850 | + } |
| 3851 | +#endif |
| 3852 | + |
3773 | 3853 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
|
3774 | 3854 | printk_once(KERN_WARNING "EXT4-fs: Warning: mounting "
|
3775 | 3855 | "with data=journal disables delayed "
|
@@ -4586,6 +4666,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
4586 | 4666 | failed_mount:
|
4587 | 4667 | if (sbi->s_chksum_driver)
|
4588 | 4668 | crypto_free_shash(sbi->s_chksum_driver);
|
| 4669 | + |
| 4670 | +#ifdef CONFIG_UNICODE |
| 4671 | + utf8_unload(sbi->s_encoding); |
| 4672 | +#endif |
| 4673 | + |
4589 | 4674 | #ifdef CONFIG_QUOTA
|
4590 | 4675 | for (i = 0; i < EXT4_MAXQUOTAS; i++)
|
4591 | 4676 | kfree(sbi->s_qf_names[i]);
|
|
0 commit comments