diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 046cff377f1016741e6db4f0c29f5e109060e2e5..c295ba786edd9082dbd9026ef2324a2d684ea1a3 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -46,10 +46,10 @@ extern struct dentry_operations v9fs_cached_dentry_operations;
 
 struct inode *v9fs_get_inode(struct super_block *sb, int mode);
 ino_t v9fs_qid2ino(struct p9_qid *qid);
-void v9fs_stat2inode(struct p9_stat *, struct inode *, struct super_block *);
+void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
 int v9fs_dir_release(struct inode *inode, struct file *filp);
 int v9fs_file_open(struct inode *inode, struct file *file);
-void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat);
+void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
 void v9fs_dentry_release(struct dentry *);
 int v9fs_uflags2omode(int uflags, int extended);
 
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index d7d0ac5a2ca3ae75f4a23a75a10fe73ad3b74305..276aed625929f7717c4482e7c9898f5a0a449224 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -85,8 +85,8 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 		return -ENOMEM;
 
 	while (1) {
-		err = v9fs_file_readn(filp, statbuf, NULL, fid->rdir_fpos,
-									buflen);
+		err = v9fs_file_readn(filp, statbuf, NULL, buflen,
+								fid->rdir_fpos);
 		if (err <= 0)
 			break;
 
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 3fd28bbafc874d24a98fd471177b885a2e69f517..041c526922845433c5a871f3afed75be7f35b0bd 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -136,7 +136,7 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
 	int n, total;
 	struct p9_fid *fid = filp->private_data;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+	P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid,
 					(long long unsigned) offset, count);
 
 	n = 0;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index e83aa5ebe861d2a8454985875d4f74a6736291a2..e96d84aafbe2af89a1081620373eb0505e00fa00 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -334,7 +334,7 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
 {
 	int err, umode;
 	struct inode *ret;
-	struct p9_stat *st;
+	struct p9_wstat *st;
 
 	ret = NULL;
 	st = p9_client_stat(fid);
@@ -417,6 +417,8 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	struct p9_fid *dfid, *ofid, *fid;
 	struct inode *inode;
 
+	P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
+
 	err = 0;
 	ofid = NULL;
 	fid = NULL;
@@ -424,6 +426,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	dfid = v9fs_fid_clone(dentry->d_parent);
 	if (IS_ERR(dfid)) {
 		err = PTR_ERR(dfid);
+		P9_DPRINTK(P9_DEBUG_VFS, "fid clone failed %d\n", err);
 		dfid = NULL;
 		goto error;
 	}
@@ -432,18 +435,22 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	ofid = p9_client_walk(dfid, 0, NULL, 1);
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
+		P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
 		ofid = NULL;
 		goto error;
 	}
 
 	err = p9_client_fcreate(ofid, name, perm, mode, extension);
-	if (err < 0)
+	if (err < 0) {
+		P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
 		goto error;
+	}
 
 	/* now walk from the parent so we can get unopened fid */
 	fid = p9_client_walk(dfid, 1, &name, 0);
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
+		P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
 		fid = NULL;
 		goto error;
 	} else
@@ -453,6 +460,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
+		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
 		goto error;
 	}
 
@@ -734,7 +742,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	int err;
 	struct v9fs_session_info *v9ses;
 	struct p9_fid *fid;
-	struct p9_stat *st;
+	struct p9_wstat *st;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
 	err = -EPERM;
@@ -815,10 +823,9 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
  */
 
 void
-v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
+v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
 	struct super_block *sb)
 {
-	int n;
 	char ext[32];
 	struct v9fs_session_info *v9ses = sb->s_fs_info;
 
@@ -842,11 +849,7 @@ v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
 		int major = -1;
 		int minor = -1;
 
-		n = stat->extension.len;
-		if (n > sizeof(ext)-1)
-			n = sizeof(ext)-1;
-		memmove(ext, stat->extension.str, n);
-		ext[n] = 0;
+		strncpy(ext, stat->extension, sizeof(ext));
 		sscanf(ext, "%c %u %u", &type, &major, &minor);
 		switch (type) {
 		case 'c':
@@ -857,8 +860,8 @@ v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
 			break;
 		default:
 			P9_DPRINTK(P9_DEBUG_ERROR,
-				"Unknown special type %c (%.*s)\n", type,
-				stat->extension.len, stat->extension.str);
+				"Unknown special type %c %s\n", type,
+				stat->extension);
 		};
 		inode->i_rdev = MKDEV(major, minor);
 	} else
@@ -904,7 +907,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
 
 	struct v9fs_session_info *v9ses;
 	struct p9_fid *fid;
-	struct p9_stat *st;
+	struct p9_wstat *st;
 
 	P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
 	retval = -EPERM;
@@ -926,15 +929,10 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
 	}
 
 	/* copy extension buffer into buffer */
-	if (st->extension.len < buflen)
-		buflen = st->extension.len + 1;
-
-	memmove(buffer, st->extension.str, buflen - 1);
-	buffer[buflen-1] = 0;
+	strncpy(buffer, st->extension, buflen);
 
 	P9_DPRINTK(P9_DEBUG_VFS,
-		"%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len,
-		st->extension.str, buffer);
+		"%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
 
 	retval = buflen;
 
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index bf59c3960494c76a91bb3b0809be897166725852..d6cb1a0ca724d772e2d8bec5093ea621bbe8d864 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -111,7 +111,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 	struct inode *inode = NULL;
 	struct dentry *root = NULL;
 	struct v9fs_session_info *v9ses = NULL;
-	struct p9_stat *st = NULL;
+	struct p9_wstat *st = NULL;
 	int mode = S_IRWXUGO | S_ISVTX;
 	uid_t uid = current->fsuid;
 	gid_t gid = current->fsgid;
@@ -161,10 +161,14 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 
 	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, " return simple set mount\n");
 	return simple_set_mnt(mnt, sb);
 
 release_sb:
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 46d0b8f8e5eca1474041d479dfa877667fad4d38..56c15aee6e61d18e8710e4ee40843de41b613f65 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -39,6 +39,7 @@
  * @P9_DEBUG_TRANS: transport tracing
  * @P9_DEBUG_SLABS: memory management tracing
  * @P9_DEBUG_FCALL: verbose dump of protocol messages
+ * @P9_DEBUG_FID: fid allocation/deallocation tracking
  *
  * These flags are passed at mount time to turn on various levels of
  * verbosity and tracing which will be output to the system logs.
