diff --git a/9p/client.c b/9p/client.c
index 96331d8..da0a1c2 100644
--- a/9p/client.c
+++ b/9p/client.c
@@ -37,91 +37,10 @@
 #include "transport.h"
 #include "protocol.h"
 
-/*
-  * Client Option Parsing (code inspired by NFS code)
-  *  - a little lazy - parse all client options
-  */
-
-enum {
-	Opt_msize,
-	Opt_trans,
-	Opt_legacy,
-	Opt_err,
-};
-
-static const match_table_t tokens = {
-	{Opt_msize, "msize=%u"},
-	{Opt_legacy, "noextend"},
-	{Opt_trans, "trans=%s"},
-	{Opt_err, NULL},
-};
-
 static struct p9_req_t *
 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
 
 /**
- * parse_options - parse mount options into client structure
- * @opts: options string passed from mount
- * @clnt: existing v9fs client information
- *
- * Return 0 upon success, -ERRNO upon failure
- */
-
-static int parse_opts(char *opts, struct p9_client *clnt)
-{
-	char *options;
-	char *p;
-	substring_t args[MAX_OPT_ARGS];
-	int option;
-	int ret = 0;
-
-	clnt->dotu = 1;
-	clnt->msize = 8192;
-
-	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;
-		if (!*p)
-			continue;
-		token = match_token(p, tokens, args);
-		if (token < Opt_trans) {
-			int 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) {
-		case Opt_msize:
-			clnt->msize = option;
-			break;
-		case Opt_trans:
-			clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
-			break;
-		case Opt_legacy:
-			clnt->dotu = 0;
-			break;
-		default:
-			continue;
-		}
-	}
-
-	kfree(options);
-	return ret;
-}
-
-/**
  * p9_tag_alloc - lookup/allocate a request by tag
  * @c: client session to lookup tag within
  * @tag: numeric id for transaction
@@ -659,7 +578,7 @@ error:
 }
 EXPORT_SYMBOL(p9_client_version);
 
-struct p9_client *p9_client_create(const char *dev_name, char *options)
+struct p9_client *p9_client_create(struct p9_client_opts *copts)
 {
 	int err;
 	struct p9_client *clnt;
@@ -669,7 +588,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 	if (!clnt)
 		return ERR_PTR(-ENOMEM);
 
-	clnt->trans_mod = NULL;
+	clnt->dotu = copts->dotu;
+	clnt->msize = copts->msize;
+
 	clnt->trans = NULL;
 	spin_lock_init(&clnt->lock);
 	INIT_LIST_HEAD(&clnt->fidlist);
@@ -682,10 +603,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 
 	p9_tag_init(clnt);
 
-	err = parse_opts(options, clnt);
-	if (err < 0)
-		goto error;
-
+	clnt->trans_mod = copts->transport;
 	if (!clnt->trans_mod)
 		clnt->trans_mod = v9fs_get_default_trans();
 
@@ -699,7 +617,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 	P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
 		clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
 
-	err = clnt->trans_mod->create(clnt, dev_name, options);
+	err = clnt->trans_mod->create(clnt, copts->trans_opts);
 	if (err)
 		goto error;
 
diff --git a/9p/trans_fd.c b/9p/trans_fd.c
index ab8fc37..8d09d65 100644
--- a/9p/trans_fd.c
+++ b/9p/trans_fd.c
@@ -47,20 +47,6 @@
 #define MAXPOLLWADDR	2
 
 /**
- * struct p9_fd_opts - per-transport options
- * @rfd: file descriptor for reading (trans=fd)
- * @wfd: file descriptor for writing (trans=fd)
- * @port: port to connect to (trans=tcp)
- *
- */
-
-struct p9_fd_opts {
-	int rfd;
-	int wfd;
-	u16 port;
-};
-
-/**
  * struct p9_trans_fd - transport state
  * @rd: reference to file to read from
  * @wr: reference of file to write to
@@ -74,23 +60,6 @@ struct p9_trans_fd {
 	struct p9_conn *conn;
 };
 
-/*
-  * Option Parsing (code inspired by NFS code)
-  *  - a little lazy - parse all fd-transport options
-  */
-
-enum {
-	/* Options that take integer arguments */
-	Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
-};
-
-static const match_table_t tokens = {
-	{Opt_port, "port=%u"},
-	{Opt_rfdno, "rfdno=%u"},
-	{Opt_wfdno, "wfdno=%u"},
-	{Opt_err, NULL},
-};
-
 enum {
 	Rworksched = 1,		/* read work scheduled or running */
 	Rpending = 2,		/* can read */
@@ -699,69 +668,6 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
 	return ret;
 }
 
