Commit d4fab7b2 authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: clean up error handling in __ext4_fill_super()

There were two ways to return an error code; one was via setting the
'err' variable, and the second, if err was zero, was via the 'ret'
variable.  This was both confusing and fragile, and when code was
factored out of __ext4_fill_super(), some of the error codes returned
by the original code was replaced by -EINVAL, and in one case, the
error code was placed by 0, triggering a kernel null pointer
dereference.

Clean this up by removing the 'ret' variable, leaving only one way to
set the error code to be returned, and restore the errno codes that
were returned via the the mount system call as they were before we
started refactoring __ext4_fill_super().
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
parent 3b50d501
...@@ -5196,9 +5196,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5196,9 +5196,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
ext4_fsblk_t logical_sb_block; ext4_fsblk_t logical_sb_block;
struct inode *root; struct inode *root;
int ret = -ENOMEM;
int needs_recovery; int needs_recovery;
int err = 0; int err;
ext4_group_t first_not_zeroed; ext4_group_t first_not_zeroed;
struct ext4_fs_context *ctx = fc->fs_private; struct ext4_fs_context *ctx = fc->fs_private;
int silent = fc->sb_flags & SB_SILENT; int silent = fc->sb_flags & SB_SILENT;
...@@ -5211,8 +5210,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5211,8 +5210,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
sbi->s_sectors_written_start = sbi->s_sectors_written_start =
part_stat_read(sb->s_bdev, sectors[STAT_WRITE]); part_stat_read(sb->s_bdev, sectors[STAT_WRITE]);
/* -EINVAL is default */
ret = -EINVAL;
err = ext4_load_super(sb, &logical_sb_block, silent); err = ext4_load_super(sb, &logical_sb_block, silent);
if (err) if (err)
goto out_fail; goto out_fail;
...@@ -5238,7 +5235,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5238,7 +5235,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
*/ */
sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT; sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
if (ext4_inode_info_init(sb, es)) err = ext4_inode_info_init(sb, es);
if (err)
goto failed_mount; goto failed_mount;
err = parse_apply_sb_mount_options(sb, ctx); err = parse_apply_sb_mount_options(sb, ctx);
...@@ -5254,10 +5252,12 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5254,10 +5252,12 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
ext4_apply_options(fc, sb); ext4_apply_options(fc, sb);
if (ext4_encoding_init(sb, es)) err = ext4_encoding_init(sb, es);
if (err)
goto failed_mount; goto failed_mount;
if (ext4_check_journal_data_mode(sb)) err = ext4_check_journal_data_mode(sb);
if (err)
goto failed_mount; goto failed_mount;
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
...@@ -5266,18 +5266,22 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5266,18 +5266,22 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
/* i_version is always enabled now */ /* i_version is always enabled now */
sb->s_flags |= SB_I_VERSION; sb->s_flags |= SB_I_VERSION;
if (ext4_check_feature_compatibility(sb, es, silent)) err = ext4_check_feature_compatibility(sb, es, silent);
if (err)
goto failed_mount; goto failed_mount;
if (ext4_block_group_meta_init(sb, silent)) err = ext4_block_group_meta_init(sb, silent);
if (err)
goto failed_mount; goto failed_mount;
ext4_hash_info_init(sb); ext4_hash_info_init(sb);
if (ext4_handle_clustersize(sb)) err = ext4_handle_clustersize(sb);
if (err)
goto failed_mount; goto failed_mount;
if (ext4_check_geometry(sb, es)) err = ext4_check_geometry(sb, es);
if (err)
goto failed_mount; goto failed_mount;
timer_setup(&sbi->s_err_report, print_daily_error_info, 0); timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
...@@ -5288,8 +5292,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5288,8 +5292,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
if (err) if (err)
goto failed_mount3; goto failed_mount3;
/* Register extent status tree shrinker */ err = ext4_es_register_shrinker(sbi);
if (ext4_es_register_shrinker(sbi)) if (err)
goto failed_mount3; goto failed_mount3;
sbi->s_stripe = ext4_get_stripe_size(sbi); sbi->s_stripe = ext4_get_stripe_size(sbi);
...@@ -5334,6 +5338,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5334,6 +5338,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
goto failed_mount3a; goto failed_mount3a;
} }
err = -EINVAL;
/* /*
* The first inode we look at is the journal inode. Don't try * The first inode we look at is the journal inode. Don't try
* root first: it may be modified in the journal! * root first: it may be modified in the journal!
...@@ -5385,6 +5390,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5385,6 +5390,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
if (!sbi->s_ea_block_cache) { if (!sbi->s_ea_block_cache) {
ext4_msg(sb, KERN_ERR, ext4_msg(sb, KERN_ERR,
"Failed to create ea_block_cache"); "Failed to create ea_block_cache");
err = -EINVAL;
goto failed_mount_wq; goto failed_mount_wq;
} }
...@@ -5393,6 +5399,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5393,6 +5399,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
if (!sbi->s_ea_inode_cache) { if (!sbi->s_ea_inode_cache) {
ext4_msg(sb, KERN_ERR, ext4_msg(sb, KERN_ERR,
"Failed to create ea_inode_cache"); "Failed to create ea_inode_cache");
err = -EINVAL;
goto failed_mount_wq; goto failed_mount_wq;
} }
} }
...@@ -5427,7 +5434,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5427,7 +5434,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1); alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
if (!EXT4_SB(sb)->rsv_conversion_wq) { if (!EXT4_SB(sb)->rsv_conversion_wq) {
printk(KERN_ERR "EXT4-fs: failed to create workqueue\n"); printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
ret = -ENOMEM; err = -ENOMEM;
goto failed_mount4; goto failed_mount4;
} }
...@@ -5439,28 +5446,28 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5439,28 +5446,28 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
root = ext4_iget(sb, EXT4_ROOT_INO, EXT4_IGET_SPECIAL); root = ext4_iget(sb, EXT4_ROOT_INO, EXT4_IGET_SPECIAL);
if (IS_ERR(root)) { if (IS_ERR(root)) {
ext4_msg(sb, KERN_ERR, "get root inode failed"); ext4_msg(sb, KERN_ERR, "get root inode failed");
ret = PTR_ERR(root); err = PTR_ERR(root);
root = NULL; root = NULL;
goto failed_mount4; goto failed_mount4;
} }
if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck"); ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck");
iput(root); iput(root);
err = -EFSCORRUPTED;
goto failed_mount4; goto failed_mount4;
} }
sb->s_root = d_make_root(root); sb->s_root = d_make_root(root);
if (!sb->s_root) { if (!sb->s_root) {
ext4_msg(sb, KERN_ERR, "get root dentry failed"); ext4_msg(sb, KERN_ERR, "get root dentry failed");
ret = -ENOMEM; err = -ENOMEM;
goto failed_mount4; goto failed_mount4;
} }
ret = ext4_setup_super(sb, es, sb_rdonly(sb)); err = ext4_setup_super(sb, es, sb_rdonly(sb));
if (ret == -EROFS) { if (err == -EROFS) {
sb->s_flags |= SB_RDONLY; sb->s_flags |= SB_RDONLY;
ret = 0; } else if (err)
} else if (ret)
goto failed_mount4a; goto failed_mount4a;
ext4_set_resv_clusters(sb); ext4_set_resv_clusters(sb);
...@@ -5513,7 +5520,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5513,7 +5520,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
ext4_msg(sb, KERN_ERR, ext4_msg(sb, KERN_ERR,
"unable to initialize " "unable to initialize "
"flex_bg meta info!"); "flex_bg meta info!");
ret = -ENOMEM; err = -ENOMEM;
goto failed_mount6; goto failed_mount6;
} }
...@@ -5639,7 +5646,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) ...@@ -5639,7 +5646,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
ext4_blkdev_remove(sbi); ext4_blkdev_remove(sbi);
out_fail: out_fail:
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
return err ? err : ret; return err;
} }
static int ext4_fill_super(struct super_block *sb, struct fs_context *fc) static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment