diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-19 17:26:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-19 17:26:31 -0400 |
commit | 6162e4b0bedeb3dac2ba0a5e1b1f56db107d97ec (patch) | |
tree | b4ee364c3819f19acd8a63b06d455b11cd91b9ae /fs/ext4/super.c | |
parent | 17974c054db3030b714b7108566bf5208d965a19 (diff) | |
parent | 6ddb2447846a8ece111e316a2863c2355023682d (diff) |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o:
"A few bug fixes and add support for file-system level encryption in
ext4"
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (31 commits)
ext4 crypto: enable encryption feature flag
ext4 crypto: add symlink encryption
ext4 crypto: enable filename encryption
ext4 crypto: filename encryption modifications
ext4 crypto: partial update to namei.c for fname crypto
ext4 crypto: insert encrypted filenames into a leaf directory block
ext4 crypto: teach ext4_htree_store_dirent() to store decrypted filenames
ext4 crypto: filename encryption facilities
ext4 crypto: implement the ext4 decryption read path
ext4 crypto: implement the ext4 encryption write path
ext4 crypto: inherit encryption policies on inode and directory create
ext4 crypto: enforce context consistency
ext4 crypto: add encryption key management facilities
ext4 crypto: add ext4 encryption facilities
ext4 crypto: add encryption policy and password salt support
ext4 crypto: add encryption xattr support
ext4 crypto: export ext4_empty_dir()
ext4 crypto: add ext4 encryption Kconfig
ext4 crypto: reserve codepoints used by the ext4 encryption feature
ext4 crypto: add ext4_mpage_readpages()
...
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d348c7d29d80..821f22dbe825 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/time.h> | 22 | #include <linux/time.h> |
23 | #include <linux/vmalloc.h> | 23 | #include <linux/vmalloc.h> |
24 | #include <linux/jbd2.h> | ||
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
27 | #include <linux/blkdev.h> | 26 | #include <linux/blkdev.h> |
@@ -323,22 +322,6 @@ static void save_error_info(struct super_block *sb, const char *func, | |||
323 | ext4_commit_super(sb, 1); | 322 | ext4_commit_super(sb, 1); |
324 | } | 323 | } |
325 | 324 | ||
326 | /* | ||
327 | * The del_gendisk() function uninitializes the disk-specific data | ||
328 | * structures, including the bdi structure, without telling anyone | ||
329 | * else. Once this happens, any attempt to call mark_buffer_dirty() | ||
330 | * (for example, by ext4_commit_super), will cause a kernel OOPS. | ||
331 | * This is a kludge to prevent these oops until we can put in a proper | ||
332 | * hook in del_gendisk() to inform the VFS and file system layers. | ||
333 | */ | ||
334 | static int block_device_ejected(struct super_block *sb) | ||
335 | { | ||
336 | struct inode *bd_inode = sb->s_bdev->bd_inode; | ||
337 | struct backing_dev_info *bdi = inode_to_bdi(bd_inode); | ||
338 | |||
339 | return bdi->dev == NULL; | ||
340 | } | ||
341 | |||
342 | static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) | 325 | static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) |
343 | { | 326 | { |
344 | struct super_block *sb = journal->j_private; | 327 | struct super_block *sb = journal->j_private; |
@@ -893,6 +876,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
893 | atomic_set(&ei->i_ioend_count, 0); | 876 | atomic_set(&ei->i_ioend_count, 0); |
894 | atomic_set(&ei->i_unwritten, 0); | 877 | atomic_set(&ei->i_unwritten, 0); |
895 | INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work); | 878 | INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work); |
879 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
880 | ei->i_encryption_key.mode = EXT4_ENCRYPTION_MODE_INVALID; | ||
881 | #endif | ||
896 | 882 | ||
897 | return &ei->vfs_inode; | 883 | return &ei->vfs_inode; |
898 | } | 884 | } |
@@ -1120,7 +1106,7 @@ enum { | |||
1120 | Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev, | 1106 | Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev, |
1121 | Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit, | 1107 | Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit, |
1122 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 1108 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
1123 | Opt_data_err_abort, Opt_data_err_ignore, | 1109 | Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption, |
1124 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 1110 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
1125 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, | 1111 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, |
1126 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, | 1112 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, |
@@ -1211,6 +1197,7 @@ static const match_table_t tokens = { | |||
1211 | {Opt_init_itable, "init_itable"}, | 1197 | {Opt_init_itable, "init_itable"}, |
1212 | {Opt_noinit_itable, "noinit_itable"}, | 1198 | {Opt_noinit_itable, "noinit_itable"}, |
1213 | {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, | 1199 | {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, |
1200 | {Opt_test_dummy_encryption, "test_dummy_encryption"}, | ||
1214 | {Opt_removed, "check=none"}, /* mount option from ext2/3 */ | 1201 | {Opt_removed, "check=none"}, /* mount option from ext2/3 */ |
1215 | {Opt_removed, "nocheck"}, /* mount option from ext2/3 */ | 1202 | {Opt_removed, "nocheck"}, /* mount option from ext2/3 */ |
1216 | {Opt_removed, "reservation"}, /* mount option from ext2/3 */ | 1203 | {Opt_removed, "reservation"}, /* mount option from ext2/3 */ |
@@ -1412,6 +1399,7 @@ static const struct mount_opts { | |||
1412 | {Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT}, | 1399 | {Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT}, |
1413 | {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT}, | 1400 | {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT}, |
1414 | {Opt_max_dir_size_kb, 0, MOPT_GTE0}, | 1401 | {Opt_max_dir_size_kb, 0, MOPT_GTE0}, |
1402 | {Opt_test_dummy_encryption, 0, MOPT_GTE0}, | ||
1415 | {Opt_err, 0, 0} | 1403 | {Opt_err, 0, 0} |
1416 | }; | 1404 | }; |
1417 | 1405 | ||
@@ -1588,6 +1576,15 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
1588 | } | 1576 | } |
1589 | *journal_ioprio = | 1577 | *journal_ioprio = |
1590 | IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg); | 1578 | IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg); |
1579 | } else if (token == Opt_test_dummy_encryption) { | ||
1580 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1581 | sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION; | ||
1582 | ext4_msg(sb, KERN_WARNING, | ||
1583 | "Test dummy encryption mode enabled"); | ||
1584 | #else | ||
1585 | ext4_msg(sb, KERN_WARNING, | ||
1586 | "Test dummy encryption mount option ignored"); | ||
1587 | #endif | ||
1591 | } else if (m->flags & MOPT_DATAJ) { | 1588 | } else if (m->flags & MOPT_DATAJ) { |
1592 | if (is_remount) { | 1589 | if (is_remount) { |
1593 | if (!sbi->s_journal) | 1590 | if (!sbi->s_journal) |
@@ -2685,11 +2682,13 @@ static struct attribute *ext4_attrs[] = { | |||
2685 | EXT4_INFO_ATTR(lazy_itable_init); | 2682 | EXT4_INFO_ATTR(lazy_itable_init); |
2686 | EXT4_INFO_ATTR(batched_discard); | 2683 | EXT4_INFO_ATTR(batched_discard); |
2687 | EXT4_INFO_ATTR(meta_bg_resize); | 2684 | EXT4_INFO_ATTR(meta_bg_resize); |
2685 | EXT4_INFO_ATTR(encryption); | ||
2688 | 2686 | ||
2689 | static struct attribute *ext4_feat_attrs[] = { | 2687 | static struct attribute *ext4_feat_attrs[] = { |
2690 | ATTR_LIST(lazy_itable_init), | 2688 | ATTR_LIST(lazy_itable_init), |
2691 | ATTR_LIST(batched_discard), | 2689 | ATTR_LIST(batched_discard), |
2692 | ATTR_LIST(meta_bg_resize), | 2690 | ATTR_LIST(meta_bg_resize), |
2691 | ATTR_LIST(encryption), | ||
2693 | NULL, | 2692 | NULL, |
2694 | }; | 2693 | }; |
2695 | 2694 | ||
@@ -3448,6 +3447,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3448 | if (sb->s_bdev->bd_part) | 3447 | if (sb->s_bdev->bd_part) |
3449 | sbi->s_sectors_written_start = | 3448 | sbi->s_sectors_written_start = |
3450 | part_stat_read(sb->s_bdev->bd_part, sectors[1]); | 3449 | part_stat_read(sb->s_bdev->bd_part, sectors[1]); |
3450 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
3451 | /* Modes of operations for file and directory encryption. */ | ||
3452 | sbi->s_file_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; | ||
3453 | sbi->s_dir_encryption_mode = EXT4_ENCRYPTION_MODE_INVALID; | ||
3454 | #endif | ||
3451 | 3455 | ||
3452 | /* Cleanup superblock name */ | 3456 | /* Cleanup superblock name */ |
3453 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) | 3457 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) |
@@ -3692,6 +3696,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3692 | } | 3696 | } |
3693 | } | 3697 | } |
3694 | 3698 | ||
3699 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT) && | ||
3700 | es->s_encryption_level) { | ||
3701 | ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d", | ||
3702 | es->s_encryption_level); | ||
3703 | goto failed_mount; | ||
3704 | } | ||
3705 | |||
3695 | if (sb->s_blocksize != blocksize) { | 3706 | if (sb->s_blocksize != blocksize) { |
3696 | /* Validate the filesystem blocksize */ | 3707 | /* Validate the filesystem blocksize */ |
3697 | if (!sb_set_blocksize(sb, blocksize)) { | 3708 | if (!sb_set_blocksize(sb, blocksize)) { |
@@ -4054,6 +4065,13 @@ no_journal: | |||
4054 | } | 4065 | } |
4055 | } | 4066 | } |
4056 | 4067 | ||
4068 | if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) && | ||
4069 | !(sb->s_flags & MS_RDONLY) && | ||
4070 | !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) { | ||
4071 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT); | ||
4072 | ext4_commit_super(sb, 1); | ||
4073 | } | ||
4074 | |||
4057 | /* | 4075 | /* |
4058 | * Get the # of file system overhead blocks from the | 4076 | * Get the # of file system overhead blocks from the |
4059 | * superblock if present. | 4077 | * superblock if present. |
@@ -4570,7 +4588,7 @@ static int ext4_commit_super(struct super_block *sb, int sync) | |||
4570 | struct buffer_head *sbh = EXT4_SB(sb)->s_sbh; | 4588 | struct buffer_head *sbh = EXT4_SB(sb)->s_sbh; |
4571 | int error = 0; | 4589 | int error = 0; |
4572 | 4590 | ||
4573 | if (!sbh || block_device_ejected(sb)) | 4591 | if (!sbh) |
4574 | return error; | 4592 | return error; |
4575 | if (buffer_write_io_error(sbh)) { | 4593 | if (buffer_write_io_error(sbh)) { |
4576 | /* | 4594 | /* |