-/**
- * parse_opts - parse mount options into p9_fd_opts structure
- * @params: options string passed from mount
- * @opts: fd transport-specific structure to parse options into
- *
- * Returns 0 upon success, -ERRNO upon failure
- */
-
-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 (!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);
-		if (token != Opt_err) {
-			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) {
-		case Opt_port:
-			opts->port = option;
-			break;
-		case Opt_rfdno:
-			opts->rfd = option;
-			break;
-		case Opt_wfdno:
-			opts->wfd = option;
-			break;
-		default:
-			continue;
-		}
-	}
-	kfree(options);
-	return 0;
-}
-
 static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
 {
 	struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
@@ -877,26 +783,24 @@ static inline int valid_ipaddr4(const char *buf)
 }
 
 static int
-p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
+p9_fd_create_tcp(struct p9_client *client, struct p9_trans_opts *opts)
 {
 	int err;
 	struct socket *csocket;
 	struct sockaddr_in sin_server;
-	struct p9_fd_opts opts;
 	struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
 
-	err = parse_opts(args, &opts);
-	if (err < 0)
-		return err;
-
-	if (valid_ipaddr4(addr) < 0)
+	if (valid_ipaddr4(opts->addr) < 0)
 		return -EINVAL;
 
 	csocket = NULL;
 
+	if (!opts->port)
+		opts->port = P9_PORT;
+
 	sin_server.sin_family = AF_INET;
-	sin_server.sin_addr.s_addr = in_aton(addr);
-	sin_server.sin_port = htons(opts.port);
+	sin_server.sin_addr.s_addr = in_aton(opts->addr);
+	sin_server.sin_port = htons(opts->port);
 	sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
 
 	if (!csocket) {
@@ -911,7 +815,7 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
 	if (err < 0) {
 		P9_EPRINTK(KERN_ERR,
 			"p9_trans_tcp: problem connecting socket to %s\n",
-			addr);
+			opts->addr);
 		goto error;
 	}
 
@@ -939,7 +843,7 @@ error:
 }
 
 static int
-p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
+p9_fd_create_unix(struct p9_client *client, struct p9_trans_opts *opts)
 {
 	int err;
 	struct socket *csocket;
@@ -948,22 +852,22 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
 
 	csocket = NULL;
 
-	if (strlen(addr) > UNIX_PATH_MAX) {
+	if (strlen(opts->addr) > UNIX_PATH_MAX) {
 		P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
-			addr);
+			opts->addr);
 		err = -ENAMETOOLONG;
 		goto error;
 	}
 
 	sun_server.sun_family = PF_UNIX;
-	strcpy(sun_server.sun_path, addr);
+	strcpy(sun_server.sun_path, opts->addr);
 	sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
 	err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
 			sizeof(struct sockaddr_un) - 1, 0);
 	if (err < 0) {
 		P9_EPRINTK(KERN_ERR,
 			"p9_trans_unix: problem connecting socket: %s: %d\n",
-			addr, err);
+			opts->addr, err);
 		goto error;
 	}
 
@@ -990,20 +894,17 @@ error:
 }
 
 static int
