ext4: add MODULE_SOFTDEP to ensure crc32c is included in the initramfs
[sfrench/cifs-2.6.git] / fs / ext4 / super.c
index 5de959fb0244291b2b29874a242c049fd8e6bcf0..eb104e8476f040e61253a6676c93e882e5a22314 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  linux/fs/ext4/super.c
  *
@@ -100,15 +101,13 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
  *   i_data_sem (rw)
  *
  * truncate:
- * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (w) -> i_mmap_sem (w) ->
- *   i_mmap_rwsem (w) -> page lock
- * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (w) -> i_mmap_sem (w) ->
- *   transaction start -> i_data_sem (rw)
+ * sb_start_write -> i_mutex -> i_mmap_sem (w) -> i_mmap_rwsem (w) -> page lock
+ * sb_start_write -> i_mutex -> i_mmap_sem (w) -> transaction start ->
+ *   i_data_sem (rw)
  *
  * direct IO:
- * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (r) -> mmap_sem
- * sb_start_write -> i_mutex -> EXT4_STATE_DIOREAD_LOCK (r) ->
- *   transaction start -> i_data_sem (rw)
+ * sb_start_write -> i_mutex -> mmap_sem
+ * sb_start_write -> i_mutex -> transaction start -> i_data_sem (rw)
  *
  * writepages:
  * transaction start -> page lock(s) -> i_data_sem (rw)
@@ -447,6 +446,7 @@ void __ext4_error(struct super_block *sb, const char *function,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
                return;
 
+       trace_ext4_error(sb, function, line);
        if (ext4_error_ratelimit(sb)) {
                va_start(args, fmt);
                vaf.fmt = fmt;
@@ -471,6 +471,7 @@ void __ext4_error_inode(struct inode *inode, const char *function,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return;
 
+       trace_ext4_error(inode->i_sb, function, line);
        es->s_last_error_ino = cpu_to_le32(inode->i_ino);
        es->s_last_error_block = cpu_to_le64(block);
        if (ext4_error_ratelimit(inode->i_sb)) {
@@ -506,6 +507,7 @@ void __ext4_error_file(struct file *file, const char *function,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return;
 
+       trace_ext4_error(inode->i_sb, function, line);
        es = EXT4_SB(inode->i_sb)->s_es;
        es->s_last_error_ino = cpu_to_le32(inode->i_ino);
        if (ext4_error_ratelimit(inode->i_sb)) {
@@ -718,6 +720,7 @@ __acquires(bitlock)
        if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
                return;
 
+       trace_ext4_error(sb, function, line);
        es->s_last_error_ino = cpu_to_le32(ino);
        es->s_last_error_block = cpu_to_le64(block);
        __save_error_info(sb, function, line);
@@ -743,6 +746,7 @@ __acquires(bitlock)
        }
 
        ext4_unlock_group(sb, grp);
+       ext4_commit_super(sb, 1);
        ext4_handle_error(sb);
        /*
         * We only get here in the ERRORS_RO case; relocking the group
@@ -871,7 +875,6 @@ static void ext4_put_super(struct super_block *sb)
        ext4_unregister_li_request(sb);
        ext4_quota_off_umount(sb);
 
-       flush_workqueue(sbi->rsv_conversion_wq);
        destroy_workqueue(sbi->rsv_conversion_wq);
 
        if (sbi->s_journal) {
@@ -1037,11 +1040,13 @@ static void init_once(void *foo)
 
 static int __init init_inodecache(void)
 {
-       ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
-                                            sizeof(struct ext4_inode_info),
-                                            0, (SLAB_RECLAIM_ACCOUNT|
-                                               SLAB_MEM_SPREAD|SLAB_ACCOUNT),
-                                            init_once);
+       ext4_inode_cachep = kmem_cache_create_usercopy("ext4_inode_cache",
+                               sizeof(struct ext4_inode_info), 0,
+                               (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|
+                                       SLAB_ACCOUNT),
+                               offsetof(struct ext4_inode_info, i_data),
+                               sizeof_field(struct ext4_inode_info, i_data),
+                               init_once);
        if (ext4_inode_cachep == NULL)
                return -ENOMEM;
        return 0;
@@ -1070,9 +1075,7 @@ void ext4_clear_inode(struct inode *inode)
                jbd2_free_inode(EXT4_I(inode)->jinode);
                EXT4_I(inode)->jinode = NULL;
        }
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
-       fscrypt_put_encryption_info(inode, NULL);
-#endif
+       fscrypt_put_encryption_info(inode);
 }
 
 static struct inode *ext4_nfs_get_inode(struct super_block *sb,
@@ -2018,7 +2021,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
-       int def_errors, def_mount_opt = nodefs ? 0 : sbi->s_def_mount_opt;
+       int def_errors, def_mount_opt = sbi->s_def_mount_opt;
        const struct mount_opts *m;
        char sep = nodefs ? '\n' : ',';
 
@@ -2033,7 +2036,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
                if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
                    (m->flags & MOPT_CLEAR_ERR))
                        continue;
-               if (!(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
+               if (!nodefs && !(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
                        continue; /* skip if same as the default */
                if ((want_set &&
                     (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) ||
@@ -2067,7 +2070,8 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
                SEQ_OPTS_PUTS("i_version");
        if (nodefs || sbi->s_stripe)
                SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe);
-       if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ def_mount_opt)) {
+       if (nodefs || EXT4_MOUNT_DATA_FLAGS &
+                       (sbi->s_mount_opt ^ def_mount_opt)) {
                if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
                        SEQ_OPTS_PUTS("data=journal");
                else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
@@ -2080,7 +2084,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
                SEQ_OPTS_PRINT("inode_readahead_blks=%u",
                               sbi->s_inode_readahead_blks);
 
-       if (nodefs || (test_opt(sb, INIT_INODE_TABLE) &&
+       if (test_opt(sb, INIT_INODE_TABLE) && (nodefs ||
                       (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)))
                SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult);
        if (nodefs || sbi->s_max_dir_size_kb)
@@ -2332,6 +2336,8 @@ static int ext4_check_descriptors(struct super_block *sb,
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
                                 "Block bitmap for group %u overlaps "
                                 "superblock", i);
+                       if (!sb_rdonly(sb))
+                               return 0;
                }
                if (block_bitmap < first_block || block_bitmap > last_block) {
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
@@ -2344,6 +2350,8 @@ static int ext4_check_descriptors(struct super_block *sb,
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
                                 "Inode bitmap for group %u overlaps "
                                 "superblock", i);
+                       if (!sb_rdonly(sb))
+                               return 0;
                }
                if (inode_bitmap < first_block || inode_bitmap > last_block) {
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
@@ -2356,6 +2364,8 @@ static int ext4_check_descriptors(struct super_block *sb,
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
                                 "Inode table for group %u overlaps "
                                 "superblock", i);
+                       if (!sb_rdonly(sb))
+                               return 0;
                }
                if (inode_table < first_block ||
                    inode_table + sbi->s_itb_per_group - 1 > last_block) {
@@ -2677,7 +2687,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,
         * compensate.
         */
        if (sb->s_blocksize == 1024 && nr == 0 &&
-           le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) == 0)
+           le32_to_cpu(sbi->s_es->s_first_data_block) == 0)
                has_super++;
 
        return (has_super + ext4_group_first_block_no(sb, bg));
@@ -3122,7 +3132,7 @@ int ext4_register_li_request(struct super_block *sb,
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_li_request *elr = NULL;
-       ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+       ext4_group_t ngroups = sbi->s_groups_count;
        int ret = 0;
 
        mutex_lock(&ext4_li_mtx);
@@ -3489,15 +3499,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        /* Load the checksum driver */
-       if (ext4_has_feature_metadata_csum(sb) ||
-           ext4_has_feature_ea_inode(sb)) {
-               sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
-               if (IS_ERR(sbi->s_chksum_driver)) {
-                       ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
-                       ret = PTR_ERR(sbi->s_chksum_driver);
-                       sbi->s_chksum_driver = NULL;
-                       goto failed_mount;
-               }
+       sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
+       if (IS_ERR(sbi->s_chksum_driver)) {
+               ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
+               ret = PTR_ERR(sbi->s_chksum_driver);
+               sbi->s_chksum_driver = NULL;
+               goto failed_mount;
        }
 
        /* Check superblock checksum */
@@ -3659,6 +3666,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        ext4_msg(sb, KERN_INFO, "mounting ext2 file system "
                                 "using the ext4 subsystem");
                else {
+                       /*
+                        * If we're probing be silent, if this looks like
+                        * it's actually an ext[34] filesystem.
+                        */
+                       if (silent && ext4_feature_set_ok(sb, sb_rdonly(sb)))
+                               goto failed_mount;
                        ext4_msg(sb, KERN_ERR, "couldn't mount as ext2 due "
                                 "to feature incompatibilities");
                        goto failed_mount;
@@ -3670,6 +3683,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        ext4_msg(sb, KERN_INFO, "mounting ext3 file system "
                                 "using the ext4 subsystem");
                else {
+                       /*
+                        * If we're probing be silent, if this looks like
+                        * it's actually an ext4 filesystem.
+                        */
+                       if (silent && ext4_feature_set_ok(sb, sb_rdonly(sb)))
+                               goto failed_mount;
                        ext4_msg(sb, KERN_ERR, "couldn't mount as ext3 due "
                                 "to feature incompatibilities");
                        goto failed_mount;
@@ -3711,11 +3730,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                if (ext4_has_feature_inline_data(sb)) {
                        ext4_msg(sb, KERN_ERR, "Cannot use DAX on a filesystem"
                                        " that may contain inline data");
-                       goto failed_mount;
+                       sbi->s_mount_opt &= ~EXT4_MOUNT_DAX;
                }
                err = bdev_dax_supported(sb, blocksize);
-               if (err)
-                       goto failed_mount;
+               if (err) {
+                       ext4_msg(sb, KERN_ERR,
+                               "DAX unsupported by block device. Turning off DAX.");
+                       sbi->s_mount_opt &= ~EXT4_MOUNT_DAX;
+               }
        }
 
        if (ext4_has_feature_encrypt(sb) && es->s_encryption_level) {
@@ -4090,10 +4112,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                 * cope, else JOURNAL_DATA
                 */
                if (jbd2_journal_check_available_features
-                   (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE))
+                   (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
                        set_opt(sb, ORDERED_DATA);
-               else
+                       sbi->s_def_mount_opt |= EXT4_MOUNT_ORDERED_DATA;
+               } else {
                        set_opt(sb, JOURNAL_DATA);
+                       sbi->s_def_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;
+               }
                break;
 
        case EXT4_MOUNT_ORDERED_DATA:
@@ -4837,7 +4862,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
        bool needs_barrier = false;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
+       if (unlikely(ext4_forced_shutdown(sbi)))
                return 0;
 
        trace_ext4_sync_fs(sb, wait);
@@ -5861,5 +5886,6 @@ static void __exit ext4_exit_fs(void)
 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
 MODULE_DESCRIPTION("Fourth Extended Filesystem");
 MODULE_LICENSE("GPL");
+MODULE_SOFTDEP("pre: crc32c");
 module_init(ext4_init_fs)
 module_exit(ext4_exit_fs)