summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-07 08:16:50 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 16:39:59 +0200
commitf8201abcb2badce7eaa6a3715f9a228cfd88a453 (patch)
treeb635d8ad39ada141b06884e91ad7de41c44a2f0e /fs
parentMerge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mch... (diff)
downloadlinux-f8201abcb2badce7eaa6a3715f9a228cfd88a453.tar.xz
linux-f8201abcb2badce7eaa6a3715f9a228cfd88a453.zip
ramfs: fix double freeing s_fs_info on failed mount
If ramfs mount fails, s_fs_info will be freed twice in ramfs_fill_super() and ramfs_kill_sb(), leading to kernel oops. Consolidate and beautify the code. Make sure s_fs_info and s_root are in known good states. Acked-by: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ramfs/inode.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index a404fb88e456..3a6b193d8444 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -221,22 +221,23 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
save_mount_options(sb, data);
fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL);
+ sb->s_fs_info = fsi;
if (!fsi) {
err = -ENOMEM;
goto fail;
}
- sb->s_fs_info = fsi;
err = ramfs_parse_options(data, &fsi->mount_opts);
if (err)
goto fail;
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = RAMFS_MAGIC;
- sb->s_op = &ramfs_ops;
- sb->s_time_gran = 1;
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = RAMFS_MAGIC;
+ sb->s_op = &ramfs_ops;
+ sb->s_time_gran = 1;
+
inode = ramfs_get_inode(sb, S_IFDIR | fsi->mount_opts.mode, 0);
if (!inode) {
err = -ENOMEM;
@@ -244,14 +245,16 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
}
root = d_alloc_root(inode);
+ sb->s_root = root;
if (!root) {
err = -ENOMEM;
goto fail;
}
- sb->s_root = root;
+
return 0;
fail:
kfree(fsi);
+ sb->s_fs_info = NULL;
iput(inode);
return err;
}