-p9_fd_create(struct p9_client *client, const char *addr, char *args)
+p9_fd_create(struct p9_client *client, struct p9_trans_opts *opts)
 {
 	int err;
-	struct p9_fd_opts opts;
 	struct p9_trans_fd *p = NULL; /* this get allocated in p9_fd_open */
 
-	parse_opts(args, &opts);
-
-	if (opts.rfd == ~0 || opts.wfd == ~0) {
+	if (opts->rfd == ~0 || opts->wfd == ~0) {
 		printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
 		return -ENOPROTOOPT;
 	}
 
-	err = p9_fd_open(client, opts.rfd, opts.wfd);
+	err = p9_fd_open(client, opts->rfd, opts->wfd);
 	if (err < 0)
 		goto error;
 
diff --git a/9p/trans_rdma.c b/9p/trans_rdma.c
index 3c4d2cb..bc98e99 100644
--- a/9p/trans_rdma.c
+++ b/9p/trans_rdma.c
@@ -123,103 +123,6 @@ struct p9_rdma_context {
 	};
 };
 
-/**
- * p9_rdma_opts - Collection of mount options
- * @port: port of connection
- * @sq_depth: The requested depth of the SQ. This really doesn't need
- * to be any deeper than the number of threads used in the client
- * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth
- * @timeout: Time to wait in msecs for CM events
- */
-struct p9_rdma_opts {
-	short port;
-	int sq_depth;
-	int rq_depth;
-	long timeout;
-};
-
-/*
- * Option Parsing (code inspired by NFS code)
- */
-enum {
-	/* Options that take integer arguments */
-	Opt_port, Opt_rq_depth, Opt_sq_depth, Opt_timeout, Opt_err,
-};
-
-static match_table_t tokens = {
-	{Opt_port, "port=%u"},
-	{Opt_sq_depth, "sq=%u"},
-	{Opt_rq_depth, "rq=%u"},
-	{Opt_timeout, "timeout=%u"},
-	{Opt_err, NULL},
-};
-
-/**
- * parse_opts - parse mount options into rdma options structure
- * @params: options string passed from mount
- * @opts: rdma transport-specific structure to parse options into
- *
- * Returns 0 upon success, -ERRNO upon failure
- */
-static int parse_opts(char *params, struct p9_rdma_opts *opts)
-{
-	char *p;
-	substring_t args[MAX_OPT_ARGS];
-	int option;
-	char *options;
-	int ret;
-
-	opts->port = P9_PORT;
-	opts->sq_depth = P9_RDMA_SQ_DEPTH;
-	opts->rq_depth = P9_RDMA_RQ_DEPTH;
-	opts->timeout = P9_RDMA_TIMEOUT;
-
-	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);
-		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) {
-		case Opt_port:
-			opts->port = option;
-			break;
-		case Opt_sq_depth:
-			opts->sq_depth = option;
-			break;
-		case Opt_rq_depth:
-			opts->rq_depth = option;
-			break;
-		case Opt_timeout:
-			opts->timeout = option;
-			break;
-		default:
-			continue;
-		}
-	}
-	/* RQ must be at least as large as the SQ */
-	opts->rq_depth = max(opts->rq_depth, opts->sq_depth);
-	kfree(options);
-	return 0;
-}
-
 static int
 p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
 {
@@ -532,10 +435,22 @@ static void rdma_close(struct p9_client *client)
  * alloc_rdma - Allocate and initialize the rdma transport structure
  * @opts: Mount options structure
  */
-static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts)
+static struct p9_trans_rdma *alloc_rdma(struct p9_trans_opts *opts)
 {
 	struct p9_trans_rdma *rdma;
 
+	if (!opts->port)
+		opts->port = P9_PORT;
+
+	if (!opts->sq_depth)
+		opts->sq_depth = P9_RDMA_SQ_DEPTH;
+
+	if (!opts->rq_depth)
+		opts->rq_depth = P9_RDMA_RQ_DEPTH;
+
+	if (!opts->timeout)
+		opts->timeout = P9_RDMA_TIMEOUT;
+
 	rdma = kzalloc(sizeof(struct p9_trans_rdma), GFP_KERNEL);
 	if (!rdma)
 		return NULL;
@@ -560,26 +475,19 @@ static int rdma_cancel(struct p9_client *client, struct p9_req_t *req)
 /**
  * trans_create_rdma - Transport method for creating atransport instance
  * @client: client instance
- * @addr: IP address string
- * @args: Mount options string
+ * @opts: transport options passed through the mount string
  */
 static int
-rdma_create_trans(struct p9_client *client, const char *addr, char *args)
+rdma_create_trans(struct p9_client *client, struct p9_trans_opts *opts)
 {
 	int err;
-	struct p9_rdma_opts opts;
 	struct p9_trans_rdma *rdma;
 	struct rdma_conn_param conn_param;
 	struct ib_qp_init_attr qp_attr;
 	struct ib_device_attr devattr;
 
-	/* Parse the transport specific mount options */
-	err = parse_opts(args, &opts);
-	if (err < 0)
-		return err;
-
 	/* Create and initialize the RDMA transport structure */
-	rdma = alloc_rdma(&opts);
+	rdma = alloc_rdma(opts);
 	if (!rdma)
 		return -ENOMEM;
 
@@ -593,8 +501,8 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
 
 	/* Resolve the server's address */
 	rdma->addr.sin_family = AF_INET;
-	rdma->addr.sin_addr.s_addr = in_aton(addr);
-	rdma->addr.sin_port = htons(opts.port);
+	rdma->addr.sin_addr.s_addr = in_aton(opts->addr);
+	rdma->addr.sin_port = htons(opts->port);
 	err = rdma_resolve_addr(rdma->cm_id, NULL,
 				(struct sockaddr *)&rdma->addr,
 				rdma->timeout);
@@ -620,7 +528,7 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
 	/* Create the Completion Queue */
 	rdma->cq = ib_create_cq(rdma->cm_id->device, cq_comp_handler,
 				cq_event_handler, client,
-				opts.sq_depth + opts.rq_depth + 1, 0);
+				opts->sq_depth + opts->rq_depth + 1, 0);
 	if (IS_ERR(rdma->cq))
 		goto error;
 	ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP);