@@ -53,13 +54,17 @@ enum p9_debug_flags {
 	P9_DEBUG_TRANS =	(1<<6),
 	P9_DEBUG_SLABS =      	(1<<7),
 	P9_DEBUG_FCALL =	(1<<8),
+	P9_DEBUG_FID =		(1<<9),
 };
 
 extern unsigned int p9_debug_level;
 
 #define P9_DPRINTK(level, format, arg...) \
 do {  \
-	if ((p9_debug_level & level) == level) \
+	if (level == P9_DEBUG_9P) \
+		printk(KERN_NOTICE "(%8.8d) " \
+		format , task_pid_nr(current) , ## arg); \
+	else if ((p9_debug_level & level) == level) \
 		printk(KERN_NOTICE "-- %s (%d): " \
 		format , __func__, task_pid_nr(current) , ## arg); \
 } while (0)
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 475ef5cf1644d97b9b8be2a3c2f35e3adb62c283..1e49b4d1030b7a15d14f2491b9e2d1538fb387e1 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -77,6 +77,7 @@ enum p9_req_status_t {
  * struct p9_req_t - request slots
  * @status: status of this request slot
  * @t_err: transport error
+ * @flush_tag: tag of request being flushed (for flush requests)
  * @wq: wait_queue for the client to block on for this request
  * @tc: the request fcall structure
  * @rc: the response fcall structure
@@ -97,10 +98,10 @@ enum p9_req_status_t {
 struct p9_req_t {
 	int status;
 	int t_err;
+	u16 flush_tag;
 	wait_queue_head_t *wq;
 	struct p9_fcall *tc;
 	struct p9_fcall *rc;
-	u16 flush_tag;
 	void *aux;
 
 	struct list_head req_list;
@@ -199,10 +200,12 @@ int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
 							u64 offset, u32 count);
 int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
 							u64 offset, u32 count);
-struct p9_stat *p9_client_stat(struct p9_fid *fid);
+struct p9_wstat *p9_client_stat(struct p9_fid *fid);
 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
 
 struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
 void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
 
+void p9stat_free(struct p9_wstat *);
+
 #endif /* NET_9P_CLIENT_H */
diff --git a/net/9p/client.c b/net/9p/client.c
index 6004fded668267408a65c6862809cb6c40c46e54..2a166bfb95a34192ed92547acb68373e0e2a2866 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -35,6 +35,7 @@
 #include <linux/parser.h>
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
+#include "protocol.h"
 
 /*
   * Client Option Parsing (code inspired by NFS code)
@@ -55,8 +56,8 @@ static const match_table_t tokens = {
 	{Opt_err, NULL},
 };
 
-static int
-p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc);
+static struct p9_req_t *
+p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
 
 /**
  * v9fs_parse_options - parse mount options into session structure
@@ -138,10 +139,11 @@ static int parse_opts(char *opts, struct p9_client *clnt)
  *
  */
 
-struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
+static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
 {
 	unsigned long flags;
 	int row, col;
+	struct p9_req_t *req;
 
 	/* This looks up the original request by tag so we know which
 	 * buffer to read the data into */
@@ -157,19 +159,11 @@ struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
 
 			if (!c->reqs[row]) {
 				printk(KERN_ERR "Couldn't grow tag array\n");
-				BUG();
+				return ERR_PTR(-ENOMEM);
 			}
 			for (col = 0; col < P9_ROW_MAXTAG; col++) {
 				c->reqs[row][col].status = REQ_STATUS_IDLE;
-				c->reqs[row][col].flush_tag = P9_NOTAG;
-				c->reqs[row][col].wq = kmalloc(
-					sizeof(wait_queue_head_t), GFP_ATOMIC);
-				if (!c->reqs[row][col].wq) {
-					printk(KERN_ERR
-						"Couldn't grow tag array\n");
-					BUG();
-				}
-				init_waitqueue_head(c->reqs[row][col].wq);
+				c->reqs[row][col].tc = NULL;
 			}
 			c->max_tag += P9_ROW_MAXTAG;
 		}
@@ -178,12 +172,39 @@ struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
 	row = tag / P9_ROW_MAXTAG;
 	col = tag % P9_ROW_MAXTAG;
 
-	c->reqs[row][col].status = REQ_STATUS_ALLOC;
-	c->reqs[row][col].flush_tag = P9_NOTAG;
+	req = &c->reqs[row][col];
+	if (!req->tc) {
+		req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
+		if (!req->wq) {
+			printk(KERN_ERR "Couldn't grow tag array\n");
+			return ERR_PTR(-ENOMEM);
+		}
+		init_waitqueue_head(req->wq);
+		req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
+								GFP_KERNEL);
+		req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
+								GFP_KERNEL);
+		if ((!req->tc) || (!req->rc)) {
+			printk(KERN_ERR "Couldn't grow tag array\n");
+			kfree(req->tc);
+			kfree(req->rc);
+			return ERR_PTR(-ENOMEM);
+		}
+		req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
+		req->tc->capacity = c->msize;
+		req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
+		req->rc->capacity = c->msize;
+	}
+
+	p9pdu_reset(req->tc);
+	p9pdu_reset(req->rc);
+
+	req->flush_tag = 0;
+	req->tc->tag = tag-1;
+	req->status = REQ_STATUS_ALLOC;
 
 	return &c->reqs[row][col];
 }
-EXPORT_SYMBOL(p9_tag_alloc);
 
 /**
  * p9_tag_lookup - lookup a request by tag
@@ -264,43 +285,16 @@ static void p9_tag_cleanup(struct p9_client *c)
 
 	/* free requests associated with tags */
 	for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
-		for (col = 0; col < P9_ROW_MAXTAG; col++)
+		for (col = 0; col < P9_ROW_MAXTAG; col++) {
 			kfree(c->reqs[row][col].wq);
+			kfree(c->reqs[row][col].tc);
+			kfree(c->reqs[row][col].rc);
+		}
 		kfree(c->reqs[row]);
 	}
 	c->max_tag = 0;
 }
 
-/**
- * p9_client_flush - flush (cancel) a request
- * c: client state
- * req: request to cancel
- *
- * This sents a flush for a particular requests and links
- * the flush request to the original request.  The current
- * code only supports a single flush request although the protocol
- * allows for multiple flush requests to be sent for a single request.
- *
- */
-
-static int p9_client_flush(struct p9_client *c, struct p9_req_t *req)
-{
-	struct p9_fcall *tc, *rc = NULL;
-	int err;
-
-	P9_DPRINTK(P9_DEBUG_9P, "client %p tag %d\n", c, req->tc->tag);
-
-	tc = p9_create_tflush(req->tc->tag);
-	if (IS_ERR(tc))
-		return PTR_ERR(tc);
-
-	err = p9_client_rpc(c, tc, &rc);
-
-	/* we don't free anything here because RPC isn't complete */
-
-	return err;
-}
-
 /**
  * p9_free_req - free a request and clean-up as necessary
  * c: client state
@@ -308,15 +302,17 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *req)
  *
  */
 
