diff mbox

[V9fs-developer,9P-FSC,3/3] 9p: Reorganize the mount parsing code.

Message ID 1248897550-16951-4-git-send-email-adkulkar@umail.iu.edu (mailing list archive)
State Rejected
Delegated to: Eric Van Hensbergen
Headers show

Commit Message

Abhishek Kulkarni July 29, 2009, 7:59 p.m. UTC
To compare or test mount parameters for equivalence, it is necessary
to have all the mount parameters apriori so that they can be compared
with the mount options of existing superblocks. This is important
specially when a cache is to be shared between similar mounts so that
we do not end up having two copies of the cache.

Signed-off-by: Abhishek Kulkarni <adkulkar@umail.iu.edu>
---
:100644 100644 96331d8... da0a1c2... M	9p/client.c
:100644 100644 ab8fc37... 8d09d65... M	9p/trans_fd.c
:100644 100644 3c4d2cb... bc98e99... M	9p/trans_rdma.c
:100644 100644 264cd23... 1293363... M	9p/trans_virtio.c
:100644 100644 4012e07... 8962cd1... M	include/net/9p/client.h
:100644 100644 6d5886e... 0acfa1f... M	include/net/9p/transport.h
:100644 100644 38cb07f... 23e14a6... M	v9fs/v9fs.c
:100644 100644 c014014... e0b9e09... M	v9fs/v9fs.h
:100644 100644 a9a9240... 171195a... M	v9fs/vfs_super.c
 9p/client.c                |   94 ++-----------------------------
 9p/trans_fd.c              |  131 +++++-------------------------------------
 9p/trans_rdma.c            |  134 +++++++-------------------------------------
 9p/trans_virtio.c          |    5 +-
 include/net/9p/client.h    |   19 ++++++-
 include/net/9p/transport.h |   29 +++++++++-
 v9fs/v9fs.c                |  112 ++++++++++++++++++++++++++++++++-----
 v9fs/v9fs.h                |    6 +-
 v9fs/vfs_super.c           |    2 +-
 9 files changed, 193 insertions(+), 339 deletions(-)
diff mbox

Patch

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);