OSDN Git Service

ext4: Allow sb to be NULL in ext4_msg()
authorLukas Czerner <lczerner@redhat.com>
Wed, 27 Oct 2021 14:18:49 +0000 (16:18 +0200)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 9 Dec 2021 19:11:07 +0000 (14:11 -0500)
At the parsing phase of mount in the new mount api sb will not be
available so allow sb to be NULL in ext4_msg and use that in
handle_mount_opt().

Also change return value to appropriate -EINVAL where needed.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Link: https://lore.kernel.org/r/20211027141857.33657-6-lczerner@redhat.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/super.c

index 3d8caf0..877eaca 100644 (file)
@@ -88,7 +88,7 @@ static void ext4_unregister_li_request(struct super_block *sb);
 static void ext4_clear_request_list(void);
 static struct inode *ext4_get_journal_inode(struct super_block *sb,
                                            unsigned int journal_inum);
-static int ext4_validate_options(struct super_block *sb);
+static int ext4_validate_options(struct fs_context *fc);
 
 /*
  * Lock ordering
@@ -915,14 +915,20 @@ void __ext4_msg(struct super_block *sb,
        struct va_format vaf;
        va_list args;
 
-       atomic_inc(&EXT4_SB(sb)->s_msg_count);
-       if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state), "EXT4-fs"))
-               return;
+       if (sb) {
+               atomic_inc(&EXT4_SB(sb)->s_msg_count);
+               if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state),
+                                 "EXT4-fs"))
+                       return;
+       }
 
        va_start(args, fmt);
        vaf.fmt = fmt;
        vaf.va = &args;
-       printk("%sEXT4-fs (%s): %pV\n", prefix, sb->s_id, &vaf);
+       if (sb)
+               printk("%sEXT4-fs (%s): %pV\n", prefix, sb->s_id, &vaf);
+       else
+               printk("%sEXT4-fs: %pV\n", prefix, &vaf);
        va_end(args);
 }
 
@@ -2286,12 +2292,12 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
        switch (token) {
        case Opt_noacl:
        case Opt_nouser_xattr:
-               ext4_msg(sb, KERN_WARNING, deprecated_msg, param->key, "3.5");
+               ext4_msg(NULL, KERN_WARNING, deprecated_msg, param->key, "3.5");
                break;
        case Opt_sb:
                return 1;       /* handled by get_sb_block() */
        case Opt_removed:
