]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/ext4/super.c
Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
[linux.git] / fs / ext4 / super.c
index 6ed4eb81e67437dc2dddbbce8ae9f7f2b59681d1..dd654e53ba3d982d99c05b2336dd4de9132b0978 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/cleancache.h>
 #include <linux/uaccess.h>
 #include <linux/iversion.h>
+#include <linux/unicode.h>
 
 #include <linux/kthread.h>
 #include <linux/freezer.h>
@@ -698,7 +699,7 @@ void __ext4_abort(struct super_block *sb, const char *function,
                        jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
                save_error_info(sb, function, line);
        }
-       if (test_opt(sb, ERRORS_PANIC)) {
+       if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) {
                if (EXT4_SB(sb)->s_journal &&
                  !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
                        return;
@@ -1054,6 +1055,9 @@ 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);
+#ifdef CONFIG_UNICODE
+       utf8_unload(sbi->s_encoding);
+#endif
        kfree(sbi);
 }
 
@@ -1103,13 +1107,16 @@ static int ext4_drop_inode(struct inode *inode)
 {
        int drop = generic_drop_inode(inode);
 
+       if (!drop)
+               drop = fscrypt_drop_inode(inode);
+
        trace_ext4_drop_inode(inode, drop);
        return drop;
 }
 
-static void ext4_i_callback(struct rcu_head *head)
+static void ext4_free_in_core_inode(struct inode *inode)
 {
-       struct inode *inode = container_of(head, struct inode, i_rcu);
+       fscrypt_free_inode(inode);
        kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
@@ -1124,7 +1131,6 @@ static void ext4_destroy_inode(struct inode *inode)
                                true);
                dump_stack();
        }
-       call_rcu(&inode->i_rcu, ext4_i_callback);
 }
 
 static void init_once(void *foo)
@@ -1176,6 +1182,7 @@ void ext4_clear_inode(struct inode *inode)
                EXT4_I(inode)->jinode = NULL;
        }
        fscrypt_put_encryption_info(inode);
+       fsverity_cleanup_inode(inode);
 }
 
 static struct inode *ext4_nfs_get_inode(struct super_block *sb,
@@ -1402,6 +1409,7 @@ static const struct quotactl_ops ext4_qctl_operations = {
 
 static const struct super_operations ext4_sops = {
        .alloc_inode    = ext4_alloc_inode,
+       .free_inode     = ext4_free_in_core_inode,
        .destroy_inode  = ext4_destroy_inode,
        .write_inode    = ext4_write_inode,
        .dirty_inode    = ext4_dirty_inode,
@@ -1750,6 +1758,36 @@ static const struct mount_opts {
        {Opt_err, 0, 0}
 };
 
+#ifdef CONFIG_UNICODE
+static const struct ext4_sb_encodings {
+       __u16 magic;
+       char *name;
+       char *version;
+} ext4_sb_encoding_map[] = {
+       {EXT4_ENC_UTF8_12_1, "utf8", "12.1.0"},
+};
+
+static int ext4_sb_read_encoding(const struct ext4_super_block *es,
+                                const struct ext4_sb_encodings **encoding,
+                                __u16 *flags)
+{
+       __u16 magic = le16_to_cpu(es->s_encoding);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ext4_sb_encoding_map); i++)
+               if (magic == ext4_sb_encoding_map[i].magic)
+                       break;
+
+       if (i >= ARRAY_SIZE(ext4_sb_encoding_map))
+               return -EINVAL;
+
+       *encoding = &ext4_sb_encoding_map[i];
+       *flags = le16_to_cpu(es->s_encoding_flags);
+
+       return 0;
+}
+#endif
+
 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)
@@ -1840,6 +1878,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
        } else if (token == Opt_commit) {
                if (arg == 0)
                        arg = JBD2_DEFAULT_MAX_COMMIT_AGE;
+               else if (arg > INT_MAX / HZ) {
+                       ext4_msg(sb, KERN_ERR,
+                                "Invalid commit interval %d, "
+                                "must be smaller than %d",
+                                arg, INT_MAX / HZ);
+                       return -1;
+               }
                sbi->s_commit_interval = HZ * arg;
        } else if (token == Opt_debug_want_extra_isize) {
                sbi->s_want_extra_isize = arg;
@@ -2706,13 +2751,9 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files)
        loff_t res;
        loff_t upper_limit = MAX_LFS_FILESIZE;
 