@@ -645,8 +553,8 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
 	memset(&qp_attr, 0, sizeof qp_attr);
 	qp_attr.event_handler = qp_event_handler;
 	qp_attr.qp_context = client;
-	qp_attr.cap.max_send_wr = opts.sq_depth;
-	qp_attr.cap.max_recv_wr = opts.rq_depth;
+	qp_attr.cap.max_send_wr = opts->sq_depth;
+	qp_attr.cap.max_recv_wr = opts->rq_depth;
 	qp_attr.cap.max_send_sge = P9_RDMA_SEND_SGE;
 	qp_attr.cap.max_recv_sge = P9_RDMA_RECV_SGE;
 	qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
diff --git a/9p/trans_virtio.c b/9p/trans_virtio.c
index 264cd23..1293363 100644
--- a/9p/trans_virtio.c
+++ b/9p/trans_virtio.c
@@ -270,8 +270,7 @@ fail:
 /**
  * p9_virtio_create - allocate a new virtio channel
  * @client: client instance invoking this transport
- * @devname: string identifying the channel to connect to (unused)
- * @args: args passed from sys_mount() for per-transport options (unused)
+ * @opts: v9fs transport-specific mount options (unused)
  *
  * This sets up a transport channel for 9p communication.  Right now
  * we only match the first available channel, but eventually we couldlook up
@@ -288,7 +287,7 @@ fail:
  */
 
 static int