-               ext4_msg(sb, KERN_WARNING, "Ignoring removed %s option",
+               ext4_msg(NULL, KERN_WARNING, "Ignoring removed %s option",
                         param->key);
                return 1;
        case Opt_abort:
@@ -2310,7 +2316,7 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
 #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
                sb->s_flags |= SB_INLINECRYPT;
 #else
-               ext4_msg(sb, KERN_ERR, "inline encryption not supported");
+               ext4_msg(NULL, KERN_ERR, "inline encryption not supported");
 #endif
                return 1;
        case Opt_errors:
@@ -2326,22 +2332,22 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                        break;
 
        if (m->token == Opt_err) {
-               ext4_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" "
+               ext4_msg(NULL, KERN_ERR, "Unrecognized mount option \"%s\" "
                         "or missing value", param->key);
-               return -1;
+               return -EINVAL;
        }
 
        if ((m->flags & MOPT_NO_EXT2) && IS_EXT2_SB(sb)) {
-               ext4_msg(sb, KERN_ERR,
+               ext4_msg(NULL, KERN_ERR,
                         "Mount option \"%s\" incompatible with ext2",
                         param->key);
-               return -1;
+               return -EINVAL;
        }
        if ((m->flags & MOPT_NO_EXT3) && IS_EXT3_SB(sb)) {
-               ext4_msg(sb, KERN_ERR,
+               ext4_msg(NULL, KERN_ERR,
                         "Mount option \"%s\" incompatible with ext3",
                         param->key);
-               return -1;
+               return -EINVAL;
        }
 
        if (m->flags & MOPT_EXPLICIT) {
@@ -2350,28 +2356,28 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                } else if (m->mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) {
                        set_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM);
                } else
-                       return -1;
+                       return -EINVAL;
        }
        if (m->flags & MOPT_CLEAR_ERR)
                clear_opt(sb, ERRORS_MASK);
        if (token == Opt_noquota && sb_any_quota_loaded(sb)) {
-               ext4_msg(sb, KERN_ERR, "Cannot change quota "
+               ext4_msg(NULL, KERN_ERR, "Cannot change quota "
                         "options when quota turned on");
-               return -1;
+               return -EINVAL;
        }
 
        if (m->flags & MOPT_NOSUPPORT) {
-               ext4_msg(sb, KERN_ERR, "%s option not supported",
+               ext4_msg(NULL, KERN_ERR, "%s option not supported",
                         param->key);
        } else if (token == Opt_commit) {
                if (result.uint_32 == 0)
                        sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE;
                else if (result.uint_32 > INT_MAX / HZ) {
-                       ext4_msg(sb, KERN_ERR,
+                       ext4_msg(NULL, KERN_ERR,
                                 "Invalid commit interval %d, "
                                 "must be smaller than %d",
                                 result.uint_32, INT_MAX / HZ);
-                       return -1;
+                       return -EINVAL;
                }
                sbi->s_commit_interval = HZ * result.uint_32;
        } else if (token == Opt_debug_want_extra_isize) {
@@ -2379,9 +2385,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                    (result.uint_32 < 4) ||
                    (result.uint_32 >
                     (sbi->s_inode_size - EXT4_GOOD_OLD_INODE_SIZE))) {
-                       ext4_msg(sb, KERN_ERR,
+                       ext4_msg(NULL, KERN_ERR,
                                 "Invalid want_extra_isize %d", result.uint_32);
-                       return -1;
+                       return -EINVAL;
                }
                sbi->s_want_extra_isize = result.uint_32;
        } else if (token == Opt_max_batch_time) {
@@ -2392,10 +2398,10 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                if (result.uint_32 &&
                    (result.uint_32 > (1 << 30) ||
                     !is_power_of_2(result.uint_32))) {
-                       ext4_msg(sb, KERN_ERR,
+                       ext4_msg(NULL, KERN_ERR,
                                 "EXT4-fs: inode_readahead_blks must be "
                                 "0 or a power of 2 smaller than 2^31");
-                       return -1;
+                       return -EINVAL;
                }
                sbi->s_inode_readahead_blks = result.uint_32;
        } else if (token == Opt_init_itable) {
@@ -2414,24 +2420,24 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
        } else if (token == Opt_resuid) {
                uid = make_kuid(current_user_ns(), result.uint_32);
                if (!uid_valid(uid)) {
-                       ext4_msg(sb, KERN_ERR, "Invalid uid value %d",
+                       ext4_msg(NULL, KERN_ERR, "Invalid uid value %d",
                                 result.uint_32);
-                       return -1;
+                       return -EINVAL;
                }
                sbi->s_resuid = uid;
        } else if (token == Opt_resgid) {
                gid = make_kgid(current_user_ns(), result.uint_32);
                if (!gid_valid(gid)) {
-                       ext4_msg(sb, KERN_ERR, "Invalid gid value %d",
+                       ext4_msg(NULL, KERN_ERR, "Invalid gid value %d",
                                 result.uint_32);
-                       return -1;
+                       return -EINVAL;
                }
                sbi->s_resgid = gid;
        } else if (token == Opt_journal_dev) {
                if (is_remount) {
-                       ext4_msg(sb, KERN_ERR,
+                       ext4_msg(NULL, KERN_ERR,
                                 "Cannot specify journal on remount");
-                       return -1;
+                       return -EINVAL;
                }
                ctx->journal_devnum = result.uint_32;
        } else if (token == Opt_journal_path) {
@@ -2440,16 +2446,16 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                int error;
 
                if (is_remount) {
-                       ext4_msg(sb, KERN_ERR,
+                       ext4_msg(NULL, KERN_ERR,
                                 "Cannot specify journal on remount");
-                       return -1;
+                       return -EINVAL;
                }
 
                error = fs_lookup_param(fc, param, 1, &path);
                if (error) {
-                       ext4_msg(sb, KERN_ERR, "error: could not find "
+                       ext4_msg(NULL, KERN_ERR, "error: could not find "
                                 "journal device path");
-                       return -1;
+                       return -EINVAL;
                }
 
                journal_inode = d_inode(path.dentry);
@@ -2457,9 +2463,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                path_put(&path);
        } else if (token == Opt_journal_ioprio) {
                if (result.uint_32 > 7) {
-                       ext4_msg(sb, KERN_ERR, "Invalid journal IO priority"
+                       ext4_msg(NULL, KERN_ERR, "Invalid journal IO priority"
                                 " (must be 0-7)");
-                       return -1;
+                       return -EINVAL;
                }
                ctx->journal_ioprio =
                        IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, result.uint_32);
@@ -2468,11 +2474,11 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
        } else if (m->flags & MOPT_DATAJ) {
                if (is_remount) {
                        if (!sbi->s_journal)
-                               ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
+                               ext4_msg(NULL, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
                        else if (test_opt(sb, DATA_FLAGS) != m->mount_opt) {
-                               ext4_msg(sb, KERN_ERR,
+                               ext4_msg(NULL, KERN_ERR,
                                         "Cannot change data mode on remount");
-                               return -1;
+                               return -EINVAL;
                        }
                } else {
                        clear_opt(sb, DATA_FLAGS);
@@ -2482,12 +2488,12 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
        } else if (m->flags & MOPT_QFMT) {
                if (sb_any_quota_loaded(sb) &&
                    sbi->s_jquota_fmt != m->mount_opt) {
-                       ext4_msg(sb, KERN_ERR, "Cannot change journaled "
+                       ext4_msg(NULL, KERN_ERR, "Cannot change journaled "
                                 "quota options when quota turned on");
-                       return -1;
+                       return -EINVAL;
                }
                if (ext4_has_feature_quota(sb)) {
-                       ext4_msg(sb, KERN_INFO,
+                       ext4_msg(NULL, KERN_INFO,
                                 "Quota format mount options ignored "
                                 "when QUOTA feature is enabled");
                        return 1;
@@ -2504,18 +2510,18 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                            (!(sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
                             (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER))) {
                        fail_dax_change_remount:
-                               ext4_msg(sb, KERN_ERR, "can't change "
+                               ext4_msg(NULL, KERN_ERR, "can't change "
                                         "dax mount option while remounting");
-                               return -1;
+                               return -EINVAL;
                        }
                        if (is_remount &&
                            (test_opt(sb, DATA_FLAGS) ==
                             EXT4_MOUNT_JOURNAL_DATA)) {
-                                   ext4_msg(sb, KERN_ERR, "can't mount with "
+                                   ext4_msg(NULL, KERN_ERR, "can't mount with "
                                             "both data=journal and dax");
-                                   return -1;
+                                   return -EINVAL;
                        }
-                       ext4_msg(sb, KERN_WARNING,
+                       ext4_msg(NULL, KERN_WARNING,
                                "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
                        sbi->s_mount_opt |= EXT4_MOUNT_DAX_ALWAYS;
                        sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
@@ -2541,10 +2547,10 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                        break;
                }
 #else
-               ext4_msg(sb, KERN_INFO, "dax option not supported");
+               ext4_msg(NULL, KERN_INFO, "dax option not supported");
                sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
                sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
-               return -1;
+               return -EINVAL;
 #endif
        } else if (token == Opt_data_err_abort) {
                sbi->s_mount_opt |= m->mount_opt;
@@ -2552,9 +2558,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                sbi->s_mount_opt &= ~m->mount_opt;
        } else if (token == Opt_mb_optimize_scan) {
                if (result.int_32 != 0 && result.int_32 != 1) {
-                       ext4_msg(sb, KERN_WARNING,
+                       ext4_msg(NULL, KERN_WARNING,
                                 "mb_optimize_scan should be set to 0 or 1.");
-                       return -1;
+                       return -EINVAL;
                }
                ctx->mb_optimize_scan = result.int_32;
        } else {
@@ -2567,11 +2573,11 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
                if (m->flags & MOPT_CLEAR)
                        set = !set;
                else if (unlikely(!(m->flags & MOPT_SET))) {
-                       ext4_msg(sb, KERN_WARNING,
+                       ext4_msg(NULL, KERN_WARNING,
                                 "buggy handling of option %s",
                                 param->key);
                        WARN_ON(1);
-                       return -1;
+                       return -EINVAL;
                }
                if (m->flags & MOPT_2) {
                        if (set != 0)
@@ -2639,12 +2645,17 @@ static int parse_options(char *options, struct super_block *sb,
                }
        }
 
-       return ext4_validate_options(sb);
+       ret = ext4_validate_options(&fc);
+       if (ret < 0)
+               return 0;
+
+       return 1;
 }
 
-static int ext4_validate_options(struct super_block *sb)
+static int ext4_validate_options(struct fs_context *fc)
 {
-       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_sb_info *sbi = fc->s_fs_info;
+       struct super_block *sb = sbi->s_sb;
 #ifdef CONFIG_QUOTA
        char *usr_qf_name, *grp_qf_name;
        /*
@@ -2653,9 +2664,9 @@ static int ext4_validate_options(struct super_block *sb)
         * to support legacy quotas in quota files.
         */
        if (test_opt(sb, PRJQUOTA) && !ext4_has_feature_project(sb)) {
-               ext4_msg(sb, KERN_ERR, "Project quota feature not enabled. "
+               ext4_msg(NULL, KERN_ERR, "Project quota feature not enabled. "
                         "Cannot enable project quota enforcement.");
-               return 0;
+               return -EINVAL;
        }
        usr_qf_name = get_qf_name(sb, sbi, USRQUOTA);
        grp_qf_name = get_qf_name(sb, sbi, GRPQUOTA);
@@ -2667,15 +2678,15 @@ static int ext4_validate_options(struct super_block *sb)
                        clear_opt(sb, GRPQUOTA);
 
                if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
-                       ext4_msg(sb, KERN_ERR, "old and new quota "
+                       ext4_msg(NULL, KERN_ERR, "old and new quota "
                                        "format mixing");
-                       return 0;
+                       return -EINVAL;
                }
 
                if (!sbi->s_jquota_fmt) {
-                       ext4_msg(sb, KERN_ERR, "journaled quota format "
+                       ext4_msg(NULL, KERN_ERR, "journaled quota format "
                                        "not specified");
-                       return 0;
+                       return -EINVAL;
                }
        }
 #endif
@@ -2683,11 +2694,12 @@ static int ext4_validate_options(struct super_block *sb)
                int blocksize =
                        BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
                if (blocksize < PAGE_SIZE)
-                       ext4_msg(sb, KERN_WARNING, "Warning: mounting with an "
-                                "experimental mount option 'dioread_nolock' "
-                                "for blocksize < PAGE_SIZE");
+                       ext4_msg(NULL, KERN_WARNING,
+                                "Warning: mounting with an experimental "
+                                "option 'dioread_nolock' for "
+                                "blocksize < PAGE_SIZE");
        }
-       return 1;
+       return 0;
 }
 
 static inline void ext4_show_quota_options(struct seq_file *seq,