Merge tag 'ext4-for-linus-5.8-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / fs / ext4 / super.c
index 2660a7e47eefa6d2b7973bf0464faca43ace7b36..330957ed1f05c817ee1c2d0f3d064279af75b5c1 100644 (file)
@@ -93,11 +93,11 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
  * i_mmap_rwsem (inode->i_mmap_rwsem)!
  *
  * page fault path:
- * mmap_sem -> sb_start_pagefault -> i_mmap_sem (r) -> transaction start ->
+ * mmap_lock -> sb_start_pagefault -> i_mmap_sem (r) -> transaction start ->
  *   page lock -> i_data_sem (rw)
  *
  * buffered write path:
- * sb_start_write -> i_mutex -> mmap_sem
+ * sb_start_write -> i_mutex -> mmap_lock
  * sb_start_write -> i_mutex -> transaction start -> page lock ->
  *   i_data_sem (rw)
  *
@@ -107,7 +107,7 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
  *   i_data_sem (rw)
  *
  * direct IO:
- * sb_start_write -> i_mutex -> mmap_sem
+ * sb_start_write -> i_mutex -> mmap_lock
  * sb_start_write -> i_mutex -> transaction start -> i_data_sem (rw)
  *
  * writepages:
@@ -1100,6 +1100,7 @@ static void ext4_put_super(struct super_block *sb)
                crypto_free_shash(sbi->s_chksum_driver);
        kfree(sbi->s_blockgroup_lock);
        fs_put_dax(sbi->s_daxdev);
+       fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
 #ifdef CONFIG_UNICODE
        utf8_unload(sbi->s_encoding);
 #endif
@@ -1386,9 +1387,10 @@ retry:
        return res;
 }
 
-static bool ext4_dummy_context(struct inode *inode)
+static const union fscrypt_context *
+ext4_get_dummy_context(struct super_block *sb)
 {
-       return DUMMY_ENCRYPTION_ENABLED(EXT4_SB(inode->i_sb));
+       return EXT4_SB(sb)->s_dummy_enc_ctx.ctx;
 }
 
 static bool ext4_has_stable_inodes(struct super_block *sb)
@@ -1407,7 +1409,7 @@ static const struct fscrypt_operations ext4_cryptops = {
        .key_prefix             = "ext4:",
        .get_context            = ext4_get_context,
        .set_context            = ext4_set_context,
-       .dummy_context          = ext4_dummy_context,
+       .get_dummy_context      = ext4_get_dummy_context,
        .empty_dir              = ext4_empty_dir,
        .max_namelen            = EXT4_NAME_LEN,
        .has_stable_inodes      = ext4_has_stable_inodes,
@@ -1606,6 +1608,7 @@ static const match_table_t tokens = {
        {Opt_init_itable, "init_itable"},
        {Opt_noinit_itable, "noinit_itable"},
        {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+       {Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
        {Opt_test_dummy_encryption, "test_dummy_encryption"},
        {Opt_nombcache, "nombcache"},
        {Opt_nombcache, "no_mbcache"},  /* for backward compatibility */
@@ -1824,7 +1827,7 @@ static const struct mount_opts {
        {Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
        {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
        {Opt_max_dir_size_kb, 0, MOPT_GTE0},
-       {Opt_test_dummy_encryption, 0, MOPT_GTE0},
+       {Opt_test_dummy_encryption, 0, MOPT_STRING},
        {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
        {Opt_err, 0, 0}
 };
@@ -1859,6 +1862,48 @@ static int ext4_sb_read_encoding(const struct ext4_super_block *es,
 }
 #endif
 
+static int ext4_set_test_dummy_encryption(struct super_block *sb,
+                                         const char *opt,
+                                         const substring_t *arg,
+                                         bool is_remount)
+{
+#ifdef CONFIG_FS_ENCRYPTION
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       int err;
+
+       /*
+        * This mount option is just for testing, and it's not worthwhile to
+        * implement the extra complexity (e.g. RCU protection) that would be
+        * needed to allow it to be set or changed during remount.  We do allow
+        * it to be specified during remount, but only if there is no change.
+        */
+       if (is_remount && !sbi->s_dummy_enc_ctx.ctx) {
+               ext4_msg(sb, KERN_WARNING,
+                        "Can't set test_dummy_encryption on remount");
+               return -1;
+       }
+       err = fscrypt_set_test_dummy_encryption(sb, arg, &sbi->s_dummy_enc_ctx);
+       if (err) {
+               if (err == -EEXIST)
+                       ext4_msg(sb, KERN_WARNING,
+                                "Can't change test_dummy_encryption on remount");
+               else if (err == -EINVAL)
+                       ext4_msg(sb, KERN_WARNING,
+                                "Value of option \"%s\" is unrecognized", opt);
+               else
+                       ext4_msg(sb, KERN_WARNING,
+                                "Error processing option \"%s\" [%d]",
+                                opt, err);
+               return -1;
+       }
+       ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
+#else
+       ext4_msg(sb, KERN_WARNING,
+                "Test dummy encryption mount option ignored");
+#endif
+       return 1;
+}
+
 static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                            substring_t *args, unsigned long *journal_devnum,
                            unsigned int *journal_ioprio, int is_remount)
@@ -2055,14 +2100,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                *journal_ioprio =
                        IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
        } else if (token == Opt_test_dummy_encryption) {
-#ifdef CONFIG_FS_ENCRYPTION
-               sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
-               ext4_msg(sb, KERN_WARNING,
-                        "Test dummy encryption mode enabled");
-#else
-               ext4_msg(sb, KERN_WARNING,
-                        "Test dummy encryption mount option ignored");
-#endif
+               return ext4_set_test_dummy_encryption(sb, opt, &args[0],
+                                                     is_remount);
        } else if (m->flags & MOPT_DATAJ) {
                if (is_remount) {
                        if (!sbi->s_journal)
@@ -2362,8 +2401,8 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
                SEQ_OPTS_PRINT("max_dir_size_kb=%u", sbi->s_max_dir_size_kb);
        if (test_opt(sb, DATA_ERR_ABORT))
                SEQ_OPTS_PUTS("data_err=abort");
-       if (DUMMY_ENCRYPTION_ENABLED(sbi))
-               SEQ_OPTS_PUTS("test_dummy_encryption");
+
+       fscrypt_show_test_dummy_encryption(seq, sep, sb);
 
        if (test_opt(sb, DAX_ALWAYS)) {
                if (IS_EXT2_SB(sb))
@@ -4841,6 +4880,7 @@ failed_mount:
        for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(get_qf_name(sb, sbi, i));
 #endif
+       fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
        ext4_blkdev_remove(sbi);
        brelse(bh);
 out_fail:
@@ -5317,7 +5357,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
                needs_barrier = true;
        if (needs_barrier) {
                int err;
-               err = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
+               err = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL);
                if (!ret)
                        ret = err;
        }