-void p9_free_req(struct p9_client *c, struct p9_req_t *r)
+static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
 {
-	r->flush_tag = P9_NOTAG;
+	int tag = r->tc->tag;
+	P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
+
 	r->status = REQ_STATUS_IDLE;
-	if (r->tc->tag != P9_NOTAG && p9_idpool_check(r->tc->tag, c->tagpool))
-		p9_idpool_put(r->tc->tag, c->tagpool);
+	if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
+		p9_idpool_put(tag, c->tagpool);
 
 	/* if this was a flush request we have to free response fcall */
-	if (r->tc->id == P9_TFLUSH) {
+	if (r->rc->id == P9_RFLUSH) {
 		kfree(r->tc);
 		kfree(r->rc);
 	}
@@ -333,30 +329,28 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
 	struct p9_req_t *other_req;
 	unsigned long flags;
 
-	P9_DPRINTK(P9_DEBUG_MUX, ": %d\n", req->tc->tag);
+	P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
 
 	if (req->status == REQ_STATUS_ERROR)
 		wake_up(req->wq);
 
-	if (req->tc->id == P9_TFLUSH) { /* flush receive path */
-		P9_DPRINTK(P9_DEBUG_MUX, "flush: %d\n", req->tc->tag);
+	if (req->flush_tag) { 			/* flush receive path */
+		P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag);
 		spin_lock_irqsave(&c->lock, flags);
-		other_req = p9_tag_lookup(c, req->tc->params.tflush.oldtag);
-		if (other_req->flush_tag != req->tc->tag) /* stale flush */
+		other_req = p9_tag_lookup(c, req->flush_tag);
+		if (other_req->status != REQ_STATUS_FLSH) /* stale flush */
 			spin_unlock_irqrestore(&c->lock, flags);
 		else {
-			BUG_ON(other_req->status != REQ_STATUS_FLSH);
 			other_req->status = REQ_STATUS_FLSHD;
 			spin_unlock_irqrestore(&c->lock, flags);
 			wake_up(other_req->wq);
 		}
 		p9_free_req(c, req);
 	} else { 				/* normal receive path */
-		P9_DPRINTK(P9_DEBUG_MUX, "normal: %d\n", req->tc->tag);
+		P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag);
 		spin_lock_irqsave(&c->lock, flags);
 		if (req->status != REQ_STATUS_FLSHD)
 			req->status = REQ_STATUS_RCVD;
-		req->flush_tag = P9_NOTAG;
 		spin_unlock_irqrestore(&c->lock, flags);
 		wake_up(req->wq);
 		P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
@@ -364,29 +358,165 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
 }
 EXPORT_SYMBOL(p9_client_cb);
 
+/**
+ * p9_parse_header - parse header arguments out of a packet
+ * @pdu: packet to parse
+ * @size: size of packet
+ * @type: type of request
+ * @tag: tag of packet
+ * @rewind: set if we need to rewind offset afterwards
+ */
+
+int
+p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
+								int rewind)
+{
+	int8_t r_type;
+	int16_t r_tag;
+	int32_t r_size;
+	int offset = pdu->offset;
+	int err;
+
+	pdu->offset = 0;
+	if (pdu->size == 0)
+		pdu->size = 7;
+
+	err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
+	if (err)
+		goto rewind_and_exit;
+
+	pdu->size = r_size;
+	pdu->id = r_type;
+	pdu->tag = r_tag;
+
+	P9_DPRINTK(P9_DEBUG_MUX, "pdu: type: %d tag: %d size=%d offset=%d\n",
+				pdu->id, pdu->tag, pdu->size, pdu->offset);
+
+	if (type)
+		*type = r_type;
+	if (tag)
+		*tag = r_tag;
+	if (size)
+		*size = r_size;
+
+
+rewind_and_exit:
+	if (rewind)
+		pdu->offset = offset;
+	return err;
+}
+EXPORT_SYMBOL(p9_parse_header);
+
+/**
+ * p9_check_errors - check 9p packet for error return and process it
+ * @c: current client instance
+ * @req: request to parse and check for error conditions
+ *
+ * returns error code if one is discovered, otherwise returns 0
+ *
+ * this will have to be more complicated if we have multiple
+ * error packet types
+ */
+
+static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
+{
+	int8_t type;
+	int err;
+
+	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
+	if (err) {
+		P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
+		return err;
+	}
+
+	if (type == P9_RERROR) {
+		int ecode;
+		char *ename;
+
+		err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
+		if (err) {
+			P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
+									err);
+			return err;
+		}
+
+		if (c->dotu)
+			err = -ecode;
+
+		if (!err) {
+			err = p9_errstr2errno(ename, strlen(ename));
+
+			/* string match failed */
+			if (!err)
+				err = -ESERVERFAULT;
+		}
+
+		P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
+
+		kfree(ename);
+	} else
+		err = 0;
+
+	return err;
+}
+
+/**
+ * p9_client_flush - flush (cancel) a request
+ * c: client state
+ * req: request to cancel
+ *
+ * This sents a flush for a particular requests and links
+ * the flush request to the original request.  The current
+ * code only supports a single flush request although the protocol
+ * allows for multiple flush requests to be sent for a single request.
+ *
+ */
+
+static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
+{
+	struct p9_req_t *req;
+	int16_t oldtag;
+	int err;
+
+	err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
+	if (err)
+		return err;
+
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
+
+	req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
+
+	req->flush_tag = oldtag;
+
+	/* we don't free anything here because RPC isn't complete */
+	return 0;
+}
+
 /**
  * p9_client_rpc - issue a request and wait for a response
  * @c: client session
- * @tc: &p9_fcall request to transmit
- * @rc: &p9_fcall to put reponse into
+ * @type: type of request
+ * @fmt: protocol format string (see protocol.c)
  *
- * Returns 0 on success, error code on failure
+ * Returns request structure (which client must free using p9_free_req)
  */
 
