diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 184944d4d8d1..c1b02c3a5a68 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/cleancache.h> | 42 | #include <linux/cleancache.h> |
43 | #include <linux/uaccess.h> | 43 | #include <linux/uaccess.h> |
44 | #include <linux/iversion.h> | 44 | #include <linux/iversion.h> |
45 | #include <linux/unicode.h> | ||
45 | 46 | ||
46 | #include <linux/kthread.h> | 47 | #include <linux/kthread.h> |
47 | #include <linux/freezer.h> | 48 | #include <linux/freezer.h> |
@@ -1054,6 +1055,9 @@ static void ext4_put_super(struct super_block *sb) | |||
1054 | crypto_free_shash(sbi->s_chksum_driver); | 1055 | crypto_free_shash(sbi->s_chksum_driver); |
1055 | kfree(sbi->s_blockgroup_lock); | 1056 | kfree(sbi->s_blockgroup_lock); |
1056 | fs_put_dax(sbi->s_daxdev); | 1057 | fs_put_dax(sbi->s_daxdev); |
1058 | #ifdef CONFIG_UNICODE | ||
1059 | utf8_unload(sbi->s_encoding); | ||
1060 | #endif | ||
1057 | kfree(sbi); | 1061 | kfree(sbi); |
1058 | } | 1062 | } |
1059 | 1063 | ||
@@ -1750,6 +1754,36 @@ static const struct mount_opts { | |||
1750 | {Opt_err, 0, 0} | 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 | static int handle_mount_opt(struct super_block *sb, char *opt, int token, | 1787 | static int handle_mount_opt(struct super_block *sb, char *opt, int token, |
1754 | substring_t *args, unsigned long *journal_devnum, | 1788 | substring_t *args, unsigned long *journal_devnum, |
1755 | unsigned int *journal_ioprio, int is_remount) | 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 | return 0; | 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 | if (readonly) | 2926 | if (readonly) |
2884 | return 1; | 2927 | return 1; |
2885 | 2928 | ||
@@ -3770,6 +3813,43 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3770 | &journal_ioprio, 0)) | 3813 | &journal_ioprio, 0)) |
3771 | goto failed_mount; | 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 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) { | 3853 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) { |
3774 | printk_once(KERN_WARNING "EXT4-fs: Warning: mounting " | 3854 | printk_once(KERN_WARNING "EXT4-fs: Warning: mounting " |
3775 | "with data=journal disables delayed " | 3855 | "with data=journal disables delayed " |
@@ -4586,6 +4666,11 @@ failed_mount2: | |||
4586 | failed_mount: | 4666 | failed_mount: |
4587 | if (sbi->s_chksum_driver) | 4667 | if (sbi->s_chksum_driver) |
4588 | crypto_free_shash(sbi->s_chksum_driver); | 4668 | crypto_free_shash(sbi->s_chksum_driver); |
4669 | |||
4670 | #ifdef CONFIG_UNICODE | ||
4671 | utf8_unload(sbi->s_encoding); | ||
4672 | #endif | ||
4673 | |||
4589 | #ifdef CONFIG_QUOTA | 4674 | #ifdef CONFIG_QUOTA |
4590 | for (i = 0; i < EXT4_MAXQUOTAS; i++) | 4675 | for (i = 0; i < EXT4_MAXQUOTAS; i++) |
4591 | kfree(sbi->s_qf_names[i]); | 4676 | kfree(sbi->s_qf_names[i]); |