-p9_virtio_create(struct p9_client *client, const char *devname, char *args)
+p9_virtio_create(struct p9_client *client, struct p9_trans_opts *opts)
 {
 	struct virtio_chan *chan = channels;
 	int index = 0;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 4012e07..8962cd1 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -108,6 +108,23 @@ struct p9_req_t {
 };
 
 /**
+ * struct p9_client_opts - per-client mount options
+ *
+ * @msize: max data size negotiated by the protocol
+ * @dotu: extension flags negotiated by the protocol
+ * @transport: transport module associated with this session
+ * @trans_opts: mount options for the transport module
+ *
+ */
+
+struct p9_client_opts {
+	int msize;
+	unsigned char dotu;
+	struct p9_trans_module *transport;
+	struct p9_trans_opts *trans_opts;
+};
+
+/**
  * struct p9_client - per client instance state
  * @lock: protect @fidlist
  * @msize: maximum data size negotiated by protocol
@@ -183,7 +200,7 @@ struct p9_fid {
 };
 
 int p9_client_version(struct p9_client *);
-struct p9_client *p9_client_create(const char *dev_name, char *options);
+struct p9_client *p9_client_create(struct p9_client_opts *);
 void p9_client_destroy(struct p9_client *clnt);
 void p9_client_disconnect(struct p9_client *clnt);
 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 6d5886e..0acfa1f 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -27,6 +27,33 @@
 #define NET_9P_TRANSPORT_H
 
 /**
+ * struct p9_trans_opts - transport-specific mount options
+ *
+ * @addr: endpoint address the transport should connect to
+ * @port: port to connect to (tcp/rdma)
+ * @rfd: file descriptor for reading (fd)
+ * @wfd: file descriptor for writing (fd)
+ * @sq_depth: The requested depth of the SQ. This really doesn't need
+ * to be any deeper than the number of threads used in the client (rdma)
+ * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth
+ * @timeout: Time to wait in msecs for CM events (rdma)
+ *
+ */
+
+struct p9_trans_opts {
+	/* common transport options */
+	char *addr;
+	u16 port;
+	/* fd transport options */
+	int rfd;
+	int wfd;
+	/* rdma transport options */
+	int sq_depth;
+	int rq_depth;
+	int timeout;
+};
+
+/**
  * struct p9_trans_module - transport module interface
  * @list: used to maintain a list of currently available transports
  * @name: the human-readable name of the transport
@@ -49,7 +76,7 @@ struct p9_trans_module {
 	int maxsize;		/* max message size of transport */
 	int def;		/* this transport should be default */
 	struct module *owner;
-	int (*create)(struct p9_client *, const char *, char *);
+	int (*create)(struct p9_client *, struct p9_trans_opts *);
 	void (*close) (struct p9_client *);
 	int (*request) (struct p9_client *, struct p9_req_t *req);
 	int (*cancel) (struct p9_client *, struct p9_req_t *req);
diff --git a/v9fs/v9fs.c b/v9fs/v9fs.c
index 38cb07f..23e14a6 100644
--- a/v9fs/v9fs.c
+++ b/v9fs/v9fs.c
@@ -42,11 +42,14 @@
 
 enum {
 	/* Options that take integer arguments */
-	Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid,
+	Opt_debug, Opt_dfltuid, Opt_dfltgid, 
+	Opt_afid, Opt_msize, Opt_port, 
+	Opt_rfdno, Opt_wfdno, Opt_rq_depth, 
+	Opt_sq_depth, Opt_timeout,
 	/* String options */
 	Opt_uname, Opt_remotename, Opt_trans,
 	/* Options that take no arguments */
-	Opt_nodevmap,
+	Opt_nodevmap, Opt_legacy,
 	/* Cache options */
 	Opt_cache_loose,
 	/* Access options */
@@ -57,21 +60,31 @@ enum {
 
 static const match_table_t tokens = {
 	{Opt_debug, "debug=%x"},
+	{Opt_port, "port=%u"},
+	{Opt_legacy, "noextend"},
+	{Opt_trans, "trans=%s"},
 	{Opt_dfltuid, "dfltuid=%u"},
 	{Opt_dfltgid, "dfltgid=%u"},
 	{Opt_afid, "afid=%u"},
+	{Opt_msize, "msize=%u"},
 	{Opt_uname, "uname=%s"},
 	{Opt_remotename, "aname=%s"},
 	{Opt_nodevmap, "nodevmap"},
 	{Opt_cache_loose, "cache=loose"},
 	{Opt_cache_loose, "loose"},
 	{Opt_access, "access=%s"},
+	{Opt_rfdno, "rfdno=%u"},
+	{Opt_wfdno, "wfdno=%u"},
+	{Opt_sq_depth, "sq=%u"},
+	{Opt_rq_depth, "rq=%u"},
+	{Opt_timeout, "timeout=%u"},
 	{Opt_err, NULL}
 };
 
 /**
  * v9fs_parse_options - parse mount options into session structure
  * @v9ses: existing v9fs session information
+ * @opts: options string passed from mount
  *
  * Return 0 upon success, -ERRNO upon failure.
  */
@@ -84,6 +97,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, const char *opts)
 	int option = 0;
 	char *s, *e;
 	int ret = 0;
+	struct p9_client_opts *copts = v9ses->options;
 
 	if (!opts)
 		return 0;
@@ -117,6 +131,15 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, const char *opts)
 #endif
 			break;
 
+		case Opt_port:
+			copts->trans_opts->port = option;
+			break;
+		case Opt_legacy:
+			copts->dotu = 0;
+			break;
+		case Opt_trans:
+			copts->transport = v9fs_get_trans_by_name(&args[0]);
+			break;
 		case Opt_dfltuid:
 			v9ses->dfltuid = option;
 			break;
@@ -126,6 +149,9 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, const char *opts)
 		case Opt_afid:
 			v9ses->afid = option;
 			break;