-static int
-p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
+static struct p9_req_t *
+p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
 {
-	int tag, err, size;
-	char *rdata;
+	va_list ap;
+	int tag, err;
 	struct p9_req_t *req;
 	unsigned long flags;
 	int sigpending;
 	int flushed = 0;
 
-	P9_DPRINTK(P9_DEBUG_9P, "client %p tc %p rc %p\n", c, tc, rc);
+	P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
 
 	if (c->status != Connected)
-		return -EIO;
+		return ERR_PTR(-EIO);
 
 	if (signal_pending(current)) {
 		sigpending = 1;
@@ -395,50 +525,22 @@ p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
 		sigpending = 0;
 
 	tag = P9_NOTAG;
-	if (tc->id != P9_TVERSION) {
+	if (type != P9_TVERSION) {
 		tag = p9_idpool_get(c->tagpool);
 		if (tag < 0)
-			return -ENOMEM;
+			return ERR_PTR(-ENOMEM);
 	}
 
 	req = p9_tag_alloc(c, tag);
+	if (IS_ERR(req))
+		return req;
 
-	/* if this is a flush request, backlink flush request now to
-	 * avoid race conditions later. */
-	if (tc->id == P9_TFLUSH) {
-		struct p9_req_t *other_req =
-				p9_tag_lookup(c, tc->params.tflush.oldtag);
-		if (other_req->status == REQ_STATUS_FLSH)
-			other_req->flush_tag = tag;
-	}
-
-	p9_set_tag(tc, tag);
-
-	/*
-	 * if client passed in a pre-allocated response fcall struct
-	 * then we just use that, otherwise we allocate one.
-	 */
-
-	if (rc == NULL)
-		req->rc = NULL;
-	else
-		req->rc = *rc;
-	if (req->rc == NULL) {
-		req->rc = kmalloc(sizeof(struct p9_fcall) + c->msize,
-								GFP_KERNEL);
-		if (!req->rc) {
-			err = -ENOMEM;
-			p9_idpool_put(tag, c->tagpool);
-			p9_free_req(c, req);
-			goto reterr;
-		}
-		*rc = req->rc;
-	}
-
-	rdata = (char *)req->rc+sizeof(struct p9_fcall);
-
-	req->tc = tc;
-	P9_DPRINTK(P9_DEBUG_9P, "request: tc: %p rc: %p\n", req->tc, req->rc);
+	/* marshall the data */
+	p9pdu_prepare(req->tc, tag, type);
+	va_start(ap, fmt);
+	err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap);
+	va_end(ap);
+	p9pdu_finalize(req->tc);
 
 	err = c->trans_mod->request(c, req);
 	if (err < 0) {
@@ -447,28 +549,28 @@ p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
 	}
 
 	/* if it was a flush we just transmitted, return our tag */
-	if (tc->id == P9_TFLUSH)
-		return 0;
+	if (type == P9_TFLUSH)
+		return req;
 again:
-	P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d\n", req->wq, tag);
+	P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
 	err = wait_event_interruptible(*req->wq,
 						req->status >= REQ_STATUS_RCVD);
-	P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d returned %d (flushed=%d)\n",
+	P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n",
 						req->wq, tag, err, flushed);
 
 	if (req->status == REQ_STATUS_ERROR) {
-		P9_DPRINTK(P9_DEBUG_9P, "req_status error %d\n", req->t_err);
+		P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
 		err = req->t_err;
 	} else if (err == -ERESTARTSYS && flushed) {
-		P9_DPRINTK(P9_DEBUG_9P, "flushed - going again\n");
+		P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n");
 		goto again;
 	} else if (req->status == REQ_STATUS_FLSHD) {
-		P9_DPRINTK(P9_DEBUG_9P, "flushed - erestartsys\n");
+		P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n");
 		err = -ERESTARTSYS;
 	}
 
 	if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) {
-		P9_DPRINTK(P9_DEBUG_9P, "flushing\n");
+		P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
 		spin_lock_irqsave(&c->lock, flags);
 		if (req->status == REQ_STATUS_SENT)
 			req->status = REQ_STATUS_FLSH;
@@ -493,42 +595,17 @@ p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
 	if (err < 0)
 		goto reterr;
 
-	size = le32_to_cpu(*(__le32 *) rdata);
-
-	err = p9_deserialize_fcall(rdata, size, req->rc, c->dotu);
-	if (err < 0) {
-		P9_DPRINTK(P9_DEBUG_9P,
-			"9p debug: client rpc deserialize returned %d\n", err);
-		goto reterr;
+	err = p9_check_errors(c, req);
+	if (!err) {
+		P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type);
+		return req;
 	}
 
-	if (req->rc->id == P9_RERROR) {
-		int ecode = req->rc->params.rerror.errno;
-		struct p9_str *ename = &req->rc->params.rerror.error;
-
-		P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
-								ename->str);
-
-		if (c->dotu)
-			err = -ecode;
-
-		if (!err) {
-			err = p9_errstr2errno(ename->str, ename->len);
-
-			/* string match failed */
-			if (!err) {
-				PRINT_FCALL_ERROR("unknown error", req->rc);
-				err = -ESERVERFAULT;
-			}
-		}
-	} else
-		err = 0;
-
 reterr:
+	P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type,
+									err);
 	p9_free_req(c, req);
-
-	P9_DPRINTK(P9_DEBUG_9P, "returning %d\n", err);
-	return err;
+	return ERR_PTR(err);
 }
 
 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
@@ -536,7 +613,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 	int err;
 	struct p9_fid *fid;
 
-	P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+	P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
 	fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
 	if (!fid)
 		return ERR_PTR(-ENOMEM);
@@ -569,7 +646,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
 {
 	struct p9_client *clnt;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
 	clnt = fid->clnt;
 	p9_idpool_put(fid->fid, clnt->fidpool);
 	spin_lock(&clnt->lock);
@@ -578,49 +655,46 @@ static void p9_fid_destroy(struct p9_fid *fid)
 	kfree(fid);
 }
 
-static int p9_client_version(struct p9_client *clnt)
+int p9_client_version(struct p9_client *c)
 {
 	int err = 0;
-	struct p9_fcall *tc, *rc;
-	struct p9_str *version;
+	struct p9_req_t *req;
+	char *version;
+	int msize;
 
-	P9_DPRINTK(P9_DEBUG_9P, "%p\n", clnt);
-	err = 0;
-	tc = NULL;
-	rc = NULL;
-
-	tc = p9_create_tversion(clnt->msize,
-					clnt->dotu ? "9P2000.u" : "9P2000");
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
-		goto error;
-	}
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n",
+							c->msize, c->dotu);
+	req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize,
+				c->dotu ? "9P2000.u" : "9P2000");
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
-	err = p9_client_rpc(clnt, tc, &rc);
-	if (err)
+	err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version);
+	if (err) {
+		P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
 		goto error;
+	}
 
-	version = &rc->params.rversion.version;
-	if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8))
-		clnt->dotu = 1;
-	else if (version->len == 6 && !memcmp(version->str, "9P2000", 6))
-		clnt->dotu = 0;
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
+	if (!memcmp(version, "9P2000.u", 8))
+		c->dotu = 1;
+	else if (!memcmp(version, "9P2000", 6))
+		c->dotu = 0;
 	else {
 		err = -EREMOTEIO;
 		goto error;
 	}
 
-	if (rc->params.rversion.msize < clnt->msize)
-		clnt->msize = rc->params.rversion.msize;
+	if (msize < c->msize)
+		c->msize = msize;
 
 error:
-	kfree(tc);
-	kfree(rc);
+	kfree(version);
+	p9_free_req(c, req);
 
 	return err;
 }
-EXPORT_SYMBOL(p9_client_auth);
+EXPORT_SYMBOL(p9_client_version);
 
 struct p9_client *p9_client_create(const char *dev_name, char *options)
 {
@@ -656,7 +730,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 		goto error;
 	}
 
-	P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
+	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);
@@ -682,7 +756,7 @@ void p9_client_destroy(struct p9_client *clnt)
 {
 	struct p9_fid *fid, *fidptr;
 
-	P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+	P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt);
 
 	if (clnt->trans_mod)
 		clnt->trans_mod->close(clnt);
@@ -712,14 +786,13 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
 	char *uname, u32 n_uname, char *aname)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
+	struct p9_req_t *req;
 	struct p9_fid *fid;
+	struct p9_qid qid;
 
-	P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n",
-		clnt, afid?afid->fid:-1, uname, aname);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
+					afid ? afid->fid : -1, uname, aname);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 
 	fid = p9_fid_create(clnt);
 	if (IS_ERR(fid)) {
@@ -728,73 +801,75 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
 		goto error;
 	}
 
-	tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname,
-		n_uname, clnt->dotu);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
+	req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
+			afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
 		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
-	if (err)
+	err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
+	if (err) {
+		p9_free_req(clnt, req);
 		goto error;
+	}
 
-	memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid));
-	kfree(tc);
-	kfree(rc);
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
+					qid.type, qid.path, qid.version);
+
+	memmove(&fid->qid, &qid, sizeof(struct p9_qid));
+
+	p9_free_req(clnt, req);
 	return fid;
 
 error:
