9p: rework client code to use new protocol support functions
authorEric Van Hensbergen <ericvh@gmail.com>
Thu, 16 Oct 2008 13:30:07 +0000 (08:30 -0500)
committerEric Van Hensbergen <ericvh@gmail.com>
Fri, 17 Oct 2008 16:04:45 +0000 (11:04 -0500)
Now that the new protocol functions are in place, this patch switches
the client code to using the new support code.

Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
12 files changed:
fs/9p/v9fs_vfs.h
fs/9p/vfs_dir.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
include/net/9p/9p.h
include/net/9p/client.h
net/9p/client.c
net/9p/protocol.c
net/9p/protocol.h
net/9p/trans_fd.c
net/9p/util.c

index 046cff3..c295ba7 100644 (file)
@@ -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);
 
index d7d0ac5..276aed6 100644 (file)
@@ -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;
 
index 3fd28bb..041c526 100644 (file)
@@ -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;
index e83aa5e..e96d84a 100644 (file)
@@ -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;
 
index bf59c39..d6cb1a0 100644 (file)
@@ -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:
index 46d0b8f..56c15ae 100644 (file)
@@ -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)
index 475ef5c..1e49b4d 100644 (file)
@@ -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 */
index 6004fde..2a166bf 100644 (file)
@@ -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,59 +285,34 @@ 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
  * r: request to release
  *
  */
 
-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);
@@ -365,28 +359,164 @@ 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 @@ again:
        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);
index 43e9822..4ebeffd 100644 (file)
@@ -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"
 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;
+}
index 596ee10..ccde462 100644 (file)
@@ -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);
index e147ec5..e8ebe2c 100644 (file)
@@ -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;
 }
 
index 958fc58..dc4ec05 100644 (file)
@@ -105,6 +105,7 @@ retry:
        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);