-       /* small i_blocks in vfs inode? */
-       if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
-               /*
-                * CONFIG_LBDAF is not enabled implies the inode
-                * i_block represent total blocks in 512 bytes
-                * 32 == size of vfs inode i_blocks * 8
-                */
+       BUILD_BUG_ON(sizeof(blkcnt_t) < sizeof(u64));
+
+       if (!has_huge_files) {
                upper_limit = (1LL << 32) - 1;
 
                /* total blocks in file system block size */
@@ -2753,11 +2794,11 @@ static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
         * number of 512-byte sectors of the file.
         */
 
-       if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
+       if (!has_huge_files) {
                /*
-                * !has_huge_files or CONFIG_LBDAF not enabled implies that
-                * the inode i_block field represents total file blocks in
-                * 2^32 512-byte sectors == size of vfs inode i_blocks * 8
+                * !has_huge_files or implies that the inode i_block field
+                * represents total file blocks in 2^32 512-byte sectors ==
+                * size of vfs inode i_blocks * 8
                 */
                upper_limit = (1LL << 32) - 1;
 
@@ -2880,6 +2921,15 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
                return 0;
        }
 
+#ifndef CONFIG_UNICODE
+       if (ext4_has_feature_casefold(sb)) {
+               ext4_msg(sb, KERN_ERR,
+                        "Filesystem with casefold feature cannot be "
+                        "mounted without CONFIG_UNICODE");
+               return 0;
+       }
+#endif
+
        if (readonly)
                return 1;
 
@@ -2897,18 +2947,6 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
                                ~EXT4_FEATURE_RO_COMPAT_SUPP));
                return 0;
        }
-       /*
-        * Large file size enabled file system can only be mounted
-        * read-write on 32-bit systems if kernel is built with CONFIG_LBDAF
-        */
-       if (ext4_has_feature_huge_file(sb)) {
-               if (sizeof(blkcnt_t) < sizeof(u64)) {
-                       ext4_msg(sb, KERN_ERR, "Filesystem with huge files "
-                                "cannot be mounted RDWR without "
-                                "CONFIG_LBDAF");
-                       return 0;
-               }
-       }
        if (ext4_has_feature_bigalloc(sb) && !ext4_has_feature_extents(sb)) {
                ext4_msg(sb, KERN_ERR,
                         "Can't support bigalloc feature without "
@@ -3513,6 +3551,37 @@ int ext4_calculate_overhead(struct super_block *sb)
        return 0;
 }
 
+static void ext4_clamp_want_extra_isize(struct super_block *sb)
+{
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_super_block *es = sbi->s_es;
+
+       /* determine the minimum size of new large inodes, if present */
+       if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE &&
+           sbi->s_want_extra_isize == 0) {
+               sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+                                                    EXT4_GOOD_OLD_INODE_SIZE;
+               if (ext4_has_feature_extra_isize(sb)) {
+                       if (sbi->s_want_extra_isize <
+                           le16_to_cpu(es->s_want_extra_isize))
+                               sbi->s_want_extra_isize =
+                                       le16_to_cpu(es->s_want_extra_isize);
+                       if (sbi->s_want_extra_isize <
+                           le16_to_cpu(es->s_min_extra_isize))
+                               sbi->s_want_extra_isize =
+                                       le16_to_cpu(es->s_min_extra_isize);
+               }
+       }
+       /* Check if enough inode space is available */
+       if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
+                                                       sbi->s_inode_size) {
+               sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+                                                      EXT4_GOOD_OLD_INODE_SIZE;
+               ext4_msg(sb, KERN_INFO,
+                        "required extra inode space not available");
+       }
+}
+
 static void ext4_set_resv_clusters(struct super_block *sb)
 {
        ext4_fsblk_t resv_clusters;
@@ -3739,6 +3808,43 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                           &journal_ioprio, 0))
                goto failed_mount;
 
+#ifdef CONFIG_UNICODE
+       if (ext4_has_feature_casefold(sb) && !sbi->s_encoding) {
+               const struct ext4_sb_encodings *encoding_info;
+               struct unicode_map *encoding;
+               __u16 encoding_flags;
+
+               if (ext4_has_feature_encrypt(sb)) {
+                       ext4_msg(sb, KERN_ERR,
+                                "Can't mount with encoding and encryption");
+                       goto failed_mount;
+               }
+
+               if (ext4_sb_read_encoding(es, &encoding_info,
+                                         &encoding_flags)) {
+                       ext4_msg(sb, KERN_ERR,
+                                "Encoding requested by superblock is unknown");
+                       goto failed_mount;
+               }
+
+               encoding = utf8_load(encoding_info->version);
+               if (IS_ERR(encoding)) {
+                       ext4_msg(sb, KERN_ERR,
+                                "can't mount with superblock charset: %s-%s "
+                                "not supported by the kernel. flags: 0x%x.",
+                                encoding_info->name, encoding_info->version,
+                                encoding_flags);
+                       goto failed_mount;
+               }
+               ext4_msg(sb, KERN_INFO,"Using encoding defined by superblock: "
+                        "%s-%s with flags 0x%hx", encoding_info->name,
+                        encoding_info->version?:"\b", encoding_flags);
+
+               sbi->s_encoding = encoding;
+               sbi->s_encoding_flags = encoding_flags;
+       }
+#endif
+
        if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
                printk_once(KERN_WARNING "EXT4-fs: Warning: mounting "
                            "with data=journal disables delayed "
@@ -3940,8 +4046,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                               sbi->s_inode_size);
                        goto failed_mount;
                }
-               if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
-                       sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);
+               /*
+                * i_atime_extra is the last extra field available for [acm]times in
+                * struct ext4_inode. Checking for that field should suffice to ensure
+                * we have extra space for all three.
+                */
+               if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
+                       sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
+                       sb->s_time_gran = 1;
+                       sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
+               } else {
+                       sb->s_time_gran = NSEC_PER_SEC;
+                       sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
+               }
+
+               sb->s_time_min = EXT4_TIMESTAMP_MIN;
        }
 
        sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