-	kfree(tc);
-	kfree(rc);
 	if (fid)
 		p9_fid_destroy(fid);
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL(p9_client_attach);
 
-struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
-	u32 n_uname, char *aname)
+struct p9_fid *
+p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
-	struct p9_fid *fid;
+	struct p9_req_t *req;
+	struct p9_qid qid;
+	struct p9_fid *afid;
 
-	P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname,
-									aname);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 
-	fid = p9_fid_create(clnt);
-	if (IS_ERR(fid)) {
-		err = PTR_ERR(fid);
-		fid = NULL;
+	afid = p9_fid_create(clnt);
+	if (IS_ERR(afid)) {
+		err = PTR_ERR(afid);
+		afid = NULL;
 		goto error;
 	}
 
-	tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
+	req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
+			afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
 		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
-	if (err)
+	err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
+	if (err) {
+		p9_free_req(clnt, req);
 		goto error;
+	}
 
-	memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid));
-	kfree(tc);
-	kfree(rc);
-	return fid;
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
+					qid.type, qid.path, qid.version);
+
+	memmove(&afid->qid, &qid, sizeof(struct p9_qid));
+	p9_free_req(clnt, req);
+	return afid;
 
 error:
-	kfree(tc);
-	kfree(rc);
-	if (fid)
-		p9_fid_destroy(fid);
+	if (afid)
+		p9_fid_destroy(afid);
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL(p9_client_auth);
@@ -803,15 +878,13 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
 	int clone)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
 	struct p9_client *clnt;
 	struct p9_fid *fid;
+	struct p9_qid *wqids;
+	struct p9_req_t *req;
+	int16_t nwqids, count;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
-		oldfid->fid, nwname, wnames?wnames[0]:NULL);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = oldfid->clnt;
 	if (clone) {
 		fid = p9_fid_create(clnt);
@@ -825,53 +898,46 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
 	} else
 		fid = oldfid;
 
-	tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
+
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
+		oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
+
+	req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
+								nwname, wnames);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
 		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
-	if (err) {
-		if (rc && rc->id == P9_RWALK)
-			goto clunk_fid;
-		else
-			goto error;
-	}
+	err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids);
+	p9_free_req(clnt, req);
+	if (err)
+		goto clunk_fid;
 
-	if (rc->params.rwalk.nwqid != nwname) {
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
+
+	if (nwqids != nwname) {
 		err = -ENOENT;
 		goto clunk_fid;
 	}
 
+	for (count = 0; count < nwqids; count++)
+		P9_DPRINTK(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
+			count, wqids[count].type, wqids[count].path,
+			wqids[count].version);
+
 	if (nwname)
-		memmove(&fid->qid,
-			&rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
-			sizeof(struct p9_qid));
+		memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
 	else
 		fid->qid = oldfid->qid;
 
-	kfree(tc);
-	kfree(rc);
 	return fid;
 
 clunk_fid:
-	kfree(tc);
-	kfree(rc);
-	rc = NULL;
-	tc = p9_create_tclunk(fid->fid);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
-		goto error;
-	}
-
-	p9_client_rpc(clnt, tc, &rc);
+	p9_client_clunk(fid);
+	fid = NULL;
 
 error:
-	kfree(tc);
-	kfree(rc);
 	if (fid && (fid != oldfid))
 		p9_fid_destroy(fid);
 
@@ -882,35 +948,36 @@ EXPORT_SYMBOL(p9_client_walk);
 int p9_client_open(struct p9_fid *fid, int mode)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
 	struct p9_client *clnt;
+	struct p9_req_t *req;
+	struct p9_qid qid;
+	int iounit;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TOPEN fid %d mode %d\n", fid->fid, mode);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = fid->clnt;
 
 	if (fid->mode != -1)
 		return -EINVAL;
 
-	tc = p9_create_topen(fid->fid, mode);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
-		goto done;
+	req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
+	err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
+	p9_free_req(clnt, req);
 	if (err)
-		goto done;
+		goto error;
+
+	P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n",
+				qid.type, qid.path, qid.version, iounit);
 
 	fid->mode = mode;
-	fid->iounit = rc->params.ropen.iounit;
+	fid->iounit = iounit;
 
-done:
-	kfree(tc);
-	kfree(rc);
+error:
 	return err;
 }
 EXPORT_SYMBOL(p9_client_open);
@@ -919,37 +986,38 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
 		     char *extension)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
 	struct p9_client *clnt;
+	struct p9_req_t *req;
+	struct p9_qid qid;
+	int iounit;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid,
-		name, perm, mode);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
+						fid->fid, name, perm, mode);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = fid->clnt;
 
 	if (fid->mode != -1)
 		return -EINVAL;
 
-	tc = p9_create_tcreate(fid->fid, name, perm, mode, extension,
-							       clnt->dotu);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
-		goto done;
+	req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
+				mode, extension);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
+	err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
+	p9_free_req(clnt, req);
 	if (err)
-		goto done;
+		goto error;
+
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
+				qid.type, qid.path, qid.version, iounit);
 
 	fid->mode = mode;
-	fid->iounit = rc->params.ropen.iounit;
+	fid->iounit = iounit;
 
-done:
-	kfree(tc);
-	kfree(rc);
+error:
 	return err;
 }
 EXPORT_SYMBOL(p9_client_fcreate);
@@ -957,31 +1025,25 @@ EXPORT_SYMBOL(p9_client_fcreate);
 int p9_client_clunk(struct p9_fid *fid)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
 	struct p9_client *clnt;
+	struct p9_req_t *req;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = fid->clnt;
 
-	tc = p9_create_tclunk(fid->fid);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
-		goto done;
+	req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
-	if (err)
-		goto done;
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
 
+	p9_free_req(clnt, req);
 	p9_fid_destroy(fid);
 
-done:
-	kfree(tc);
-	kfree(rc);
+error:
 	return err;
 }
 EXPORT_SYMBOL(p9_client_clunk);
@@ -989,31 +1051,25 @@ EXPORT_SYMBOL(p9_client_clunk);
 int p9_client_remove(struct p9_fid *fid)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
 	struct p9_client *clnt;
+	struct p9_req_t *req;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = fid->clnt;
 
-	tc = p9_create_tremove(fid->fid);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
-		goto done;
+	req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
-	if (err)
-		goto done;
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
 
+	p9_free_req(clnt, req);
 	p9_fid_destroy(fid);
 
-done:
-	kfree(tc);
-	kfree(rc);
+error:
 	return err;
 }
 EXPORT_SYMBOL(p9_client_remove);
@@ -1022,15 +1078,14 @@ int
 p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 								u32 count)
 {
-	int err, n, rsize, total;
-	struct p9_fcall *tc, *rc;
+	int err, rsize, total;
 	struct p9_client *clnt;
+	struct p9_req_t *req;
+	char *dataptr;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid,
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
 					(long long unsigned) offset, count);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = fid->clnt;
 	total = 0;
 
@@ -1038,53 +1093,40 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
 		rsize = clnt->msize - P9_IOHDRSZ;
 
-	do {
-		if (count < rsize)
-			rsize = count;
+	if (count < rsize)
+		rsize = count;
 
-		tc = p9_create_tread(fid->fid, offset, rsize);
-		if (IS_ERR(tc)) {
-			err = PTR_ERR(tc);
-			tc = NULL;
-			goto error;
-		}
+	req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
+	}
 
-		err = p9_client_rpc(clnt, tc, &rc);
-		if (err)
-			goto error;
+	err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr);
+	if (err)
+		goto free_and_error;
 
-		n = rc->params.rread.count;
-		if (n > count)
-			n = count;
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
 
-		if (data) {
-			memmove(data, rc->params.rread.data, n);
-			data += n;
-		}
+	if (data) {
+		memmove(data, dataptr, count);
+		data += count;
+	}
 
-		if (udata) {
-			err = copy_to_user(udata, rc->params.rread.data, n);
-			if (err) {
-				err = -EFAULT;
-				goto error;
-			}
-			udata += n;
+	if (udata) {
+		err = copy_to_user(udata, dataptr, count);
+		if (err) {
+			err = -EFAULT;
+			goto free_and_error;
 		}
+	}
 
-		count -= n;
-		offset += n;
-		total += n;
-		kfree(tc);
-		tc = NULL;
-		kfree(rc);
-		rc = NULL;
-	} while (count > 0 && n == rsize);
-
-	return total;
+	p9_free_req(clnt, req);
+	return count;
 
+free_and_error:
+	p9_free_req(clnt, req);
 error:
-	kfree(tc);
-	kfree(rc);
 	return err;
 }
 EXPORT_SYMBOL(p9_client_read);
@@ -1093,15 +1135,13 @@ int
 p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
 							u64 offset, u32 count)
 {
-	int err, n, rsize, total;
-	struct p9_fcall *tc, *rc;
+	int err, rsize, total;
 	struct p9_client *clnt;
+	struct p9_req_t *req;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
-					(long long unsigned) offset, count);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
+				fid->fid, (long long unsigned) offset, count);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = fid->clnt;
 	total = 0;
 
@@ -1109,129 +1149,70 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
 	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
 		rsize = clnt->msize - P9_IOHDRSZ;
 
-	do {
-		if (count < rsize)
-			rsize = count;
-
-		if (data)
-			tc = p9_create_twrite(fid->fid, offset, rsize, data);
-		else
-			tc = p9_create_twrite_u(fid->fid, offset, rsize, udata);
-		if (IS_ERR(tc)) {
-			err = PTR_ERR(tc);
-			tc = NULL;
-			goto error;
-		}
-
-		err = p9_client_rpc(clnt, tc, &rc);
-		if (err)
-			goto error;
-
-		n = rc->params.rread.count;
-		count -= n;
-
-		if (data)
-			data += n;
-		else
-			udata += n;
+	if (count < rsize)
+		rsize = count;
+	if (data)
+		req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
+								rsize, data);
+	else
+		req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
+								rsize, udata);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
+	}
 
-		offset += n;
-		total += n;
-		kfree(tc);
-		tc = NULL;
-		kfree(rc);
-		rc = NULL;
-	} while (count > 0);
+	err = p9pdu_readf(req->rc, clnt->dotu, "d", &count);
+	if (err)
+		goto free_and_error;
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
 
-	return total;
+	p9_free_req(clnt, req);
+	return count;
 
+free_and_error:
+	p9_free_req(clnt, req);
 error:
-	kfree(tc);
-	kfree(rc);
 	return err;
 }
 EXPORT_SYMBOL(p9_client_write);
 
-static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
+struct p9_wstat *p9_client_stat(struct p9_fid *fid)
 {
-	int n;
-	char *p;
-	struct p9_stat *ret;
-
-	n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
-		st->muid.len;
+	int err;
+	struct p9_client *clnt;
+	struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
+	struct p9_req_t *req;
+	u16 ignored;
 
-	if (dotu)
-		n += st->extension.len;
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
 
-	ret = kmalloc(n, GFP_KERNEL);
 	if (!ret)
 		return ERR_PTR(-ENOMEM);
 
-	memmove(ret, st, sizeof(struct p9_stat));
-	p = ((char *) ret) + sizeof(struct p9_stat);
-	memmove(p, st->name.str, st->name.len);
-	ret->name.str = p;
-	p += st->name.len;
-	memmove(p, st->uid.str, st->uid.len);
-	ret->uid.str = p;
-	p += st->uid.len;
-	memmove(p, st->gid.str, st->gid.len);
-	ret->gid.str = p;
-	p += st->gid.len;
-	memmove(p, st->muid.str, st->muid.len);
-	ret->muid.str = p;
-	p += st->muid.len;
-
-	if (dotu) {
-		memmove(p, st->extension.str, st->extension.len);
-		ret->extension.str = p;
-		p += st->extension.len;
-	}
-
-	return ret;
-}
-
-struct p9_stat *p9_client_stat(struct p9_fid *fid)
-{
-	int err;
-	struct p9_fcall *tc, *rc;
-	struct p9_client *clnt;
-	struct p9_stat *ret;
-
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
-	ret = NULL;
 	clnt = fid->clnt;
 
-	tc = p9_create_tstat(fid->fid);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
+	req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
 		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
+	err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
+	p9_free_req(clnt, req);
 	if (err)
 		goto error;
 
-	ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu);
-	if (IS_ERR(ret)) {
-		err = PTR_ERR(ret);
-		ret = NULL;
-		goto error;
-	}
+	P9_DPRINTK(P9_DEBUG_9P,
+		"<<< RSTAT sz=%x type=%x dev=%x qid=%2.2x %4.4x %8.8llx"
+		" mode=%8.8x uid=%d gid=%d size=%lld %s\n",
+		ret->size, ret->type, ret->dev, ret->qid.type,
+		ret->qid.version, ret->qid.path, ret->mode,
+		ret->n_uid, ret->n_gid, ret->length, ret->name);
 
-	kfree(tc);
-	kfree(rc);
 	return ret;
-
 error:
-	kfree(tc);
-	kfree(rc);
-	kfree(ret);
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL(p9_client_stat);
@@ -1239,27 +1220,23 @@ EXPORT_SYMBOL(p9_client_stat);
 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
 {
 	int err;
-	struct p9_fcall *tc, *rc;
+	struct p9_req_t *req;
 	struct p9_client *clnt;
 
-	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
 	err = 0;
-	tc = NULL;
-	rc = NULL;
 	clnt = fid->clnt;
 
-	tc = p9_create_twstat(fid->fid, wst, clnt->dotu);
-	if (IS_ERR(tc)) {
-		err = PTR_ERR(tc);
-		tc = NULL;
-		goto done;
+	req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
 	}
 
-	err = p9_client_rpc(clnt, tc, &rc);
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
 
-done:
-	kfree(tc);
-	kfree(rc);
+	p9_free_req(clnt, req);
+error:
 	return err;
 }
 EXPORT_SYMBOL(p9_client_wstat);
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 43e98220e9a41b2aa17c32219913fcb0f672da65..4ebeffd21d3d170f56053943b9949b0625936f28 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -27,6 +27,7 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
+#include <linux/uaccess.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 #include "protocol.h"
@@ -51,6 +52,38 @@
 static int
 p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...);
 
+#define PACKET_DEBUG 0
+
+void
+p9pdu_dump(int way, struct p9_fcall *pdu)
+{
+	int i, n;
+	u8 *data = pdu->sdata;
+	int datalen = pdu->size;
+	char buf[255];
+	int buflen = 255;
+
+	i = n = 0;
+	if (datalen > (buflen-16))
+		datalen = buflen-16;
+	while (i < datalen) {
+		n += scnprintf(buf + n, buflen - n, "%02x ", data[i]);
+		if (i%4 == 3)
+			n += scnprintf(buf + n, buflen - n, " ");
+		if (i%32 == 31)
+			n += scnprintf(buf + n, buflen - n, "\n");
+
+		i++;
+	}
+	n += scnprintf(buf + n, buflen - n, "\n");
+
+	if (way)
+		printk(KERN_NOTICE "[[(%d)[ %s\n", datalen, buf);
+	else
+		printk(KERN_NOTICE "]](%d)] %s\n", datalen, buf);
+}
+EXPORT_SYMBOL(p9pdu_dump);
+
 void p9stat_free(struct p9_wstat *stbuf)
 {
 	kfree(stbuf->name);
@@ -77,6 +110,18 @@ static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size)
 	return size - len;
 }
 
+static size_t
+pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
+{
+	size_t len = MIN(pdu->capacity - pdu->size, size);
+	int err = copy_from_user(&pdu->sdata[pdu->size], udata, len);
+	if (err)
+		printk(KERN_WARNING "pdu_write_u returning: %d\n", err);
+
+	pdu->size += len;
+	return size - len;
+}
+
 /*
 	b - int8_t
 	w - int16_t
@@ -174,7 +219,6 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
 				stbuf->extension = NULL;
 				stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
 				    -1;
-
 				errcode =
 				    p9pdu_readf(pdu, optional,
 						"wwdQdddqssss?sddd",
@@ -332,7 +376,6 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
 		case 's':{
 				const char *ptr = va_arg(ap, const char *);
 				int16_t len = 0;
-
 				if (ptr)
 					len = MIN(strlen(ptr), USHORT_MAX);
 
@@ -356,7 +399,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
 				    p9pdu_writef(pdu, optional,
 						 "wwdQdddqssss?sddd",
 						 stbuf->size, stbuf->type,
-						 stbuf->dev, stbuf->qid,
+						 stbuf->dev, &stbuf->qid,
 						 stbuf->mode, stbuf->atime,
 						 stbuf->mtime, stbuf->length,
 						 stbuf->name, stbuf->uid,
@@ -374,6 +417,16 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
 					errcode = -EFAULT;
 			}
 			break;
+		case 'U':{
+				int32_t count = va_arg(ap, int32_t);
+				const char __user *udata =
+						va_arg(ap, const void *);
+				errcode =
+				    p9pdu_writef(pdu, optional, "d", count);
+				if (!errcode && pdu_write_u(pdu, udata, count))
+					errcode = -EFAULT;
+			}
+			break;
 		case 'T':{
 				int16_t nwname = va_arg(ap, int);
 				const char **wnames = va_arg(ap, const char **);
@@ -455,3 +508,29 @@ p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...)
 
 	return ret;
 }
+
+int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
+{
+	return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
+}
+
+int p9pdu_finalize(struct p9_fcall *pdu)
+{
+	int size = pdu->size;
+	int err;
+
+	pdu->size = 0;
+	err = p9pdu_writef(pdu, 0, "d", size);
+	pdu->size = size;
+
+	if (PACKET_DEBUG)
+		p9pdu_dump(0, pdu);
+
+	return err;
+}
+
+void p9pdu_reset(struct p9_fcall *pdu)
+{
+	pdu->offset = 0;
+	pdu->size = 0;
+}
diff --git a/net/9p/protocol.h b/net/9p/protocol.h
index 596ee10d506ffe9f4dfcf7c2673665ba7815866e..ccde462e7ac57173fa4eb8aea0131d6225357fef 100644
--- a/net/9p/protocol.h
+++ b/net/9p/protocol.h
@@ -27,5 +27,8 @@
 
 int
 p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap);
-
 int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...);
+int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type);
+int p9pdu_finalize(struct p9_fcall *pdu);
+void p9pdu_dump(int, struct p9_fcall *);
+void p9pdu_reset(struct p9_fcall *pdu);
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index e147ec539585dcfbd074576e5dbd0775fe343a2f..e8ebe2cb7e8bbed14ba22b2bdcb789c010068b79 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -181,7 +181,7 @@ static void p9_mux_poll_stop(struct p9_conn *m)
  *
  */
 
