summaryrefslogtreecommitdiff
path: root/fs/exofs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-11-10 06:26:42 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-12-05 11:20:32 +0300
commitbd5acf3e81ec539c10d0bf116b43297de6a43338 (patch)
tree9e922df07094d86dac4a023b4b6a99bf34271df5 /fs/exofs
parentd1dbff485dc86b1e0e87c96ee032de98a2bbf2b5 (diff)
downloadlinux-bd5acf3e81ec539c10d0bf116b43297de6a43338.tar.xz
exofs_mount(): fix leaks on failure exits
[ Upstream commit 26cb5a328c6b2bda9e859307ce4cfc60df3a2c28 ] ... and don't abuse mount_nodev(), while we are at it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Reviewed-by: David Howells <dhowells@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/exofs')
-rw-r--r--fs/exofs/super.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index 7d61e3fa378c..8fb98bb94237 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -705,21 +705,18 @@ out:
/*
* Read the superblock from the OSD and fill in the fields
*/
-static int exofs_fill_super(struct super_block *sb, void *data, int silent)
+static int exofs_fill_super(struct super_block *sb,
+ struct exofs_mountopt *opts,
+ struct exofs_sb_info *sbi,
+ int silent)
{
struct inode *root;
- struct exofs_mountopt *opts = data;
- struct exofs_sb_info *sbi; /*extended info */
struct osd_dev *od; /* Master device */
struct exofs_fscb fscb; /*on-disk superblock info */
struct ore_comp comp;
unsigned table_count;
int ret;
- sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
- if (!sbi)
- return -ENOMEM;
-
/* use mount options to fill superblock */
if (opts->is_osdname) {
struct osd_dev_info odi = {.systemid_len = 0};
@@ -863,7 +860,9 @@ static struct dentry *exofs_mount(struct file_system_type *type,
int flags, const char *dev_name,
void *data)
{
+ struct super_block *s;
struct exofs_mountopt opts;
+ struct exofs_sb_info *sbi;
int ret;
ret = parse_options(data, &opts);
@@ -872,9 +871,31 @@ static struct dentry *exofs_mount(struct file_system_type *type,
return ERR_PTR(ret);
}
+ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+ if (!sbi) {
+ kfree(opts.dev_name);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ s = sget(type, NULL, set_anon_super, flags, NULL);
+
+ if (IS_ERR(s)) {
+ kfree(opts.dev_name);
+ kfree(sbi);
+ return ERR_CAST(s);
+ }
+
if (!opts.dev_name)
opts.dev_name = dev_name;
- return mount_nodev(type, flags, &opts, exofs_fill_super);
+
+
+ ret = exofs_fill_super(s, &opts, sbi, flags & SB_SILENT ? 1 : 0);
+ if (ret) {
+ deactivate_locked_super(s);
+ return ERR_PTR(ret);
+ }
+ s->s_flags |= SB_ACTIVE;
+ return dget(s->s_root);
}
/*