There are some potential resource leaks in error case of erofs_fill_super(), so add proper error handling for it.
Signed-off-by: Chengguang Xu <[email protected]> --- fs/erofs/super.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 0e369494f2f2..06e721bd1c8c 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -369,7 +369,7 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) sb->s_fs_info = sbi; err = erofs_read_superblock(sb); if (err) - return err; + goto free; sb->s_flags |= SB_RDONLY | SB_NOATIME; sb->s_maxbytes = MAX_LFS_FILESIZE; @@ -385,7 +385,7 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) err = erofs_parse_options(sb, data); if (err) - return err; + goto free; if (test_opt(sbi, POSIX_ACL)) sb->s_flags |= SB_POSIXACL; @@ -398,29 +398,44 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) /* get the root inode */ inode = erofs_iget(sb, ROOT_NID(sbi), true); - if (IS_ERR(inode)) - return PTR_ERR(inode); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto free; + } if (!S_ISDIR(inode->i_mode)) { erofs_err(sb, "rootino(nid %llu) is not a directory(i_mode %o)", ROOT_NID(sbi), inode->i_mode); iput(inode); - return -EINVAL; + err = -EINVAL; + goto free; } sb->s_root = d_make_root(inode); - if (!sb->s_root) - return -ENOMEM; + if (!sb->s_root) { + err = -ENOMEM; + goto free; + } erofs_shrinker_register(sb); /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */ err = erofs_init_managed_cache(sb); if (err) - return err; + goto free_root_inode; erofs_info(sb, "mounted with opts: %s, root inode @ nid %llu.", (char *)data, ROOT_NID(sbi)); + return 0; + +free_root_inode: + dput(sb->s_root); + sb->s_root = NULL; + erofs_shrinker_unregister(sb); +free: + kfree(sbi); + sb->s_fs_info = NULL; + return err; } static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, -- 2.20.1
