ext4: add MODULE_SOFTDEP to ensure crc32c is included in the initramfs
[sfrench/cifs-2.6.git] / fs / ext4 / super.c
index 39bf464c35f170c2e77171fc0422997921949883..eb104e8476f040e61253a6676c93e882e5a22314 100644 (file)
@@ -101,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)
@@ -448,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;
@@ -472,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)) {
@@ -507,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)) {
@@ -719,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);
@@ -2019,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' : ',';
 
@@ -2034,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) ||
@@ -2068,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)
@@ -2081,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)
@@ -2333,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: "
@@ -2345,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: "
@@ -2357,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) {
@@ -3490,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 */
@@ -3660,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;
@@ -3671,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;
@@ -4094,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:
@@ -5865,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)