@@ -4057,8 +4176,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        if (err) {
                ext4_msg(sb, KERN_ERR, "filesystem"
                         " too large to mount safely on this system");
-               if (sizeof(sector_t) < 8)
-                       ext4_msg(sb, KERN_WARNING, "CONFIG_LBDAF not enabled");
                goto failed_mount;
        }
 
@@ -4179,6 +4296,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 #ifdef CONFIG_FS_ENCRYPTION
        sb->s_cop = &ext4_cryptops;
 #endif
+#ifdef CONFIG_FS_VERITY
+       sb->s_vop = &ext4_verityops;
+#endif
 #ifdef CONFIG_QUOTA
        sb->dq_op = &ext4_quota_operations;
        if (ext4_has_feature_quota(sb))
@@ -4238,7 +4358,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                                 "data=, fs mounted w/o journal");
                        goto failed_mount_wq;
                }
-               sbi->s_def_mount_opt &= EXT4_MOUNT_JOURNAL_CHECKSUM;
+               sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM;
                clear_opt(sb, JOURNAL_CHECKSUM);
                clear_opt(sb, DATA_FLAGS);
                sbi->s_journal = NULL;
@@ -4326,6 +4446,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount_wq;
        }
 
+       if (ext4_has_feature_verity(sb) && blocksize != PAGE_SIZE) {
+               ext4_msg(sb, KERN_ERR, "Unsupported blocksize for fs-verity");
+               goto failed_mount_wq;
+       }
+
        if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
            !ext4_has_feature_encrypt(sb)) {
                ext4_set_feature_encrypt(sb);
@@ -4373,6 +4498,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                iput(root);
                goto failed_mount4;
        }
+
+#ifdef CONFIG_UNICODE
+       if (sbi->s_encoding)
+               sb->s_d_op = &ext4_dentry_ops;
+#endif
+
        sb->s_root = d_make_root(root);
        if (!sb->s_root) {
                ext4_msg(sb, KERN_ERR, "get root dentry failed");
@@ -4387,30 +4518,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        } else if (ret)
                goto failed_mount4a;
 
-       /* determine the minimum size of new large inodes, if present */
-       if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE &&
-           sbi->s_want_extra_isize == 0) {
-               sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
-                                                    EXT4_GOOD_OLD_INODE_SIZE;
-               if (ext4_has_feature_extra_isize(sb)) {
-                       if (sbi->s_want_extra_isize <
-                           le16_to_cpu(es->s_want_extra_isize))
-                               sbi->s_want_extra_isize =
-                                       le16_to_cpu(es->s_want_extra_isize);
-                       if (sbi->s_want_extra_isize <
-                           le16_to_cpu(es->s_min_extra_isize))
-                               sbi->s_want_extra_isize =
-                                       le16_to_cpu(es->s_min_extra_isize);
-               }
-       }
-       /* Check if enough inode space is available */
-       if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
-                                                       sbi->s_inode_size) {
-               sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
-                                                      EXT4_GOOD_OLD_INODE_SIZE;
-               ext4_msg(sb, KERN_INFO, "required extra inode space not"
-                        "available");
-       }
+       ext4_clamp_want_extra_isize(sb);
 
        ext4_set_resv_clusters(sb);
 
@@ -4578,9 +4686,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 failed_mount:
        if (sbi->s_chksum_driver)
                crypto_free_shash(sbi->s_chksum_driver);
+
+#ifdef CONFIG_UNICODE
+       utf8_unload(sbi->s_encoding);
+#endif
+
 #ifdef CONFIG_QUOTA
        for (i = 0; i < EXT4_MAXQUOTAS; i++)
-               kfree(sbi->s_qf_names[i]);
+               kfree(get_qf_name(sb, sbi, i));
 #endif
        ext4_blkdev_remove(sbi);
        brelse(bh);
@@ -5194,6 +5307,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
+       ext4_clamp_want_extra_isize(sb);
+
        if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
            test_opt(sb, JOURNAL_CHECKSUM)) {
                ext4_msg(sb, KERN_ERR, "changing journal_checksum "
@@ -6011,6 +6126,10 @@ static int __init ext4_init_fs(void)
                return err;
 
        err = ext4_init_pending();
+       if (err)
+               goto out7;
+
+       err = ext4_init_post_read_processing();
        if (err)
                goto out6;
 
@@ -6052,8 +6171,10 @@ static int __init ext4_init_fs(void)
 out4:
        ext4_exit_pageio();
 out5:
-       ext4_exit_pending();
+       ext4_exit_post_read_processing();
 out6:
+       ext4_exit_pending();
+out7:
        ext4_exit_es();
 
        return err;
@@ -6070,6 +6191,7 @@ static void __exit ext4_exit_fs(void)
        ext4_exit_sysfs();
        ext4_exit_system_zone();
        ext4_exit_pageio();
+       ext4_exit_post_read_processing();
        ext4_exit_es();
        ext4_exit_pending();
 }