-void p9_conn_cancel(struct p9_conn *m, int err)
+static void p9_conn_cancel(struct p9_conn *m, int err)
 {
 	struct p9_req_t *req, *rtmp;
 	unsigned long flags;
@@ -287,7 +287,7 @@ static void p9_read_work(struct work_struct *work)
 	if (m->err < 0)
 		return;
 
-	P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
+	P9_DPRINTK(P9_DEBUG_TRANS, "start mux %p pos %d\n", m, m->rpos);
 
 	if (!m->rbuf) {
 		m->rbuf = m->tmp_buf;
@@ -296,11 +296,11 @@ static void p9_read_work(struct work_struct *work)
 	}
 
 	clear_bit(Rpending, &m->wsched);
-	P9_DPRINTK(P9_DEBUG_MUX, "read mux %p pos %d size: %d = %d\n", m,
+	P9_DPRINTK(P9_DEBUG_TRANS, "read mux %p pos %d size: %d = %d\n", m,
 					m->rpos, m->rsize, m->rsize-m->rpos);
 	err = p9_fd_read(m->client, m->rbuf + m->rpos,
 						m->rsize - m->rpos);
-	P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err);
+	P9_DPRINTK(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
 	if (err == -EAGAIN) {
 		clear_bit(Rworksched, &m->wsched);
 		return;
@@ -313,7 +313,7 @@ static void p9_read_work(struct work_struct *work)
 
 	if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */
 		u16 tag;
-		P9_DPRINTK(P9_DEBUG_MUX, "got new header\n");
+		P9_DPRINTK(P9_DEBUG_TRANS, "got new header\n");
 
 		n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */
 		if (n >= m->client->msize) {
@@ -324,8 +324,8 @@ static void p9_read_work(struct work_struct *work)
 		}
 
 		tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */
-		P9_DPRINTK(P9_DEBUG_MUX, "mux %p pkt: size: %d bytes tag: %d\n",
-								 m, n, tag);
+		P9_DPRINTK(P9_DEBUG_TRANS,
+			"mux %p pkt: size: %d bytes tag: %d\n", m, n, tag);
 
 		m->req = p9_tag_lookup(m->client, tag);
 		if (!m->req) {
@@ -351,7 +351,7 @@ static void p9_read_work(struct work_struct *work)
 
 	/* not an else because some packets (like clunk) have no payload */
 	if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */
-		P9_DPRINTK(P9_DEBUG_MUX, "got new packet\n");
+		P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n");
 
 		list_del(&m->req->req_list);
 		p9_client_cb(m->client, m->req);
@@ -369,7 +369,7 @@ static void p9_read_work(struct work_struct *work)
 			n = p9_fd_poll(m->client, NULL);
 
 		if (n & POLLIN) {
-			P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
+			P9_DPRINTK(P9_DEBUG_TRANS, "sched read work %p\n", m);
 			queue_work(p9_mux_wq, &m->rq);
 		} else
 			clear_bit(Rworksched, &m->wsched);
@@ -453,11 +453,11 @@ static void p9_write_work(struct work_struct *work)
 		spin_unlock(&m->client->lock);
 	}
 
-	P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
+	P9_DPRINTK(P9_DEBUG_TRANS, "mux %p pos %d size %d\n", m, m->wpos,
 								m->wsize);
 	clear_bit(Wpending, &m->wsched);
 	err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
-	P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
+	P9_DPRINTK(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
 	if (err == -EAGAIN) {
 		clear_bit(Wworksched, &m->wsched);
 		return;
@@ -481,7 +481,7 @@ static void p9_write_work(struct work_struct *work)
 			n = p9_fd_poll(m->client, NULL);
 
 		if (n & POLLOUT) {
-			P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
+			P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m);
 			queue_work(p9_mux_wq, &m->wq);
 		} else
 			clear_bit(Wworksched, &m->wsched);
@@ -558,7 +558,8 @@ static struct p9_conn *p9_conn_create(struct p9_client *client)
 	int n;
 	struct p9_conn *m;
 
-	P9_DPRINTK(P9_DEBUG_MUX, "client %p msize %d\n", client, client->msize);
+	P9_DPRINTK(P9_DEBUG_TRANS, "client %p msize %d\n", client,
+								client->msize);
 	m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
 	if (!m)
 		return ERR_PTR(-ENOMEM);
@@ -575,12 +576,12 @@ static struct p9_conn *p9_conn_create(struct p9_client *client)
 
 	n = p9_fd_poll(client, &m->pt);
 	if (n & POLLIN) {
-		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
+		P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can read\n", m);
 		set_bit(Rpending, &m->wsched);
 	}
 
 	if (n & POLLOUT) {
-		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
+		P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can write\n", m);
 		set_bit(Wpending, &m->wsched);
 	}
 
@@ -602,7 +603,7 @@ static void p9_poll_mux(struct p9_conn *m)
 
 	n = p9_fd_poll(m->client, NULL);
 	if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
-		P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
+		P9_DPRINTK(P9_DEBUG_TRANS, "error mux %p err %d\n", m, n);
 		if (n >= 0)
 			n = -ECONNRESET;
 		p9_conn_cancel(m, n);
@@ -610,19 +611,19 @@ static void p9_poll_mux(struct p9_conn *m)
 
 	if (n & POLLIN) {
 		set_bit(Rpending, &m->wsched);
-		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
+		P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can read\n", m);
 		if (!test_and_set_bit(Rworksched, &m->wsched)) {
-			P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
+			P9_DPRINTK(P9_DEBUG_TRANS, "sched read work %p\n", m);
 			queue_work(p9_mux_wq, &m->rq);
 		}
 	}
 
 	if (n & POLLOUT) {
 		set_bit(Wpending, &m->wsched);
-		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
+		P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can write\n", m);
 		if ((m->wsize || !list_empty(&m->unsent_req_list))
 		    && !test_and_set_bit(Wworksched, &m->wsched)) {
-			P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
+			P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m);
 			queue_work(p9_mux_wq, &m->wq);
 		}
 	}
@@ -645,8 +646,8 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
 	struct p9_trans_fd *ts = client->trans;
 	struct p9_conn *m = ts->conn;
 
-	P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
-		req->tc, req->tc->id);
+	P9_DPRINTK(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", m,
+						current, req->tc, req->tc->id);
 	if (m->err < 0)
 		return m->err;
 
@@ -672,19 +673,12 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
 	struct p9_trans_fd *ts = client->trans;
 	struct p9_conn *m = ts->conn;
 
-	P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p\n", m, req);
+	P9_DPRINTK(P9_DEBUG_TRANS, "mux %p req %p\n", m, req);
 
 	spin_lock(&client->lock);
 	list_del(&req->req_list);
 	spin_unlock(&client->lock);
 
-	/* if a response was received for a request, do nothing */
-	if (req->rc || req->t_err) {
-		P9_DPRINTK(P9_DEBUG_MUX,
-			"mux %p req %p response already received\n", m, req);
-		return 0;
-	}
-
 	if (req->status == REQ_STATUS_UNSENT) {
 		req->status = REQ_STATUS_FLSHD;
 		return 0;
@@ -809,7 +803,7 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket)
 
 static void p9_conn_destroy(struct p9_conn *m)
 {
-	P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
+	P9_DPRINTK(P9_DEBUG_TRANS, "mux %p prev %p next %p\n", m,
 		m->mux_list.prev, m->mux_list.next);
 
 	p9_mux_poll_stop(m);
@@ -1060,7 +1054,7 @@ static int p9_poll_proc(void *a)
 {
 	unsigned long flags;
 
-	P9_DPRINTK(P9_DEBUG_MUX, "start %p\n", current);
+	P9_DPRINTK(P9_DEBUG_TRANS, "start %p\n", current);
  repeat:
 	spin_lock_irqsave(&p9_poll_lock, flags);
 	while (!list_empty(&p9_poll_pending_list)) {
@@ -1078,7 +1072,7 @@ static int p9_poll_proc(void *a)
 
 	set_current_state(TASK_INTERRUPTIBLE);
 	if (list_empty(&p9_poll_pending_list)) {
-		P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n");
+		P9_DPRINTK(P9_DEBUG_TRANS, "sleeping...\n");
 		schedule();
 	}
 	__set_current_state(TASK_RUNNING);
@@ -1086,7 +1080,7 @@ static int p9_poll_proc(void *a)
 	if (!kthread_should_stop())
 		goto repeat;
 
-	P9_DPRINTK(P9_DEBUG_MUX, "finish\n");
+	P9_DPRINTK(P9_DEBUG_TRANS, "finish\n");
 	return 0;
 }
 
diff --git a/net/9p/util.c b/net/9p/util.c
index 958fc58cd1ffbb0723552b180302c569387adfb4..dc4ec05ad93d5324b3a7d6b81c63ae1c7815af39 100644
--- a/net/9p/util.c
+++ b/net/9p/util.c
@@ -105,6 +105,7 @@ int p9_idpool_get(struct p9_idpool *p)
 	else if (error)
 		return -1;
 
+	P9_DPRINTK(P9_DEBUG_MUX, " id %d pool %p\n", i, p);
 	return i;
 }
 EXPORT_SYMBOL(p9_idpool_get);
@@ -121,6 +122,9 @@ EXPORT_SYMBOL(p9_idpool_get);
 void p9_idpool_put(int id, struct p9_idpool *p)
 {
 	unsigned long flags;
+
+	P9_DPRINTK(P9_DEBUG_MUX, " id %d pool %p\n", id, p);
+
 	spin_lock_irqsave(&p->lock, flags);
 	idr_remove(&p->pool, id);
 	spin_unlock_irqrestore(&p->lock, flags);