diff options
-rw-r--r-- | fs/ext4/ext4.h | 21 | ||||
-rw-r--r-- | fs/ext4/super.c | 85 |
2 files changed, 105 insertions, 1 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 2a2e6ed9aab4..c1504c471fef 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1313,7 +1313,9 @@ struct ext4_super_block { | |||
1313 | __u8 s_first_error_time_hi; | 1313 | __u8 s_first_error_time_hi; |
1314 | __u8 s_last_error_time_hi; | 1314 | __u8 s_last_error_time_hi; |
1315 | __u8 s_pad[2]; | 1315 | __u8 s_pad[2]; |
1316 | __le32 s_reserved[96]; /* Padding to the end of the block */ | 1316 | __le16 s_encoding; /* Filename charset encoding */ |
1317 | __le16 s_encoding_flags; /* Filename charset encoding flags */ | ||
1318 | __le32 s_reserved[95]; /* Padding to the end of the block */ | ||
1317 | __le32 s_checksum; /* crc32c(superblock) */ | 1319 | __le32 s_checksum; /* crc32c(superblock) */ |
1318 | }; | 1320 | }; |
1319 | 1321 | ||
@@ -1338,6 +1340,16 @@ struct ext4_super_block { | |||
1338 | /* Number of quota types we support */ | 1340 | /* Number of quota types we support */ |
1339 | #define EXT4_MAXQUOTAS 3 | 1341 | #define EXT4_MAXQUOTAS 3 |
1340 | 1342 | ||
1343 | #define EXT4_ENC_UTF8_12_1 1 | ||
1344 | |||
1345 | /* | ||
1346 | * Flags for ext4_sb_info.s_encoding_flags. | ||
1347 | */ | ||
1348 | #define EXT4_ENC_STRICT_MODE_FL (1 << 0) | ||
1349 | |||
1350 | #define ext4_has_strict_mode(sbi) \ | ||
1351 | (sbi->s_encoding_flags & EXT4_ENC_STRICT_MODE_FL) | ||
1352 | |||
1341 | /* | 1353 | /* |
1342 | * fourth extended-fs super-block data in memory | 1354 | * fourth extended-fs super-block data in memory |
1343 | */ | 1355 | */ |
@@ -1387,6 +1399,10 @@ struct ext4_sb_info { | |||
1387 | struct kobject s_kobj; | 1399 | struct kobject s_kobj; |
1388 | struct completion s_kobj_unregister; | 1400 | struct completion s_kobj_unregister; |
1389 | struct super_block *s_sb; | 1401 | struct super_block *s_sb; |
1402 | #ifdef CONFIG_UNICODE | ||
1403 | struct unicode_map *s_encoding; | ||
1404 | __u16 s_encoding_flags; | ||
1405 | #endif | ||
1390 | 1406 | ||
1391 | /* Journaling */ | 1407 | /* Journaling */ |
1392 | struct journal_s *s_journal; | 1408 | struct journal_s *s_journal; |
@@ -1660,6 +1676,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) | |||
1660 | #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ | 1676 | #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ |
1661 | #define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */ | 1677 | #define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */ |
1662 | #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 | 1678 | #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 |
1679 | #define EXT4_FEATURE_INCOMPAT_CASEFOLD 0x20000 | ||
1663 | 1680 | ||
1664 | extern void ext4_update_dynamic_rev(struct super_block *sb); | 1681 | extern void ext4_update_dynamic_rev(struct super_block *sb); |
1665 | 1682 | ||
@@ -1753,6 +1770,7 @@ EXT4_FEATURE_INCOMPAT_FUNCS(csum_seed, CSUM_SEED) | |||
1753 | EXT4_FEATURE_INCOMPAT_FUNCS(largedir, LARGEDIR) | 1770 | EXT4_FEATURE_INCOMPAT_FUNCS(largedir, LARGEDIR) |
1754 | EXT4_FEATURE_INCOMPAT_FUNCS(inline_data, INLINE_DATA) | 1771 | EXT4_FEATURE_INCOMPAT_FUNCS(inline_data, INLINE_DATA) |
1755 | EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT) | 1772 | EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT) |
1773 | EXT4_FEATURE_INCOMPAT_FUNCS(casefold, CASEFOLD) | ||
1756 | 1774 | ||
1757 | #define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR | 1775 | #define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR |
1758 | #define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ | 1776 | #define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ |
@@ -1780,6 +1798,7 @@ EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT) | |||
1780 | EXT4_FEATURE_INCOMPAT_MMP | \ | 1798 | EXT4_FEATURE_INCOMPAT_MMP | \ |
1781 | EXT4_FEATURE_INCOMPAT_INLINE_DATA | \ | 1799 | EXT4_FEATURE_INCOMPAT_INLINE_DATA | \ |
1782 | EXT4_FEATURE_INCOMPAT_ENCRYPT | \ | 1800 | EXT4_FEATURE_INCOMPAT_ENCRYPT | \ |
1801 | EXT4_FEATURE_INCOMPAT_CASEFOLD | \ | ||
1783 | EXT4_FEATURE_INCOMPAT_CSUM_SEED | \ | 1802 | EXT4_FEATURE_INCOMPAT_CSUM_SEED | \ |
1784 | EXT4_FEATURE_INCOMPAT_LARGEDIR) | 1803 | EXT4_FEATURE_INCOMPAT_LARGEDIR) |
1785 | #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ | 1804 | #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ |
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]); |