+		case Opt_msize:
+			copts->msize = option;
+			break;
 		case Opt_uname:
 			match_strlcpy(v9ses->uname, &args[0], PATH_MAX);
 			break;
@@ -138,7 +164,6 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, const char *opts)
 		case Opt_cache_loose:
 			v9ses->cache = CACHE_LOOSE;
 			break;
-
 		case Opt_access:
 			s = match_strdup(&args[0]);
 			if (!s) {
@@ -161,7 +186,21 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, const char *opts)
 			}
 			kfree(s);
 			break;
-
+		case Opt_rfdno:
+			copts->trans_opts->rfd = option;
+			break;
+		case Opt_wfdno:
+			copts->trans_opts->wfd = option;
+			break;
+		case Opt_sq_depth:
+			copts->trans_opts->sq_depth = option;
+			break;
+		case Opt_rq_depth:
+			copts->trans_opts->rq_depth = option;
+			break;
+		case Opt_timeout:
+			copts->trans_opts->timeout = option;
+			break;
 		default:
 			continue;
 		}
@@ -172,29 +211,49 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, const char *opts)
 
 /**
  * v9fs_session_new - create a new session object
+ * @addr: remote server address
  * @data: options
  *
  */
-struct v9fs_session_info *v9fs_session_new(const char *data)
+struct v9fs_session_info *v9fs_session_new(const char *dev_name, const char *data)
 {
 	struct v9fs_session_info *v9ses = NULL;
+	struct p9_client_opts *opts = NULL;
 	int ret = 0;
 
 	v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
 	if (!v9ses)
 		return ERR_PTR(-ENOMEM);
 
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts) {
+		ret = -ENOMEM;
+		P9_EPRINTK(KERN_ERR,
+			   "failed to allocate the client opts structure\n");
+		goto error;
+	}
+
+	opts->trans_opts = kzalloc(sizeof(struct p9_trans_opts), GFP_KERNEL);
+	if (!opts->trans_opts) {
+		ret = -ENOMEM;
+		kfree(opts);
+		P9_EPRINTK(KERN_ERR,
+			   "failed to allocate trans-specific opts structure\n");
+		goto error;
+	}
+
+	v9ses->options = opts;
 	v9ses->uname = __getname();
 	if (!v9ses->uname) {
-		kfree(v9ses);
-		return ERR_PTR(-ENOMEM);
+		ret = -ENOMEM;
+		goto free_options;
 	}
 
 	v9ses->aname = __getname();
 	if (!v9ses->aname) {
+		ret = -ENOMEM;
 		__putname(v9ses->uname);
-		kfree(v9ses);
-		return ERR_PTR(-ENOMEM);
+		goto free_options;
 	}
 
 	/* setup defaults */
