diff --git a/v9fs/v9fs.c b/v9fs/v9fs.c
index 2ae631a..38cb07f 100644
--- a/v9fs/v9fs.c
+++ b/v9fs/v9fs.c
@@ -76,7 +76,7 @@ static const match_table_t tokens = {
  * Return 0 upon success, -ERRNO upon failure.
  */
 
-static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
+static int v9fs_parse_options(struct v9fs_session_info *v9ses, const char *opts)
 {
 	char *options;
 	substring_t args[MAX_OPT_ARGS];
@@ -85,11 +85,6 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 	char *s, *e;
 	int ret = 0;
 
-	/* setup defaults */
-	v9ses->afid = ~0;
-	v9ses->debug = 0;
-	v9ses->cache = 0;
-
 	if (!opts)
 		return 0;
 
@@ -176,49 +171,74 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 }
 
 /**
- * v9fs_session_init - initialize session
- * @v9ses: session information structure
- * @dev_name: device being mounted
+ * v9fs_session_new - create a new session object
  * @data: options
  *
  */
-
-struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
-		  const char *dev_name, char *data)
+struct v9fs_session_info *v9fs_session_new(const char *data)
 {
-	int retval = -EINVAL;
-	struct p9_fid *fid;
-	int rc;
+	struct v9fs_session_info *v9ses = NULL;
+	int ret = 0;
+
+	v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
+	if (!v9ses)
+		return ERR_PTR(-ENOMEM);
 
 	v9ses->uname = __getname();
-	if (!v9ses->uname)
+	if (!v9ses->uname) {
+		kfree(v9ses);
 		return ERR_PTR(-ENOMEM);
+	}
 
 	v9ses->aname = __getname();
 	if (!v9ses->aname) {
 		__putname(v9ses->uname);
+		kfree(v9ses);
 		return ERR_PTR(-ENOMEM);
 	}
 
+	/* setup defaults */
 	v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER;
 	strcpy(v9ses->uname, V9FS_DEFUSER);
 	strcpy(v9ses->aname, V9FS_DEFANAME);
+
 	v9ses->uid = ~0;
 	v9ses->dfltuid = V9FS_DEFUID;
 	v9ses->dfltgid = V9FS_DEFGID;
+	v9ses->afid = ~0;
+	v9ses->debug = 0;
+	v9ses->cache = 0;
+	v9ses->clnt = NULL;
 
-	rc = v9fs_parse_options(v9ses, data);
-	if (rc < 0) {
-		retval = rc;
-		goto error;
+	ret = v9fs_parse_options(v9ses, data);
+	if (ret < 0) {
+		v9fs_session_close(v9ses);
+		return ERR_PTR(ret);
 	}
 
+	return v9ses;
+}
+
+/**
+ * v9fs_session_init - initialize session
+ * @v9ses: session information structure
+ * @dev_name: device being mounted
+ * @data: options
+ *
+ */
+
+struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
+		  const char *dev_name, char *data)
+{
+	struct p9_fid *fid;
+	int ret = 0;
+
 	v9ses->clnt = p9_client_create(dev_name, data);
 	if (IS_ERR(v9ses->clnt)) {
-		retval = PTR_ERR(v9ses->clnt);
-		v9ses->clnt = NULL;
+		ret = PTR_ERR(v9ses->clnt);
 		P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n");
-		goto error;
+		v9ses->clnt = NULL;
+		return ERR_PTR(ret);
 	}
 
 	if (!v9ses->clnt->dotu)
@@ -229,7 +249,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 	/* for legacy mode, fall back to V9FS_ACCESS_ANY */
 	if (!v9fs_extended(v9ses) &&
 		((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
-
 		v9ses->flags &= ~V9FS_ACCESS_MASK;
 		v9ses->flags |= V9FS_ACCESS_ANY;
 		v9ses->uid = ~0;
@@ -238,10 +257,8 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 	fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0,
 							v9ses->aname);
 	if (IS_ERR(fid)) {
-		retval = PTR_ERR(fid);
-		fid = NULL;
 		P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n");
-		goto error;
+		return ERR_CAST(fid);
 	}
 
 	if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE)
@@ -250,9 +267,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 		fid->uid = ~0;
 
 	return fid;
-
-error:
-	return ERR_PTR(retval);
 }
 
 /**
@@ -270,6 +284,7 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
 
 	__putname(v9ses->uname);
 	__putname(v9ses->aname);
+	kfree(v9ses);
 }
 
 /**
diff --git a/v9fs/v9fs.h b/v9fs/v9fs.h
index 38762bf..c014014 100644
--- a/v9fs/v9fs.h
+++ b/v9fs/v9fs.h
@@ -97,6 +97,7 @@ struct v9fs_session_info {
 
 extern struct dentry *v9fs_debugfs_root;
 
+struct v9fs_session_info *v9fs_session_new(const char *data);
 struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
 									char *);
 void v9fs_session_close(struct v9fs_session_info *v9ses);
diff --git a/v9fs/vfs_inode.c b/v9fs/vfs_inode.c
index 98fcff7..c1f72c5 100644
--- a/v9fs/vfs_inode.c
+++ b/v9fs/vfs_inode.c
@@ -215,7 +215,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 	inode = new_inode(sb);
 	if (!inode) {
 		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	inode->i_mode = mode;
diff --git a/v9fs/vfs_super.c b/v9fs/vfs_super.c
index 8d81f85..a9a9240 100644
--- a/v9fs/vfs_super.c
+++ b/v9fs/vfs_super.c
@@ -79,10 +79,16 @@ static int v9fs_set_super(struct super_block *s, void *data)
  *
  */
 
-static void
+static int
 v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
-		int flags, void *data)
+		int flags, const char *dev_name, void *data)
 {
+	struct inode *inode = NULL;
+	struct dentry *root = NULL;
+	int mode = S_IRWXUGO | S_ISVTX;
+	struct p9_wstat *st = NULL;
+	struct p9_fid *fid;
+
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 	sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
 	sb->s_blocksize = 1 << sb->s_blocksize_bits;
@@ -92,7 +98,39 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
 	sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
 	    MS_NOATIME;
 
+	inode = v9fs_get_inode(sb, S_IFDIR | mode);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	root = d_alloc_root(inode);
+	if (!root) {
+		iput(inode);
+		return -ENOMEM;
+	}
+
+	fid = v9fs_session_init(v9ses, dev_name, data);
+	if (IS_ERR(fid)) {
+		iput(inode);
+		return PTR_ERR(fid);
+	}
+
+	st = p9_client_stat(fid);
+	if (IS_ERR(st)) {
+		iput(inode);
+		p9_client_clunk(fid);
+		return PTR_ERR(st);
+	}
+
+	root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
+	v9fs_stat2inode(st, root->d_inode, sb);
+
+	v9fs_fid_add(root, fid);
+	p9stat_free(st);
+	kfree(st);
+
+	sb->s_root = root;
 	save_mount_options(sb, data);
+	return 0;
 }
 
 /**
@@ -110,81 +148,33 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 		       struct vfsmount *mnt)
 {
 	struct super_block *sb = NULL;
-	struct inode *inode = NULL;
-	struct dentry *root = NULL;
 	struct v9fs_session_info *v9ses = NULL;
-	struct p9_wstat *st = NULL;
-	int mode = S_IRWXUGO | S_ISVTX;
-	struct p9_fid *fid;
-	int retval = 0;
+	int ret = 0;
 
 	P9_DPRINTK(P9_DEBUG_VFS, " \n");
 
-	v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
-	if (!v9ses)
-		return -ENOMEM;
-
-	fid = v9fs_session_init(v9ses, dev_name, data);
-	if (IS_ERR(fid)) {
-		retval = PTR_ERR(fid);
-		goto close_session;
-	}
-
-	st = p9_client_stat(fid);
-	if (IS_ERR(st)) {
-		retval = PTR_ERR(st);
-		goto clunk_fid;
-	}
+	v9ses = v9fs_session_new(data);
+	if (IS_ERR(v9ses))
+		return PTR_ERR(v9ses);
 
 	sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
 	if (IS_ERR(sb)) {
-		retval = PTR_ERR(sb);
-		goto free_stat;
+		v9fs_session_close(v9ses);
+		return PTR_ERR(sb);
 	}
-	v9fs_fill_super(sb, v9ses, flags, data);
 
-	inode = v9fs_get_inode(sb, S_IFDIR | mode);
-	if (IS_ERR(inode)) {
-		retval = PTR_ERR(inode);
-		goto release_sb;
+	if (!sb->s_root) {
+		ret = v9fs_fill_super(sb, v9ses, flags, dev_name, data);
+		if (ret < 0) {
+			deactivate_locked_super(sb);
+			return ret;
+		}
 	}
 
-	root = d_alloc_root(inode);
-	if (!root) {
-		retval = -ENOMEM;
-		goto release_sb;
-	}
-
-	sb->s_root = root;
-	root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
-
-	v9fs_stat2inode(st, root->d_inode, sb);
-
-	v9fs_fid_add(root, fid);
-	p9stat_free(st);
-	kfree(st);
-
-P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
+	P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
+	sb->s_flags |= MS_ACTIVE;
 	simple_set_mnt(mnt, sb);
 	return 0;
-
-free_stat:
-	p9stat_free(st);
-	kfree(st);
-
-clunk_fid:
-	p9_client_clunk(fid);
-
-close_session:
-	v9fs_session_close(v9ses);
-	kfree(v9ses);
-	return retval;
-
-release_sb:
-	p9stat_free(st);
-	kfree(st);
-	deactivate_locked_super(sb);
-	return retval;
 }
 
 /**
@@ -198,13 +188,11 @@ static void v9fs_kill_super(struct super_block *s)
 	struct v9fs_session_info *v9ses = s->s_fs_info;
 
 	P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
-
-	v9fs_dentry_release(s->s_root);	/* clunk root */
-
+	if (s->s_root)
+		v9fs_dentry_release(s->s_root);	/* clunk root */
 	kill_anon_super(s);
 
 	v9fs_session_close(v9ses);
-	kfree(v9ses);
 	s->s_fs_info = NULL;
 	P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
 }
