diff --git a/net/9p/client.c b/net/9p/client.c
index 84e087e2414606ce56a3903eaae048ec1a2066ef..553c34e9f296c415e6d20c8e7273dc2c59ecd804 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -64,21 +64,30 @@ static match_table_t tokens = {
  * @options: options string passed from mount
  * @v9ses: existing v9fs session information
  *
+ * Return 0 upon success, -ERRNO upon failure
  */
 
-static void parse_opts(char *options, struct p9_client *clnt)
+static int parse_opts(char *opts, struct p9_client *clnt)
 {
+	char *options;
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
 	int option;
-	int ret;
+	int ret = 0;
 
 	clnt->trans_mod = v9fs_default_trans();
 	clnt->dotu = 1;
 	clnt->msize = 8192;
 
-	if (!options)
-		return;
+	if (!opts)
+		return 0;
+
+	options = kstrdup(opts, GFP_KERNEL);
+	if (!options) {
+		P9_DPRINTK(P9_DEBUG_ERROR,
+				"failed to allocate copy of option string\n");
+		return -ENOMEM;
+	}
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
@@ -86,10 +95,11 @@ static void parse_opts(char *options, struct p9_client *clnt)
 			continue;
 		token = match_token(p, tokens, args);
 		if (token < Opt_trans) {
-			ret = match_int(&args[0], &option);
-			if (ret < 0) {
+			int r = match_int(&args[0], &option);
+			if (r < 0) {
 				P9_DPRINTK(P9_DEBUG_ERROR,
 					"integer field, but no integer?\n");
+				ret = r;
 				continue;
 			}
 		}
@@ -107,6 +117,8 @@ static void parse_opts(char *options, struct p9_client *clnt)
 			continue;
 		}
 	}
+	kfree(options);
+	return ret;
 }
 
 
@@ -138,6 +150,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 	if (!clnt)
 		return ERR_PTR(-ENOMEM);
 
+	clnt->trans = NULL;
 	spin_lock_init(&clnt->lock);
 	INIT_LIST_HEAD(&clnt->fidlist);
 	clnt->fidpool = p9_idpool_create();
@@ -147,7 +160,10 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 		goto error;
 	}
 
-	parse_opts(options, clnt);
+	err = parse_opts(options, clnt);
+	if (err < 0)
+		goto error;
+
 	if (clnt->trans_mod == NULL) {
 		err = -EPROTONOSUPPORT;
 		P9_DPRINTK(P9_DEBUG_ERROR,
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index c6eda999fa7d04ddb6b57a8b5037bf3f03c736fb..97b103b70499d188961e5487429f0abb6fdb75ae 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -1196,35 +1196,46 @@ void p9_conn_cancel(struct p9_conn *m, int err)
 }
 
 /**
- * v9fs_parse_options - parse mount options into session structure
+ * parse_options - parse mount options into session structure
  * @options: options string passed from mount
  * @opts: transport-specific structure to parse options into
  *
+ * Returns 0 upon success, -ERRNO upon failure
  */
 
-static void parse_opts(char *options, struct p9_fd_opts *opts)
+static int parse_opts(char *params, struct p9_fd_opts *opts)
 {
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
 	int option;
+	char *options;
 	int ret;
 
 	opts->port = P9_PORT;
 	opts->rfd = ~0;
 	opts->wfd = ~0;
 
-	if (!options)
-		return;
+	if (!params)
+		return 0;
+
+	options = kstrdup(params, GFP_KERNEL);
+	if (!options) {
+		P9_DPRINTK(P9_DEBUG_ERROR,
+				"failed to allocate copy of option string\n");
+		return -ENOMEM;
+	}
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
+		int r;
 		if (!*p)
 			continue;
 		token = match_token(p, tokens, args);
-		ret = match_int(&args[0], &option);
-		if (ret < 0) {
+		r = match_int(&args[0], &option);
+		if (r < 0) {
 			P9_DPRINTK(P9_DEBUG_ERROR,
 			 "integer field, but no integer?\n");
+			ret = r;
 			continue;
 		}
 		switch (token) {
@@ -1241,6 +1252,8 @@ static void parse_opts(char *options, struct p9_fd_opts *opts)
 			continue;
 		}
 	}
+	kfree(options);
+	return 0;
 }
 
 static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd)
@@ -1430,7 +1443,9 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
 	struct p9_fd_opts opts;
 	struct p9_trans_fd *p;
 
-	parse_opts(args, &opts);
+	err = parse_opts(args, &opts);
+	if (err < 0)
+		return ERR_PTR(err);
 
 	csocket = NULL;
 	trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);