@@ -210,13 +269,36 @@ struct v9fs_session_info *v9fs_session_new(const char *data)
 	v9ses->cache = 0;
 	v9ses->clnt = NULL;
 
+	opts->dotu = 1;
+	opts->msize = 8192;
+	opts->transport = NULL;
+
+	opts->trans_opts->addr = (char *) dev_name;
+	opts->trans_opts->port = 0;
+	opts->trans_opts->rfd = ~0;
+	opts->trans_opts->wfd = ~0;
+
+	opts->trans_opts->sq_depth = 0;
+	opts->trans_opts->rq_depth = 0;
+	opts->trans_opts->timeout = 0;
+
 	ret = v9fs_parse_options(v9ses, data);
-	if (ret < 0) {
-		v9fs_session_close(v9ses);
-		return ERR_PTR(ret);
-	}
+	if (ret < 0)
+		goto free_names;
 
 	return v9ses;
+
+free_names:
+	__putname(v9ses->uname);
+	__putname(v9ses->aname);
+
+free_options:
+	kfree(v9ses->options->trans_opts);
+	kfree(v9ses->options);
+
+error:
+	kfree(v9ses);
+	return ERR_PTR(ret);
 }
 
 /**
@@ -233,7 +315,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 	struct p9_fid *fid;
 	int ret = 0;
 
-	v9ses->clnt = p9_client_create(dev_name, data);
+	v9ses->clnt = p9_client_create(v9ses->options);
 	if (IS_ERR(v9ses->clnt)) {
 		ret = PTR_ERR(v9ses->clnt);
 		P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n");
@@ -284,6 +366,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
 
 	__putname(v9ses->uname);
 	__putname(v9ses->aname);
+	kfree(v9ses->options->trans_opts);
+	kfree(v9ses->options);
 	kfree(v9ses);
 }
 
diff --git a/v9fs/v9fs.h b/v9fs/v9fs.h
index c014014..e0b9e09 100644
--- a/v9fs/v9fs.h
+++ b/v9fs/v9fs.h
@@ -60,7 +60,7 @@ enum p9_cache_modes {
  * @debug: debug level
  * @afid: authentication handle
  * @cache: cache mode of type &p9_cache_modes
- * @options: copy of options string given by user
+ * @options: client option parameters given by user
  * @uname: string user name to mount hierarchy as
  * @aname: mount specifier for remote hierarchy
  * @maxdata: maximum data to be sent/recvd per protocol message
@@ -84,6 +84,7 @@ struct v9fs_session_info {
 	unsigned short debug;
 	unsigned int afid;
 	unsigned int cache;
+	struct p9_client_opts *options;
 
 	char *uname;		/* user name to mount as */
 	char *aname;		/* name of remote hierarchy being mounted */
@@ -97,7 +98,7 @@ struct v9fs_session_info {
 
 extern struct dentry *v9fs_debugfs_root;
 
-struct v9fs_session_info *v9fs_session_new(const char *data);
+struct v9fs_session_info *v9fs_session_new(const char *, const char *);
 struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
 									char *);
 void v9fs_session_close(struct v9fs_session_info *v9ses);
@@ -106,7 +107,6 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses);
 #define V9FS_MAGIC 0x01021997
 
 /* other default globals */
-#define V9FS_PORT	564
 #define V9FS_DEFUSER	"nobody"
 #define V9FS_DEFANAME	""
 #define V9FS_DEFUID	(-2)
diff --git a/v9fs/vfs_super.c b/v9fs/vfs_super.c
index a9a9240..171195a 100644
--- a/v9fs/vfs_super.c
+++ b/v9fs/vfs_super.c
@@ -153,7 +153,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 
 	P9_DPRINTK(P9_DEBUG_VFS, " \n");
 
-	v9ses = v9fs_session_new(data);
+	v9ses = v9fs_session_new(dev_name, data);
 	if (IS_ERR(v9ses))
 		return PTR_ERR(v9ses);
 
