aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2008-10-16 09:30:07 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2008-10-17 12:04:45 -0400
commit51a87c552dfd428e304c865e24ecbe091556f226 (patch)
tree6e9012962e6601b559dcf15ae3228647a8581a31
parentcb198131b0e7aba755ac164744536d461e86ab82 (diff)
9p: rework client code to use new protocol support functions
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>
-rw-r--r--fs/9p/v9fs_vfs.h4
-rw-r--r--fs/9p/vfs_dir.c4
-rw-r--r--fs/9p/vfs_file.c2
-rw-r--r--fs/9p/vfs_inode.c38
-rw-r--r--fs/9p/vfs_super.c6
-rw-r--r--include/net/9p/9p.h7
-rw-r--r--include/net/9p/client.h7
-rw-r--r--net/9p/client.c931
-rw-r--r--net/9p/protocol.c85
-rw-r--r--net/9p/protocol.h5
-rw-r--r--net/9p/trans_fd.c62
-rw-r--r--net/9p/util.c4
12 files changed, 611 insertions, 544 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 046cff377f10..c295ba786edd 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;
46 46
47struct inode *v9fs_get_inode(struct super_block *sb, int mode); 47struct inode *v9fs_get_inode(struct super_block *sb, int mode);
48ino_t v9fs_qid2ino(struct p9_qid *qid); 48ino_t v9fs_qid2ino(struct p9_qid *qid);
49void v9fs_stat2inode(struct p9_stat *, struct inode *, struct super_block *); 49void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
50int v9fs_dir_release(struct inode *inode, struct file *filp); 50int v9fs_dir_release(struct inode *inode, struct file *filp);
51int v9fs_file_open(struct inode *inode, struct file *file); 51int v9fs_file_open(struct inode *inode, struct file *file);
52void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat); 52void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
53void v9fs_dentry_release(struct dentry *); 53void v9fs_dentry_release(struct dentry *);
54int v9fs_uflags2omode(int uflags, int extended); 54int v9fs_uflags2omode(int uflags, int extended);
55 55
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index d7d0ac5a2ca3..276aed625929 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)
85 return -ENOMEM; 85 return -ENOMEM;
86 86
87 while (1) { 87 while (1) {
88 err = v9fs_file_readn(filp, statbuf, NULL, fid->rdir_fpos, 88 err = v9fs_file_readn(filp, statbuf, NULL, buflen,
89 buflen); 89 fid->rdir_fpos);
90 if (err <= 0) 90 if (err <= 0)
91 break; 91 break;
92 92
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 3fd28bbafc87..041c52692284 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,
136 int n, total; 136 int n, total;
137 struct p9_fid *fid = filp->private_data; 137 struct p9_fid *fid = filp->private_data;
138 138
139 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, 139 P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid,
140 (long long unsigned) offset, count); 140 (long long unsigned) offset, count);
141 141
142 n = 0; 142 n = 0;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index e83aa5ebe861..e96d84aafbe2 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,
334{ 334{
335 int err, umode; 335 int err, umode;
336 struct inode *ret; 336 struct inode *ret;
337 struct p9_stat *st; 337 struct p9_wstat *st;
338 338
339 ret = NULL; 339 ret = NULL;
340 st = p9_client_stat(fid); 340 st = p9_client_stat(fid);
@@ -417,6 +417,8 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
417 struct p9_fid *dfid, *ofid, *fid; 417 struct p9_fid *dfid, *ofid, *fid;
418 struct inode *inode; 418 struct inode *inode;
419 419
420 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
421
420 err = 0; 422 err = 0;
421 ofid = NULL; 423 ofid = NULL;
422 fid = NULL; 424 fid = NULL;
@@ -424,6 +426,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
424 dfid = v9fs_fid_clone(dentry->d_parent); 426 dfid = v9fs_fid_clone(dentry->d_parent);
425 if (IS_ERR(dfid)) { 427 if (IS_ERR(dfid)) {
426 err = PTR_ERR(dfid); 428 err = PTR_ERR(dfid);
429 P9_DPRINTK(P9_DEBUG_VFS, "fid clone failed %d\n", err);
427 dfid = NULL; 430 dfid = NULL;
428 goto error; 431 goto error;
429 } 432 }
@@ -432,18 +435,22 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
432 ofid = p9_client_walk(dfid, 0, NULL, 1); 435 ofid = p9_client_walk(dfid, 0, NULL, 1);
433 if (IS_ERR(ofid)) { 436 if (IS_ERR(ofid)) {
434 err = PTR_ERR(ofid); 437 err = PTR_ERR(ofid);
438 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
435 ofid = NULL; 439 ofid = NULL;
436 goto error; 440 goto error;
437 } 441 }
438 442
439 err = p9_client_fcreate(ofid, name, perm, mode, extension); 443 err = p9_client_fcreate(ofid, name, perm, mode, extension);
440 if (err < 0) 444 if (err < 0) {
445 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
441 goto error; 446 goto error;
447 }
442 448
443 /* now walk from the parent so we can get unopened fid */ 449 /* now walk from the parent so we can get unopened fid */
444 fid = p9_client_walk(dfid, 1, &name, 0); 450 fid = p9_client_walk(dfid, 1, &name, 0);
445 if (IS_ERR(fid)) { 451 if (IS_ERR(fid)) {
446 err = PTR_ERR(fid); 452 err = PTR_ERR(fid);
453 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
447 fid = NULL; 454 fid = NULL;
448 goto error; 455 goto error;
449 } else 456 } else
@@ -453,6 +460,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
453 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 460 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
454 if (IS_ERR(inode)) { 461 if (IS_ERR(inode)) {
455 err = PTR_ERR(inode); 462 err = PTR_ERR(inode);
463 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
456 goto error; 464 goto error;
457 } 465 }
458 466
@@ -734,7 +742,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
734 int err; 742 int err;
735 struct v9fs_session_info *v9ses; 743 struct v9fs_session_info *v9ses;
736 struct p9_fid *fid; 744 struct p9_fid *fid;
737 struct p9_stat *st; 745 struct p9_wstat *st;
738 746
739 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 747 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
740 err = -EPERM; 748 err = -EPERM;
@@ -815,10 +823,9 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
815 */ 823 */
816 824
817void 825void
818v9fs_stat2inode(struct p9_stat *stat, struct inode *inode, 826v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
819 struct super_block *sb) 827 struct super_block *sb)
820{ 828{
821 int n;
822 char ext[32]; 829 char ext[32];
823 struct v9fs_session_info *v9ses = sb->s_fs_info; 830 struct v9fs_session_info *v9ses = sb->s_fs_info;
824 831
@@ -842,11 +849,7 @@ v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
842 int major = -1; 849 int major = -1;
843 int minor = -1; 850 int minor = -1;
844 851
845 n = stat->extension.len; 852 strncpy(ext, stat->extension, sizeof(ext));
846 if (n > sizeof(ext)-1)
847 n = sizeof(ext)-1;
848 memmove(ext, stat->extension.str, n);
849 ext[n] = 0;
850 sscanf(ext, "%c %u %u", &type, &major, &minor); 853 sscanf(ext, "%c %u %u", &type, &major, &minor);
851 switch (type) { 854 switch (type) {
852 case 'c': 855 case 'c':
@@ -857,8 +860,8 @@ v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
857 break; 860 break;
858 default: 861 default:
859 P9_DPRINTK(P9_DEBUG_ERROR, 862 P9_DPRINTK(P9_DEBUG_ERROR,
860 "Unknown special type %c (%.*s)\n", type, 863 "Unknown special type %c %s\n", type,
861 stat->extension.len, stat->extension.str); 864 stat->extension);
862 }; 865 };
863 inode->i_rdev = MKDEV(major, minor); 866 inode->i_rdev = MKDEV(major, minor);
864 } else 867 } else
@@ -904,7 +907,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
904 907
905 struct v9fs_session_info *v9ses; 908 struct v9fs_session_info *v9ses;
906 struct p9_fid *fid; 909 struct p9_fid *fid;
907 struct p9_stat *st; 910 struct p9_wstat *st;
908 911
909 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); 912 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
910 retval = -EPERM; 913 retval = -EPERM;
@@ -926,15 +929,10 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
926 } 929 }
927 930
928 /* copy extension buffer into buffer */ 931 /* copy extension buffer into buffer */
929 if (st->extension.len < buflen) 932 strncpy(buffer, st->extension, buflen);
930 buflen = st->extension.len + 1;
931
932 memmove(buffer, st->extension.str, buflen - 1);
933 buffer[buflen-1] = 0;
934 933
935 P9_DPRINTK(P9_DEBUG_VFS, 934 P9_DPRINTK(P9_DEBUG_VFS,
936 "%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len, 935 "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
937 st->extension.str, buffer);
938 936
939 retval = buflen; 937 retval = buflen;
940 938
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index bf59c3960494..d6cb1a0ca724 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,
111 struct inode *inode = NULL; 111 struct inode *inode = NULL;
112 struct dentry *root = NULL; 112 struct dentry *root = NULL;
113 struct v9fs_session_info *v9ses = NULL; 113 struct v9fs_session_info *v9ses = NULL;
114 struct p9_stat *st = NULL; 114 struct p9_wstat *st = NULL;
115 int mode = S_IRWXUGO | S_ISVTX; 115 int mode = S_IRWXUGO | S_ISVTX;
116 uid_t uid = current->fsuid; 116 uid_t uid = current->fsuid;
117 gid_t gid = current->fsgid; 117 gid_t gid = current->fsgid;
@@ -161,10 +161,14 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
161 161
162 sb->s_root = root; 162 sb->s_root = root;
163 root->d_inode->i_ino = v9fs_qid2ino(&st->qid); 163 root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
164
164 v9fs_stat2inode(st, root->d_inode, sb); 165 v9fs_stat2inode(st, root->d_inode, sb);
166
165 v9fs_fid_add(root, fid); 167 v9fs_fid_add(root, fid);
168 p9stat_free(st);
166 kfree(st); 169 kfree(st);
167 170
171P9_DPRINTK(P9_DEBUG_VFS, " return simple set mount\n");
168 return simple_set_mnt(mnt, sb); 172 return simple_set_mnt(mnt, sb);
169 173
170release_sb: 174release_sb:
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 46d0b8f8e5ec..56c15aee6e61 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -39,6 +39,7 @@
39 * @P9_DEBUG_TRANS: transport tracing 39 * @P9_DEBUG_TRANS: transport tracing
40 * @P9_DEBUG_SLABS: memory management tracing 40 * @P9_DEBUG_SLABS: memory management tracing
41 * @P9_DEBUG_FCALL: verbose dump of protocol messages 41 * @P9_DEBUG_FCALL: verbose dump of protocol messages
42 * @P9_DEBUG_FID: fid allocation/deallocation tracking
42 * 43 *
43 * These flags are passed at mount time to turn on various levels of 44 * These flags are passed at mount time to turn on various levels of
44 * verbosity and tracing which will be output to the system logs. 45 * verbosity and tracing which will be output to the system logs.
@@ -53,13 +54,17 @@ enum p9_debug_flags {
53 P9_DEBUG_TRANS = (1<<6), 54 P9_DEBUG_TRANS = (1<<6),
54 P9_DEBUG_SLABS = (1<<7), 55 P9_DEBUG_SLABS = (1<<7),
55 P9_DEBUG_FCALL = (1<<8), 56 P9_DEBUG_FCALL = (1<<8),
57 P9_DEBUG_FID = (1<<9),
56}; 58};
57 59
58extern unsigned int p9_debug_level; 60extern unsigned int p9_debug_level;
59 61
60#define P9_DPRINTK(level, format, arg...) \ 62#define P9_DPRINTK(level, format, arg...) \
61do { \ 63do { \
62 if ((p9_debug_level & level) == level) \ 64 if (level == P9_DEBUG_9P) \
65 printk(KERN_NOTICE "(%8.8d) " \
66 format , task_pid_nr(current) , ## arg); \
67 else if ((p9_debug_level & level) == level) \
63 printk(KERN_NOTICE "-- %s (%d): " \ 68 printk(KERN_NOTICE "-- %s (%d): " \
64 format , __func__, task_pid_nr(current) , ## arg); \ 69 format , __func__, task_pid_nr(current) , ## arg); \
65} while (0) 70} while (0)
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 475ef5cf1644..1e49b4d1030b 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -77,6 +77,7 @@ enum p9_req_status_t {
77 * struct p9_req_t - request slots 77 * struct p9_req_t - request slots
78 * @status: status of this request slot 78 * @status: status of this request slot
79 * @t_err: transport error 79 * @t_err: transport error
80 * @flush_tag: tag of request being flushed (for flush requests)
80 * @wq: wait_queue for the client to block on for this request 81 * @wq: wait_queue for the client to block on for this request
81 * @tc: the request fcall structure 82 * @tc: the request fcall structure
82 * @rc: the response fcall structure 83 * @rc: the response fcall structure
@@ -97,10 +98,10 @@ enum p9_req_status_t {
97struct p9_req_t { 98struct p9_req_t {
98 int status; 99 int status;
99 int t_err; 100 int t_err;
101 u16 flush_tag;
100 wait_queue_head_t *wq; 102 wait_queue_head_t *wq;
101 struct p9_fcall *tc; 103 struct p9_fcall *tc;
102 struct p9_fcall *rc; 104 struct p9_fcall *rc;
103 u16 flush_tag;
104 void *aux; 105 void *aux;
105 106
106 struct list_head req_list; 107 struct list_head req_list;
@@ -199,10 +200,12 @@ int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
199 u64 offset, u32 count); 200 u64 offset, u32 count);
200int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 201int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
201 u64 offset, u32 count); 202 u64 offset, u32 count);
202struct p9_stat *p9_client_stat(struct p9_fid *fid); 203struct p9_wstat *p9_client_stat(struct p9_fid *fid);
203int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); 204int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
204 205
205struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); 206struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
206void p9_client_cb(struct p9_client *c, struct p9_req_t *req); 207void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
207 208
209void p9stat_free(struct p9_wstat *);
210
208#endif /* NET_9P_CLIENT_H */ 211#endif /* NET_9P_CLIENT_H */
diff --git a/net/9p/client.c b/net/9p/client.c
index 6004fded6682..2a166bfb95a3 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -35,6 +35,7 @@
35#include <linux/parser.h> 35#include <linux/parser.h>
36#include <net/9p/client.h> 36#include <net/9p/client.h>
37#include <net/9p/transport.h> 37#include <net/9p/transport.h>
38#include "protocol.h"
38 39
39/* 40/*
40 * Client Option Parsing (code inspired by NFS code) 41 * Client Option Parsing (code inspired by NFS code)
@@ -55,8 +56,8 @@ static const match_table_t tokens = {
55 {Opt_err, NULL}, 56 {Opt_err, NULL},
56}; 57};
57 58
58static int 59static struct p9_req_t *
59p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc); 60p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
60 61
61/** 62/**
62 * v9fs_parse_options - parse mount options into session structure 63 * v9fs_parse_options - parse mount options into session structure
@@ -138,10 +139,11 @@ static int parse_opts(char *opts, struct p9_client *clnt)
138 * 139 *
139 */ 140 */
140 141
141struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) 142static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
142{ 143{
143 unsigned long flags; 144 unsigned long flags;
144 int row, col; 145 int row, col;
146 struct p9_req_t *req;
145 147
146 /* This looks up the original request by tag so we know which 148 /* This looks up the original request by tag so we know which
147 * buffer to read the data into */ 149 * buffer to read the data into */
@@ -157,19 +159,11 @@ struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
157 159
158 if (!c->reqs[row]) { 160 if (!c->reqs[row]) {
159 printk(KERN_ERR "Couldn't grow tag array\n"); 161 printk(KERN_ERR "Couldn't grow tag array\n");
160 BUG(); 162 return ERR_PTR(-ENOMEM);
161 } 163 }
162 for (col = 0; col < P9_ROW_MAXTAG; col++) { 164 for (col = 0; col < P9_ROW_MAXTAG; col++) {
163 c->reqs[row][col].status = REQ_STATUS_IDLE; 165 c->reqs[row][col].status = REQ_STATUS_IDLE;
164 c->reqs[row][col].flush_tag = P9_NOTAG; 166 c->reqs[row][col].tc = NULL;
165 c->reqs[row][col].wq = kmalloc(
166 sizeof(wait_queue_head_t), GFP_ATOMIC);
167 if (!c->reqs[row][col].wq) {
168 printk(KERN_ERR
169 "Couldn't grow tag array\n");
170 BUG();
171 }
172 init_waitqueue_head(c->reqs[row][col].wq);
173 } 167 }
174 c->max_tag += P9_ROW_MAXTAG; 168 c->max_tag += P9_ROW_MAXTAG;
175 } 169 }
@@ -178,12 +172,39 @@ struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
178 row = tag / P9_ROW_MAXTAG; 172 row = tag / P9_ROW_MAXTAG;
179 col = tag % P9_ROW_MAXTAG; 173 col = tag % P9_ROW_MAXTAG;
180 174
181 c->reqs[row][col].status = REQ_STATUS_ALLOC; 175 req = &c->reqs[row][col];
182 c->reqs[row][col].flush_tag = P9_NOTAG; 176 if (!req->tc) {
177 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
178 if (!req->wq) {
179 printk(KERN_ERR "Couldn't grow tag array\n");
180 return ERR_PTR(-ENOMEM);
181 }
182 init_waitqueue_head(req->wq);
183 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
184 GFP_KERNEL);
185 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
186 GFP_KERNEL);
187 if ((!req->tc) || (!req->rc)) {
188 printk(KERN_ERR "Couldn't grow tag array\n");
189 kfree(req->tc);
190 kfree(req->rc);
191 return ERR_PTR(-ENOMEM);
192 }
193 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
194 req->tc->capacity = c->msize;
195 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
196 req->rc->capacity = c->msize;
197 }
198
199 p9pdu_reset(req->tc);
200 p9pdu_reset(req->rc);
201
202 req->flush_tag = 0;
203 req->tc->tag = tag-1;
204 req->status = REQ_STATUS_ALLOC;
183 205
184 return &c->reqs[row][col]; 206 return &c->reqs[row][col];
185} 207}
186EXPORT_SYMBOL(p9_tag_alloc);
187 208
188/** 209/**
189 * p9_tag_lookup - lookup a request by tag 210 * p9_tag_lookup - lookup a request by tag
@@ -264,59 +285,34 @@ static void p9_tag_cleanup(struct p9_client *c)
264 285
265 /* free requests associated with tags */ 286 /* free requests associated with tags */
266 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { 287 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
267 for (col = 0; col < P9_ROW_MAXTAG; col++) 288 for (col = 0; col < P9_ROW_MAXTAG; col++) {
268 kfree(c->reqs[row][col].wq); 289 kfree(c->reqs[row][col].wq);
290 kfree(c->reqs[row][col].tc);
291 kfree(c->reqs[row][col].rc);
292 }
269 kfree(c->reqs[row]); 293 kfree(c->reqs[row]);
270 } 294 }
271 c->max_tag = 0; 295 c->max_tag = 0;
272} 296}
273 297
274/** 298/**
275 * p9_client_flush - flush (cancel) a request
276 * c: client state
277 * req: request to cancel
278 *
279 * This sents a flush for a particular requests and links
280 * the flush request to the original request. The current
281 * code only supports a single flush request although the protocol
282 * allows for multiple flush requests to be sent for a single request.
283 *
284 */
285
286static int p9_client_flush(struct p9_client *c, struct p9_req_t *req)
287{
288 struct p9_fcall *tc, *rc = NULL;
289 int err;
290
291 P9_DPRINTK(P9_DEBUG_9P, "client %p tag %d\n", c, req->tc->tag);
292
293 tc = p9_create_tflush(req->tc->tag);
294 if (IS_ERR(tc))
295 return PTR_ERR(tc);
296
297 err = p9_client_rpc(c, tc, &rc);
298
299 /* we don't free anything here because RPC isn't complete */
300
301 return err;
302}
303
304/**
305 * p9_free_req - free a request and clean-up as necessary 299 * p9_free_req - free a request and clean-up as necessary
306 * c: client state 300 * c: client state
307 * r: request to release 301 * r: request to release
308 * 302 *
309 */ 303 */
310 304
311void p9_free_req(struct p9_client *c, struct p9_req_t *r) 305static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
312{ 306{
313 r->flush_tag = P9_NOTAG; 307 int tag = r->tc->tag;
308 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
309
314 r->status = REQ_STATUS_IDLE; 310 r->status = REQ_STATUS_IDLE;
315 if (r->tc->tag != P9_NOTAG && p9_idpool_check(r->tc->tag, c->tagpool)) 311 if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
316 p9_idpool_put(r->tc->tag, c->tagpool); 312 p9_idpool_put(tag, c->tagpool);
317 313
318 /* if this was a flush request we have to free response fcall */ 314 /* if this was a flush request we have to free response fcall */
319 if (r->tc->id == P9_TFLUSH) { 315 if (r->rc->id == P9_RFLUSH) {
320 kfree(r->tc); 316 kfree(r->tc);
321 kfree(r->rc); 317 kfree(r->rc);
322 } 318 }
@@ -333,30 +329,28 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
333 struct p9_req_t *other_req; 329 struct p9_req_t *other_req;
334 unsigned long flags; 330 unsigned long flags;
335 331
336 P9_DPRINTK(P9_DEBUG_MUX, ": %d\n", req->tc->tag); 332 P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
337 333
338 if (req->status == REQ_STATUS_ERROR) 334 if (req->status == REQ_STATUS_ERROR)
339 wake_up(req->wq); 335 wake_up(req->wq);
340 336
341 if (req->tc->id == P9_TFLUSH) { /* flush receive path */ 337 if (req->flush_tag) { /* flush receive path */
342 P9_DPRINTK(P9_DEBUG_MUX, "flush: %d\n", req->tc->tag); 338 P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag);
343 spin_lock_irqsave(&c->lock, flags); 339 spin_lock_irqsave(&c->lock, flags);
344 other_req = p9_tag_lookup(c, req->tc->params.tflush.oldtag); 340 other_req = p9_tag_lookup(c, req->flush_tag);
345 if (other_req->flush_tag != req->tc->tag) /* stale flush */ 341 if (other_req->status != REQ_STATUS_FLSH) /* stale flush */
346 spin_unlock_irqrestore(&c->lock, flags); 342 spin_unlock_irqrestore(&c->lock, flags);
347 else { 343 else {
348 BUG_ON(other_req->status != REQ_STATUS_FLSH);
349 other_req->status = REQ_STATUS_FLSHD; 344 other_req->status = REQ_STATUS_FLSHD;
350 spin_unlock_irqrestore(&c->lock, flags); 345 spin_unlock_irqrestore(&c->lock, flags);
351 wake_up(other_req->wq); 346 wake_up(other_req->wq);
352 } 347 }
353 p9_free_req(c, req); 348 p9_free_req(c, req);
354 } else { /* normal receive path */ 349 } else { /* normal receive path */
355 P9_DPRINTK(P9_DEBUG_MUX, "normal: %d\n", req->tc->tag); 350 P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag);
356 spin_lock_irqsave(&c->lock, flags); 351 spin_lock_irqsave(&c->lock, flags);
357 if (req->status != REQ_STATUS_FLSHD) 352 if (req->status != REQ_STATUS_FLSHD)
358 req->status = REQ_STATUS_RCVD; 353 req->status = REQ_STATUS_RCVD;
359 req->flush_tag = P9_NOTAG;
360 spin_unlock_irqrestore(&c->lock, flags); 354 spin_unlock_irqrestore(&c->lock, flags);
361 wake_up(req->wq); 355 wake_up(req->wq);
362 P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); 356 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)
365EXPORT_SYMBOL(p9_client_cb); 359EXPORT_SYMBOL(p9_client_cb);
366 360
367/** 361/**
362 * p9_parse_header - parse header arguments out of a packet
363 * @pdu: packet to parse
364 * @size: size of packet
365 * @type: type of request
366 * @tag: tag of packet
367 * @rewind: set if we need to rewind offset afterwards
368 */
369
370int
371p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
372 int rewind)
373{
374 int8_t r_type;
375 int16_t r_tag;
376 int32_t r_size;
377 int offset = pdu->offset;
378 int err;
379
380 pdu->offset = 0;
381 if (pdu->size == 0)
382 pdu->size = 7;
383
384 err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
385 if (err)
386 goto rewind_and_exit;
387
388 pdu->size = r_size;
389 pdu->id = r_type;
390 pdu->tag = r_tag;
391
392 P9_DPRINTK(P9_DEBUG_MUX, "pdu: type: %d tag: %d size=%d offset=%d\n",
393 pdu->id, pdu->tag, pdu->size, pdu->offset);
394
395 if (type)
396 *type = r_type;
397 if (tag)
398 *tag = r_tag;
399 if (size)
400 *size = r_size;
401
402
403rewind_and_exit:
404 if (rewind)
405 pdu->offset = offset;
406 return err;
407}
408EXPORT_SYMBOL(p9_parse_header);
409
410/**
411 * p9_check_errors - check 9p packet for error return and process it
412 * @c: current client instance
413 * @req: request to parse and check for error conditions
414 *
415 * returns error code if one is discovered, otherwise returns 0
416 *
417 * this will have to be more complicated if we have multiple
418 * error packet types
419 */
420
421static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
422{
423 int8_t type;
424 int err;
425
426 err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
427 if (err) {
428 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
429 return err;
430 }
431
432 if (type == P9_RERROR) {
433 int ecode;
434 char *ename;
435
436 err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
437 if (err) {
438 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
439 err);
440 return err;
441 }
442
443 if (c->dotu)
444 err = -ecode;
445
446 if (!err) {
447 err = p9_errstr2errno(ename, strlen(ename));
448
449 /* string match failed */
450 if (!err)
451 err = -ESERVERFAULT;
452 }
453
454 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
455
456 kfree(ename);
457 } else
458 err = 0;
459
460 return err;
461}
462
463/**
464 * p9_client_flush - flush (cancel) a request
465 * c: client state
466 * req: request to cancel
467 *
468 * This sents a flush for a particular requests and links
469 * the flush request to the original request. The current
470 * code only supports a single flush request although the protocol
471 * allows for multiple flush requests to be sent for a single request.
472 *
473 */
474
475static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
476{
477 struct p9_req_t *req;
478 int16_t oldtag;
479 int err;
480
481 err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
482 if (err)
483 return err;
484
485 P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
486
487 req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
488 if (IS_ERR(req))
489 return PTR_ERR(req);
490
491 req->flush_tag = oldtag;
492
493 /* we don't free anything here because RPC isn't complete */
494 return 0;
495}
496
497/**
368 * p9_client_rpc - issue a request and wait for a response 498 * p9_client_rpc - issue a request and wait for a response
369 * @c: client session 499 * @c: client session
370 * @tc: &p9_fcall request to transmit 500 * @type: type of request
371 * @rc: &p9_fcall to put reponse into 501 * @fmt: protocol format string (see protocol.c)
372 * 502 *
373 * Returns 0 on success, error code on failure 503 * Returns request structure (which client must free using p9_free_req)
374 */ 504 */
375 505
376static int 506static struct p9_req_t *
377p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc) 507p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
378{ 508{
379 int tag, err, size; 509 va_list ap;
380 char *rdata; 510 int tag, err;
381 struct p9_req_t *req; 511 struct p9_req_t *req;
382 unsigned long flags; 512 unsigned long flags;
383 int sigpending; 513 int sigpending;
384 int flushed = 0; 514 int flushed = 0;
385 515
386 P9_DPRINTK(P9_DEBUG_9P, "client %p tc %p rc %p\n", c, tc, rc); 516 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
387 517
388 if (c->status != Connected) 518 if (c->status != Connected)
389 return -EIO; 519 return ERR_PTR(-EIO);
390 520
391 if (signal_pending(current)) { 521 if (signal_pending(current)) {
392 sigpending = 1; 522 sigpending = 1;
@@ -395,50 +525,22 @@ p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
395 sigpending = 0; 525 sigpending = 0;
396 526
397 tag = P9_NOTAG; 527 tag = P9_NOTAG;
398 if (tc->id != P9_TVERSION) { 528 if (type != P9_TVERSION) {
399 tag = p9_idpool_get(c->tagpool); 529 tag = p9_idpool_get(c->tagpool);
400 if (tag < 0) 530 if (tag < 0)
401 return -ENOMEM; 531 return ERR_PTR(-ENOMEM);
402 } 532 }
403 533
404 req = p9_tag_alloc(c, tag); 534 req = p9_tag_alloc(c, tag);
535 if (IS_ERR(req))
536 return req;
405 537
406 /* if this is a flush request, backlink flush request now to 538 /* marshall the data */
407 * avoid race conditions later. */ 539 p9pdu_prepare(req->tc, tag, type);
408 if (tc->id == P9_TFLUSH) { 540 va_start(ap, fmt);
409 struct p9_req_t *other_req = 541 err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap);
410 p9_tag_lookup(c, tc->params.tflush.oldtag); 542 va_end(ap);
411 if (other_req->status == REQ_STATUS_FLSH) 543 p9pdu_finalize(req->tc);
412 other_req->flush_tag = tag;
413 }
414
415 p9_set_tag(tc, tag);
416
417 /*
418 * if client passed in a pre-allocated response fcall struct
419 * then we just use that, otherwise we allocate one.
420 */
421
422 if (rc == NULL)
423 req->rc = NULL;
424 else
425 req->rc = *rc;
426 if (req->rc == NULL) {
427 req->rc = kmalloc(sizeof(struct p9_fcall) + c->msize,
428 GFP_KERNEL);
429 if (!req->rc) {
430 err = -ENOMEM;
431 p9_idpool_put(tag, c->tagpool);
432 p9_free_req(c, req);
433 goto reterr;
434 }
435 *rc = req->rc;
436 }
437
438 rdata = (char *)req->rc+sizeof(struct p9_fcall);
439
440 req->tc = tc;
441 P9_DPRINTK(P9_DEBUG_9P, "request: tc: %p rc: %p\n", req->tc, req->rc);
442 544
443 err = c->trans_mod->request(c, req); 545 err = c->trans_mod->request(c, req);
444 if (err < 0) { 546 if (err < 0) {
@@ -447,28 +549,28 @@ p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
447 } 549 }
448 550
449 /* if it was a flush we just transmitted, return our tag */ 551 /* if it was a flush we just transmitted, return our tag */
450 if (tc->id == P9_TFLUSH) 552 if (type == P9_TFLUSH)
451 return 0; 553 return req;
452again: 554again:
453 P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d\n", req->wq, tag); 555 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
454 err = wait_event_interruptible(*req->wq, 556 err = wait_event_interruptible(*req->wq,
455 req->status >= REQ_STATUS_RCVD); 557 req->status >= REQ_STATUS_RCVD);
456 P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d returned %d (flushed=%d)\n", 558 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n",
457 req->wq, tag, err, flushed); 559 req->wq, tag, err, flushed);
458 560
459 if (req->status == REQ_STATUS_ERROR) { 561 if (req->status == REQ_STATUS_ERROR) {
460 P9_DPRINTK(P9_DEBUG_9P, "req_status error %d\n", req->t_err); 562 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
461 err = req->t_err; 563 err = req->t_err;
462 } else if (err == -ERESTARTSYS && flushed) { 564 } else if (err == -ERESTARTSYS && flushed) {
463 P9_DPRINTK(P9_DEBUG_9P, "flushed - going again\n"); 565 P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n");
464 goto again; 566 goto again;
465 } else if (req->status == REQ_STATUS_FLSHD) { 567 } else if (req->status == REQ_STATUS_FLSHD) {
466 P9_DPRINTK(P9_DEBUG_9P, "flushed - erestartsys\n"); 568 P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n");
467 err = -ERESTARTSYS; 569 err = -ERESTARTSYS;
468 } 570 }
469 571
470 if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) { 572 if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) {
471 P9_DPRINTK(P9_DEBUG_9P, "flushing\n"); 573 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
472 spin_lock_irqsave(&c->lock, flags); 574 spin_lock_irqsave(&c->lock, flags);
473 if (req->status == REQ_STATUS_SENT) 575 if (req->status == REQ_STATUS_SENT)
474 req->status = REQ_STATUS_FLSH; 576 req->status = REQ_STATUS_FLSH;
@@ -493,42 +595,17 @@ again:
493 if (err < 0) 595 if (err < 0)
494 goto reterr; 596 goto reterr;
495 597
496 size = le32_to_cpu(*(__le32 *) rdata); 598 err = p9_check_errors(c, req);
497 599 if (!err) {
498 err = p9_deserialize_fcall(rdata, size, req->rc, c->dotu); 600 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type);
499 if (err < 0) { 601 return req;
500 P9_DPRINTK(P9_DEBUG_9P,
501 "9p debug: client rpc deserialize returned %d\n", err);
502 goto reterr;
503 } 602 }
504 603
505 if (req->rc->id == P9_RERROR) {
506 int ecode = req->rc->params.rerror.errno;
507 struct p9_str *ename = &req->rc->params.rerror.error;
508
509 P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
510 ename->str);
511
512 if (c->dotu)
513 err = -ecode;
514
515 if (!err) {
516 err = p9_errstr2errno(ename->str, ename->len);
517
518 /* string match failed */
519 if (!err) {
520 PRINT_FCALL_ERROR("unknown error", req->rc);
521 err = -ESERVERFAULT;
522 }
523 }
524 } else
525 err = 0;
526
527reterr: 604reterr:
605 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type,
606 err);
528 p9_free_req(c, req); 607 p9_free_req(c, req);
529 608 return ERR_PTR(err);
530 P9_DPRINTK(P9_DEBUG_9P, "returning %d\n", err);
531 return err;
532} 609}
533 610
534static struct p9_fid *p9_fid_create(struct p9_client *clnt) 611static 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)
536 int err; 613 int err;
537 struct p9_fid *fid; 614 struct p9_fid *fid;
538 615
539 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 616 P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
540 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); 617 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
541 if (!fid) 618 if (!fid)
542 return ERR_PTR(-ENOMEM); 619 return ERR_PTR(-ENOMEM);
@@ -569,7 +646,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
569{ 646{
570 struct p9_client *clnt; 647 struct p9_client *clnt;
571 648
572 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 649 P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
573 clnt = fid->clnt; 650 clnt = fid->clnt;
574 p9_idpool_put(fid->fid, clnt->fidpool); 651 p9_idpool_put(fid->fid, clnt->fidpool);
575 spin_lock(&clnt->lock); 652 spin_lock(&clnt->lock);
@@ -578,49 +655,46 @@ static void p9_fid_destroy(struct p9_fid *fid)
578 kfree(fid); 655 kfree(fid);
579} 656}
580 657
581static int p9_client_version(struct p9_client *clnt) 658int p9_client_version(struct p9_client *c)
582{ 659{
583 int err = 0; 660 int err = 0;
584 struct p9_fcall *tc, *rc; 661 struct p9_req_t *req;
585 struct p9_str *version; 662 char *version;
663 int msize;
586 664
587 P9_DPRINTK(P9_DEBUG_9P, "%p\n", clnt); 665 P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n",
588 err = 0; 666 c->msize, c->dotu);
589 tc = NULL; 667 req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize,
590 rc = NULL; 668 c->dotu ? "9P2000.u" : "9P2000");
591 669 if (IS_ERR(req))
592 tc = p9_create_tversion(clnt->msize, 670 return PTR_ERR(req);
593 clnt->dotu ? "9P2000.u" : "9P2000");
594 if (IS_ERR(tc)) {
595 err = PTR_ERR(tc);
596 tc = NULL;
597 goto error;
598 }
599 671
600 err = p9_client_rpc(clnt, tc, &rc); 672 err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version);
601 if (err) 673 if (err) {
674 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
602 goto error; 675 goto error;
676 }
603 677
604 version = &rc->params.rversion.version; 678 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
605 if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8)) 679 if (!memcmp(version, "9P2000.u", 8))
606 clnt->dotu = 1; 680 c->dotu = 1;
607 else if (version->len == 6 && !memcmp(version->str, "9P2000", 6)) 681 else if (!memcmp(version, "9P2000", 6))
608 clnt->dotu = 0; 682 c->dotu = 0;
609 else { 683 else {
610 err = -EREMOTEIO; 684 err = -EREMOTEIO;
611 goto error; 685 goto error;
612 } 686 }
613 687
614 if (rc->params.rversion.msize < clnt->msize) 688 if (msize < c->msize)
615 clnt->msize = rc->params.rversion.msize; 689 c->msize = msize;
616 690
617error: 691error:
618 kfree(tc); 692 kfree(version);
619 kfree(rc); 693 p9_free_req(c, req);
620 694
621 return err; 695 return err;
622} 696}
623EXPORT_SYMBOL(p9_client_auth); 697EXPORT_SYMBOL(p9_client_version);
624 698
625struct p9_client *p9_client_create(const char *dev_name, char *options) 699struct p9_client *p9_client_create(const char *dev_name, char *options)
626{ 700{
@@ -656,7 +730,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
656 goto error; 730 goto error;
657 } 731 }
658 732
659 P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", 733 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
660 clnt, clnt->trans_mod, clnt->msize, clnt->dotu); 734 clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
661 735
662 err = clnt->trans_mod->create(clnt, dev_name, options); 736 err = clnt->trans_mod->create(clnt, dev_name, options);
@@ -682,7 +756,7 @@ void p9_client_destroy(struct p9_client *clnt)
682{ 756{
683 struct p9_fid *fid, *fidptr; 757 struct p9_fid *fid, *fidptr;
684 758
685 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 759 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt);
686 760
687 if (clnt->trans_mod) 761 if (clnt->trans_mod)
688 clnt->trans_mod->close(clnt); 762 clnt->trans_mod->close(clnt);
@@ -712,14 +786,13 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
712 char *uname, u32 n_uname, char *aname) 786 char *uname, u32 n_uname, char *aname)
713{ 787{
714 int err; 788 int err;
715 struct p9_fcall *tc, *rc; 789 struct p9_req_t *req;
716 struct p9_fid *fid; 790 struct p9_fid *fid;
791 struct p9_qid qid;
717 792
718 P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n", 793 P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
719 clnt, afid?afid->fid:-1, uname, aname); 794 afid ? afid->fid : -1, uname, aname);
720 err = 0; 795 err = 0;
721 tc = NULL;
722 rc = NULL;
723 796
724 fid = p9_fid_create(clnt); 797 fid = p9_fid_create(clnt);
725 if (IS_ERR(fid)) { 798 if (IS_ERR(fid)) {
@@ -728,73 +801,75 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
728 goto error; 801 goto error;
729 } 802 }
730 803
731 tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname, 804 req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
732 n_uname, clnt->dotu); 805 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
733 if (IS_ERR(tc)) { 806 if (IS_ERR(req)) {
734 err = PTR_ERR(tc); 807 err = PTR_ERR(req);
735 tc = NULL;
736 goto error; 808 goto error;
737 } 809 }
738 810
739 err = p9_client_rpc(clnt, tc, &rc); 811 err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
740 if (err) 812 if (err) {
813 p9_free_req(clnt, req);
741 goto error; 814 goto error;
815 }
742 816
743 memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid)); 817 P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
744 kfree(tc); 818 qid.type, qid.path, qid.version);
745 kfree(rc); 819
820 memmove(&fid->qid, &qid, sizeof(struct p9_qid));
821
822 p9_free_req(clnt, req);
746 return fid; 823 return fid;
747 824
748error: 825error:
749 kfree(tc);
750 kfree(rc);
751 if (fid) 826 if (fid)
752 p9_fid_destroy(fid); 827 p9_fid_destroy(fid);
753 return ERR_PTR(err); 828 return ERR_PTR(err);
754} 829}
755EXPORT_SYMBOL(p9_client_attach); 830EXPORT_SYMBOL(p9_client_attach);
756 831
757struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, 832struct p9_fid *
758 u32 n_uname, char *aname) 833p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
759{ 834{
760 int err; 835 int err;
761 struct p9_fcall *tc, *rc; 836 struct p9_req_t *req;
762 struct p9_fid *fid; 837 struct p9_qid qid;
838 struct p9_fid *afid;
763 839
764 P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname, 840 P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
765 aname);
766 err = 0; 841 err = 0;
767 tc = NULL;
768 rc = NULL;
769 842
770 fid = p9_fid_create(clnt); 843 afid = p9_fid_create(clnt);
771 if (IS_ERR(fid)) { 844 if (IS_ERR(afid)) {
772 err = PTR_ERR(fid); 845 err = PTR_ERR(afid);
773 fid = NULL; 846 afid = NULL;
774 goto error; 847 goto error;
775 } 848 }
776 849
777 tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu); 850 req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
778 if (IS_ERR(tc)) { 851 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
779 err = PTR_ERR(tc); 852 if (IS_ERR(req)) {
780 tc = NULL; 853 err = PTR_ERR(req);
781 goto error; 854 goto error;
782 } 855 }
783 856
784 err = p9_client_rpc(clnt, tc, &rc); 857 err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
785 if (err) 858 if (err) {
859 p9_free_req(clnt, req);
786 goto error; 860 goto error;
861 }
787 862
788 memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid)); 863 P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
789 kfree(tc); 864 qid.type, qid.path, qid.version);
790 kfree(rc); 865
791 return fid; 866 memmove(&afid->qid, &qid, sizeof(struct p9_qid));
867 p9_free_req(clnt, req);
868 return afid;
792 869
793error: 870error:
794 kfree(tc); 871 if (afid)
795 kfree(rc); 872 p9_fid_destroy(afid);
796 if (fid)
797 p9_fid_destroy(fid);
798 return ERR_PTR(err); 873 return ERR_PTR(err);
799} 874}
800EXPORT_SYMBOL(p9_client_auth); 875EXPORT_SYMBOL(p9_client_auth);
@@ -803,15 +878,13 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
803 int clone) 878 int clone)
804{ 879{
805 int err; 880 int err;
806 struct p9_fcall *tc, *rc;
807 struct p9_client *clnt; 881 struct p9_client *clnt;
808 struct p9_fid *fid; 882 struct p9_fid *fid;
883 struct p9_qid *wqids;
884 struct p9_req_t *req;
885 int16_t nwqids, count;
809 886
810 P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
811 oldfid->fid, nwname, wnames?wnames[0]:NULL);
812 err = 0; 887 err = 0;
813 tc = NULL;
814 rc = NULL;
815 clnt = oldfid->clnt; 888 clnt = oldfid->clnt;
816 if (clone) { 889 if (clone) {
817 fid = p9_fid_create(clnt); 890 fid = p9_fid_create(clnt);
@@ -825,53 +898,46 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
825 } else 898 } else
826 fid = oldfid; 899 fid = oldfid;
827 900
828 tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames); 901
829 if (IS_ERR(tc)) { 902 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
830 err = PTR_ERR(tc); 903 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
831 tc = NULL; 904
905 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
906 nwname, wnames);
907 if (IS_ERR(req)) {
908 err = PTR_ERR(req);
832 goto error; 909 goto error;
833 } 910 }
834 911
835 err = p9_client_rpc(clnt, tc, &rc); 912 err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids);
836 if (err) { 913 p9_free_req(clnt, req);
837 if (rc && rc->id == P9_RWALK) 914 if (err)
838 goto clunk_fid; 915 goto clunk_fid;
839 else
840 goto error;
841 }
842 916
843 if (rc->params.rwalk.nwqid != nwname) { 917 P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
918
919 if (nwqids != nwname) {
844 err = -ENOENT; 920 err = -ENOENT;
845 goto clunk_fid; 921 goto clunk_fid;
846 } 922 }
847 923
924 for (count = 0; count < nwqids; count++)
925 P9_DPRINTK(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n",
926 count, wqids[count].type, wqids[count].path,
927 wqids[count].version);
928
848 if (nwname) 929 if (nwname)
849 memmove(&fid->qid, 930 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
850 &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
851 sizeof(struct p9_qid));
852 else 931 else
853 fid->qid = oldfid->qid; 932 fid->qid = oldfid->qid;
854 933
855 kfree(tc);
856 kfree(rc);
857 return fid; 934 return fid;
858 935
859clunk_fid: 936clunk_fid:
860 kfree(tc); 937 p9_client_clunk(fid);
861 kfree(rc); 938 fid = NULL;
862 rc = NULL;
863 tc = p9_create_tclunk(fid->fid);
864 if (IS_ERR(tc)) {
865 err = PTR_ERR(tc);
866 tc = NULL;
867 goto error;
868 }
869
870 p9_client_rpc(clnt, tc, &rc);
871 939
872error: 940error:
873 kfree(tc);
874 kfree(rc);
875 if (fid && (fid != oldfid)) 941 if (fid && (fid != oldfid))
876 p9_fid_destroy(fid); 942 p9_fid_destroy(fid);
877 943
@@ -882,35 +948,36 @@ EXPORT_SYMBOL(p9_client_walk);
882int p9_client_open(struct p9_fid *fid, int mode) 948int p9_client_open(struct p9_fid *fid, int mode)
883{ 949{
884 int err; 950 int err;
885 struct p9_fcall *tc, *rc;
886 struct p9_client *clnt; 951 struct p9_client *clnt;
952 struct p9_req_t *req;
953 struct p9_qid qid;
954 int iounit;
887 955
888 P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode); 956 P9_DPRINTK(P9_DEBUG_9P, ">>> TOPEN fid %d mode %d\n", fid->fid, mode);
889 err = 0; 957 err = 0;
890 tc = NULL;
891 rc = NULL;
892 clnt = fid->clnt; 958 clnt = fid->clnt;
893 959
894 if (fid->mode != -1) 960 if (fid->mode != -1)
895 return -EINVAL; 961 return -EINVAL;
896 962
897 tc = p9_create_topen(fid->fid, mode); 963 req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
898 if (IS_ERR(tc)) { 964 if (IS_ERR(req)) {
899 err = PTR_ERR(tc); 965 err = PTR_ERR(req);
900 tc = NULL; 966 goto error;
901 goto done;
902 } 967 }
903 968
904 err = p9_client_rpc(clnt, tc, &rc); 969 err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
970 p9_free_req(clnt, req);
905 if (err) 971 if (err)
906 goto done; 972 goto error;
973
974 P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n",
975 qid.type, qid.path, qid.version, iounit);
907 976
908 fid->mode = mode; 977 fid->mode = mode;
909 fid->iounit = rc->params.ropen.iounit; 978 fid->iounit = iounit;
910 979
911done: 980error:
912 kfree(tc);
913 kfree(rc);
914 return err; 981 return err;
915} 982}
916EXPORT_SYMBOL(p9_client_open); 983EXPORT_SYMBOL(p9_client_open);
@@ -919,37 +986,38 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
919 char *extension) 986 char *extension)
920{ 987{
921 int err; 988 int err;
922 struct p9_fcall *tc, *rc;
923 struct p9_client *clnt; 989 struct p9_client *clnt;
990 struct p9_req_t *req;
991 struct p9_qid qid;
992 int iounit;
924 993
925 P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid, 994 P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
926 name, perm, mode); 995 fid->fid, name, perm, mode);
927 err = 0; 996 err = 0;
928 tc = NULL;
929 rc = NULL;
930 clnt = fid->clnt; 997 clnt = fid->clnt;
931 998
932 if (fid->mode != -1) 999 if (fid->mode != -1)
933 return -EINVAL; 1000 return -EINVAL;
934 1001
935 tc = p9_create_tcreate(fid->fid, name, perm, mode, extension, 1002 req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
936 clnt->dotu); 1003 mode, extension);
937 if (IS_ERR(tc)) { 1004 if (IS_ERR(req)) {
938 err = PTR_ERR(tc); 1005 err = PTR_ERR(req);
939 tc = NULL; 1006 goto error;
940 goto done;
941 } 1007 }
942 1008
943 err = p9_client_rpc(clnt, tc, &rc); 1009 err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
1010 p9_free_req(clnt, req);
944 if (err) 1011 if (err)
945 goto done; 1012 goto error;
1013
1014 P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
1015 qid.type, qid.path, qid.version, iounit);
946 1016
947 fid->mode = mode; 1017 fid->mode = mode;
948 fid->iounit = rc->params.ropen.iounit; 1018 fid->iounit = iounit;
949 1019
950done: 1020error:
951 kfree(tc);
952 kfree(rc);
953 return err; 1021 return err;
954} 1022}
955EXPORT_SYMBOL(p9_client_fcreate); 1023EXPORT_SYMBOL(p9_client_fcreate);
@@ -957,31 +1025,25 @@ EXPORT_SYMBOL(p9_client_fcreate);
957int p9_client_clunk(struct p9_fid *fid) 1025int p9_client_clunk(struct p9_fid *fid)
958{ 1026{
959 int err; 1027 int err;
960 struct p9_fcall *tc, *rc;
961 struct p9_client *clnt; 1028 struct p9_client *clnt;
1029 struct p9_req_t *req;
962 1030
963 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 1031 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
964 err = 0; 1032 err = 0;
965 tc = NULL;
966 rc = NULL;
967 clnt = fid->clnt; 1033 clnt = fid->clnt;
968 1034
969 tc = p9_create_tclunk(fid->fid); 1035 req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
970 if (IS_ERR(tc)) { 1036 if (IS_ERR(req)) {
971 err = PTR_ERR(tc); 1037 err = PTR_ERR(req);
972 tc = NULL; 1038 goto error;
973 goto done;
974 } 1039 }
975 1040
976 err = p9_client_rpc(clnt, tc, &rc); 1041 P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
977 if (err)
978 goto done;
979 1042
1043 p9_free_req(clnt, req);
980 p9_fid_destroy(fid); 1044 p9_fid_destroy(fid);
981 1045
982done: 1046error:
983 kfree(tc);
984 kfree(rc);
985 return err; 1047 return err;
986} 1048}
987EXPORT_SYMBOL(p9_client_clunk); 1049EXPORT_SYMBOL(p9_client_clunk);
@@ -989,31 +1051,25 @@ EXPORT_SYMBOL(p9_client_clunk);
989int p9_client_remove(struct p9_fid *fid) 1051int p9_client_remove(struct p9_fid *fid)
990{ 1052{
991 int err; 1053 int err;
992 struct p9_fcall *tc, *rc;
993 struct p9_client *clnt; 1054 struct p9_client *clnt;
1055 struct p9_req_t *req;
994 1056
995 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 1057 P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
996 err = 0; 1058 err = 0;
997 tc = NULL;
998 rc = NULL;
999 clnt = fid->clnt; 1059 clnt = fid->clnt;
1000 1060
1001 tc = p9_create_tremove(fid->fid); 1061 req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
1002 if (IS_ERR(tc)) { 1062 if (IS_ERR(req)) {
1003 err = PTR_ERR(tc); 1063 err = PTR_ERR(req);
1004 tc = NULL; 1064 goto error;
1005 goto done;
1006 } 1065 }
1007 1066
1008 err = p9_client_rpc(clnt, tc, &rc); 1067 P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
1009 if (err)
1010 goto done;
1011 1068
1069 p9_free_req(clnt, req);
1012 p9_fid_destroy(fid); 1070 p9_fid_destroy(fid);
1013 1071
1014done: 1072error:
1015 kfree(tc);
1016 kfree(rc);
1017 return err; 1073 return err;
1018} 1074}
1019EXPORT_SYMBOL(p9_client_remove); 1075EXPORT_SYMBOL(p9_client_remove);
@@ -1022,15 +1078,14 @@ int
1022p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1078p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1023 u32 count) 1079 u32 count)
1024{ 1080{
1025 int err, n, rsize, total; 1081 int err, rsize, total;
1026 struct p9_fcall *tc, *rc;
1027 struct p9_client *clnt; 1082 struct p9_client *clnt;
1083 struct p9_req_t *req;
1084 char *dataptr;
1028 1085
1029 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid, 1086 P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
1030 (long long unsigned) offset, count); 1087 (long long unsigned) offset, count);
1031 err = 0; 1088 err = 0;
1032 tc = NULL;
1033 rc = NULL;
1034 clnt = fid->clnt; 1089 clnt = fid->clnt;
1035 total = 0; 1090 total = 0;
1036 1091
@@ -1038,53 +1093,40 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1038 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1093 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1039 rsize = clnt->msize - P9_IOHDRSZ; 1094 rsize = clnt->msize - P9_IOHDRSZ;
1040 1095
1041 do { 1096 if (count < rsize)
1042 if (count < rsize) 1097 rsize = count;
1043 rsize = count;
1044 1098
1045 tc = p9_create_tread(fid->fid, offset, rsize); 1099 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
1046 if (IS_ERR(tc)) { 1100 if (IS_ERR(req)) {
1047 err = PTR_ERR(tc); 1101 err = PTR_ERR(req);
1048 tc = NULL; 1102 goto error;
1049 goto error; 1103 }
1050 }
1051 1104
1052 err = p9_client_rpc(clnt, tc, &rc); 1105 err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr);
1053 if (err) 1106 if (err)
1054 goto error; 1107 goto free_and_error;
1055 1108
1056 n = rc->params.rread.count; 1109 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1057 if (n > count)
1058 n = count;
1059 1110
1060 if (data) { 1111 if (data) {
1061 memmove(data, rc->params.rread.data, n); 1112 memmove(data, dataptr, count);
1062 data += n; 1113 data += count;
1063 } 1114 }
1064 1115
1065 if (udata) { 1116 if (udata) {
1066 err = copy_to_user(udata, rc->params.rread.data, n); 1117 err = copy_to_user(udata, dataptr, count);
1067 if (err) { 1118 if (err) {
1068 err = -EFAULT; 1119 err = -EFAULT;
1069 goto error; 1120 goto free_and_error;
1070 }
1071 udata += n;
1072 } 1121 }
1122 }
1073 1123
1074 count -= n; 1124 p9_free_req(clnt, req);
1075 offset += n; 1125 return count;
1076 total += n;
1077 kfree(tc);
1078 tc = NULL;
1079 kfree(rc);
1080 rc = NULL;
1081 } while (count > 0 && n == rsize);
1082
1083 return total;
1084 1126
1127free_and_error:
1128 p9_free_req(clnt, req);
1085error: 1129error:
1086 kfree(tc);
1087 kfree(rc);
1088 return err; 1130 return err;
1089} 1131}
1090EXPORT_SYMBOL(p9_client_read); 1132EXPORT_SYMBOL(p9_client_read);
@@ -1093,15 +1135,13 @@ int
1093p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 1135p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1094 u64 offset, u32 count) 1136 u64 offset, u32 count)
1095{ 1137{
1096 int err, n, rsize, total; 1138 int err, rsize, total;
1097 struct p9_fcall *tc, *rc;
1098 struct p9_client *clnt; 1139 struct p9_client *clnt;
1140 struct p9_req_t *req;
1099 1141
1100 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, 1142 P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1101 (long long unsigned) offset, count); 1143 fid->fid, (long long unsigned) offset, count);
1102 err = 0; 1144 err = 0;
1103 tc = NULL;
1104 rc = NULL;
1105 clnt = fid->clnt; 1145 clnt = fid->clnt;
1106 total = 0; 1146 total = 0;
1107 1147
@@ -1109,129 +1149,70 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1109 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1149 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1110 rsize = clnt->msize - P9_IOHDRSZ; 1150 rsize = clnt->msize - P9_IOHDRSZ;
1111 1151
1112 do { 1152 if (count < rsize)
1113 if (count < rsize) 1153 rsize = count;
1114 rsize = count; 1154 if (data)
1115 1155 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
1116 if (data) 1156 rsize, data);
1117 tc = p9_create_twrite(fid->fid, offset, rsize, data); 1157 else
1118 else 1158 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
1119 tc = p9_create_twrite_u(fid->fid, offset, rsize, udata); 1159 rsize, udata);
1120 if (IS_ERR(tc)) { 1160 if (IS_ERR(req)) {
1121 err = PTR_ERR(tc); 1161 err = PTR_ERR(req);
1122 tc = NULL; 1162 goto error;
1123 goto error; 1163 }
1124 }
1125
1126 err = p9_client_rpc(clnt, tc, &rc);
1127 if (err)
1128 goto error;
1129
1130 n = rc->params.rread.count;
1131 count -= n;
1132
1133 if (data)
1134 data += n;
1135 else
1136 udata += n;
1137 1164
1138 offset += n; 1165 err = p9pdu_readf(req->rc, clnt->dotu, "d", &count);
1139 total += n; 1166 if (err)
1140 kfree(tc); 1167 goto free_and_error;
1141 tc = NULL; 1168 P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1142 kfree(rc);
1143 rc = NULL;
1144 } while (count > 0);
1145 1169
1146 return total; 1170 p9_free_req(clnt, req);
1171 return count;
1147 1172
1173free_and_error:
1174 p9_free_req(clnt, req);
1148error: 1175error:
1149 kfree(tc);
1150 kfree(rc);
1151 return err; 1176 return err;
1152} 1177}
1153EXPORT_SYMBOL(p9_client_write); 1178EXPORT_SYMBOL(p9_client_write);
1154 1179
1155static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu) 1180struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1156{ 1181{
1157 int n; 1182 int err;
1158 char *p; 1183 struct p9_client *clnt;
1159 struct p9_stat *ret; 1184 struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
1160 1185 struct p9_req_t *req;
1161 n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len + 1186 u16 ignored;
1162 st->muid.len;
1163 1187
1164 if (dotu) 1188 P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1165 n += st->extension.len;
1166 1189
1167 ret = kmalloc(n, GFP_KERNEL);
1168 if (!ret) 1190 if (!ret)
1169 return ERR_PTR(-ENOMEM); 1191 return ERR_PTR(-ENOMEM);
1170 1192
1171 memmove(ret, st, sizeof(struct p9_stat));
1172 p = ((char *) ret) + sizeof(struct p9_stat);
1173 memmove(p, st->name.str, st->name.len);
1174 ret->name.str = p;
1175 p += st->name.len;
1176 memmove(p, st->uid.str, st->uid.len);
1177 ret->uid.str = p;
1178 p += st->uid.len;
1179 memmove(p, st->gid.str, st->gid.len);
1180 ret->gid.str = p;
1181 p += st->gid.len;
1182 memmove(p, st->muid.str, st->muid.len);
1183 ret->muid.str = p;
1184 p += st->muid.len;
1185
1186 if (dotu) {
1187 memmove(p, st->extension.str, st->extension.len);
1188 ret->extension.str = p;
1189 p += st->extension.len;
1190 }
1191
1192 return ret;
1193}
1194
1195struct p9_stat *p9_client_stat(struct p9_fid *fid)
1196{
1197 int err;
1198 struct p9_fcall *tc, *rc;
1199 struct p9_client *clnt;
1200 struct p9_stat *ret;
1201
1202 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
1203 err = 0; 1193 err = 0;
1204 tc = NULL;
1205 rc = NULL;
1206 ret = NULL;
1207 clnt = fid->clnt; 1194 clnt = fid->clnt;
1208 1195
1209 tc = p9_create_tstat(fid->fid); 1196 req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
1210 if (IS_ERR(tc)) { 1197 if (IS_ERR(req)) {
1211 err = PTR_ERR(tc); 1198 err = PTR_ERR(req);
1212 tc = NULL;
1213 goto error; 1199 goto error;
1214 } 1200 }
1215 1201
1216 err = p9_client_rpc(clnt, tc, &rc); 1202 err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
1203 p9_free_req(clnt, req);
1217 if (err) 1204 if (err)
1218 goto error; 1205 goto error;
1219 1206
1220 ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu); 1207 P9_DPRINTK(P9_DEBUG_9P,
1221 if (IS_ERR(ret)) { 1208 "<<< RSTAT sz=%x type=%x dev=%x qid=%2.2x %4.4x %8.8llx"
1222 err = PTR_ERR(ret); 1209 " mode=%8.8x uid=%d gid=%d size=%lld %s\n",
1223 ret = NULL; 1210 ret->size, ret->type, ret->dev, ret->qid.type,
1224 goto error; 1211 ret->qid.version, ret->qid.path, ret->mode,
1225 } 1212 ret->n_uid, ret->n_gid, ret->length, ret->name);
1226 1213
1227 kfree(tc);
1228 kfree(rc);
1229 return ret; 1214 return ret;
1230
1231error: 1215error:
1232 kfree(tc);
1233 kfree(rc);
1234 kfree(ret);
1235 return ERR_PTR(err); 1216 return ERR_PTR(err);
1236} 1217}
1237EXPORT_SYMBOL(p9_client_stat); 1218EXPORT_SYMBOL(p9_client_stat);
@@ -1239,27 +1220,23 @@ EXPORT_SYMBOL(p9_client_stat);
1239int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) 1220int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
1240{ 1221{
1241 int err; 1222 int err;
1242 struct p9_fcall *tc, *rc; 1223 struct p9_req_t *req;
1243 struct p9_client *clnt; 1224 struct p9_client *clnt;
1244 1225
1245 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 1226 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
1246 err = 0; 1227 err = 0;
1247 tc = NULL;
1248 rc = NULL;
1249 clnt = fid->clnt; 1228 clnt = fid->clnt;
1250 1229
1251 tc = p9_create_twstat(fid->fid, wst, clnt->dotu); 1230 req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst);
1252 if (IS_ERR(tc)) { 1231 if (IS_ERR(req)) {
1253 err = PTR_ERR(tc); 1232 err = PTR_ERR(req);
1254 tc = NULL; 1233 goto error;
1255 goto done;
1256 } 1234 }
1257 1235
1258 err = p9_client_rpc(clnt, tc, &rc); 1236 P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
1259 1237
1260done: 1238 p9_free_req(clnt, req);
1261 kfree(tc); 1239error:
1262 kfree(rc);
1263 return err; 1240 return err;
1264} 1241}
1265EXPORT_SYMBOL(p9_client_wstat); 1242EXPORT_SYMBOL(p9_client_wstat);
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 43e98220e9a4..4ebeffd21d3d 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -27,6 +27,7 @@
27 27
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/uaccess.h>
30#include <net/9p/9p.h> 31#include <net/9p/9p.h>
31#include <net/9p/client.h> 32#include <net/9p/client.h>
32#include "protocol.h" 33#include "protocol.h"
@@ -51,6 +52,38 @@
51static int 52static int
52p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...); 53p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...);
53 54
55#define PACKET_DEBUG 0
56
57void
58p9pdu_dump(int way, struct p9_fcall *pdu)
59{
60 int i, n;
61 u8 *data = pdu->sdata;
62 int datalen = pdu->size;
63 char buf[255];
64 int buflen = 255;
65
66 i = n = 0;
67 if (datalen > (buflen-16))
68 datalen = buflen-16;
69 while (i < datalen) {
70 n += scnprintf(buf + n, buflen - n, "%02x ", data[i]);
71 if (i%4 == 3)
72 n += scnprintf(buf + n, buflen - n, " ");
73 if (i%32 == 31)
74 n += scnprintf(buf + n, buflen - n, "\n");
75
76 i++;
77 }
78 n += scnprintf(buf + n, buflen - n, "\n");
79
80 if (way)
81 printk(KERN_NOTICE "[[(%d)[ %s\n", datalen, buf);
82 else
83 printk(KERN_NOTICE "]](%d)] %s\n", datalen, buf);
84}
85EXPORT_SYMBOL(p9pdu_dump);
86
54void p9stat_free(struct p9_wstat *stbuf) 87void p9stat_free(struct p9_wstat *stbuf)
55{ 88{
56 kfree(stbuf->name); 89 kfree(stbuf->name);
@@ -77,6 +110,18 @@ static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size)
77 return size - len; 110 return size - len;
78} 111}
79 112
113static size_t
114pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
115{
116 size_t len = MIN(pdu->capacity - pdu->size, size);
117 int err = copy_from_user(&pdu->sdata[pdu->size], udata, len);
118 if (err)
119 printk(KERN_WARNING "pdu_write_u returning: %d\n", err);
120
121 pdu->size += len;
122 return size - len;
123}
124
80/* 125/*
81 b - int8_t 126 b - int8_t
82 w - int16_t 127 w - int16_t
@@ -174,7 +219,6 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
174 stbuf->extension = NULL; 219 stbuf->extension = NULL;
175 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = 220 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
176 -1; 221 -1;
177
178 errcode = 222 errcode =
179 p9pdu_readf(pdu, optional, 223 p9pdu_readf(pdu, optional,
180 "wwdQdddqssss?sddd", 224 "wwdQdddqssss?sddd",
@@ -332,7 +376,6 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
332 case 's':{ 376 case 's':{
333 const char *ptr = va_arg(ap, const char *); 377 const char *ptr = va_arg(ap, const char *);
334 int16_t len = 0; 378 int16_t len = 0;
335
336 if (ptr) 379 if (ptr)
337 len = MIN(strlen(ptr), USHORT_MAX); 380 len = MIN(strlen(ptr), USHORT_MAX);
338 381
@@ -356,7 +399,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
356 p9pdu_writef(pdu, optional, 399 p9pdu_writef(pdu, optional,
357 "wwdQdddqssss?sddd", 400 "wwdQdddqssss?sddd",
358 stbuf->size, stbuf->type, 401 stbuf->size, stbuf->type,
359 stbuf->dev, stbuf->qid, 402 stbuf->dev, &stbuf->qid,
360 stbuf->mode, stbuf->atime, 403 stbuf->mode, stbuf->atime,
361 stbuf->mtime, stbuf->length, 404 stbuf->mtime, stbuf->length,
362 stbuf->name, stbuf->uid, 405 stbuf->name, stbuf->uid,
@@ -374,6 +417,16 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
374 errcode = -EFAULT; 417 errcode = -EFAULT;
375 } 418 }
376 break; 419 break;
420 case 'U':{
421 int32_t count = va_arg(ap, int32_t);
422 const char __user *udata =
423 va_arg(ap, const void *);
424 errcode =
425 p9pdu_writef(pdu, optional, "d", count);
426 if (!errcode && pdu_write_u(pdu, udata, count))
427 errcode = -EFAULT;
428 }
429 break;
377 case 'T':{ 430 case 'T':{
378 int16_t nwname = va_arg(ap, int); 431 int16_t nwname = va_arg(ap, int);
379 const char **wnames = va_arg(ap, const char **); 432 const char **wnames = va_arg(ap, const char **);
@@ -455,3 +508,29 @@ p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...)
455 508
456 return ret; 509 return ret;
457} 510}
511
512int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
513{
514 return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
515}
516
517int p9pdu_finalize(struct p9_fcall *pdu)
518{
519 int size = pdu->size;
520 int err;
521
522 pdu->size = 0;
523 err = p9pdu_writef(pdu, 0, "d", size);
524 pdu->size = size;
525
526 if (PACKET_DEBUG)
527 p9pdu_dump(0, pdu);
528
529 return err;
530}
531
532void p9pdu_reset(struct p9_fcall *pdu)
533{
534 pdu->offset = 0;
535 pdu->size = 0;
536}
diff --git a/net/9p/protocol.h b/net/9p/protocol.h
index 596ee10d506f..ccde462e7ac5 100644
--- a/net/9p/protocol.h
+++ b/net/9p/protocol.h
@@ -27,5 +27,8 @@
27 27
28int 28int
29p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap); 29p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap);
30
31int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...); 30int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...);
31int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type);
32int p9pdu_finalize(struct p9_fcall *pdu);
33void p9pdu_dump(int, struct p9_fcall *);
34void p9pdu_reset(struct p9_fcall *pdu);
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index e147ec539585..e8ebe2cb7e8b 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)
181 * 181 *
182 */ 182 */
183 183
184void p9_conn_cancel(struct p9_conn *m, int err) 184static void p9_conn_cancel(struct p9_conn *m, int err)
185{ 185{
186 struct p9_req_t *req, *rtmp; 186 struct p9_req_t *req, *rtmp;
187 unsigned long flags; 187 unsigned long flags;
@@ -287,7 +287,7 @@ static void p9_read_work(struct work_struct *work)
287 if (m->err < 0) 287 if (m->err < 0)
288 return; 288 return;
289 289
290 P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); 290 P9_DPRINTK(P9_DEBUG_TRANS, "start mux %p pos %d\n", m, m->rpos);
291 291
292 if (!m->rbuf) { 292 if (!m->rbuf) {
293 m->rbuf = m->tmp_buf; 293 m->rbuf = m->tmp_buf;
@@ -296,11 +296,11 @@ static void p9_read_work(struct work_struct *work)
296 } 296 }
297 297
298 clear_bit(Rpending, &m->wsched); 298 clear_bit(Rpending, &m->wsched);
299 P9_DPRINTK(P9_DEBUG_MUX, "read mux %p pos %d size: %d = %d\n", m, 299 P9_DPRINTK(P9_DEBUG_TRANS, "read mux %p pos %d size: %d = %d\n", m,
300 m->rpos, m->rsize, m->rsize-m->rpos); 300 m->rpos, m->rsize, m->rsize-m->rpos);
301 err = p9_fd_read(m->client, m->rbuf + m->rpos, 301 err = p9_fd_read(m->client, m->rbuf + m->rpos,
302 m->rsize - m->rpos); 302 m->rsize - m->rpos);
303 P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err); 303 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
304 if (err == -EAGAIN) { 304 if (err == -EAGAIN) {
305 clear_bit(Rworksched, &m->wsched); 305 clear_bit(Rworksched, &m->wsched);
306 return; 306 return;
@@ -313,7 +313,7 @@ static void p9_read_work(struct work_struct *work)
313 313
314 if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */ 314 if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */
315 u16 tag; 315 u16 tag;
316 P9_DPRINTK(P9_DEBUG_MUX, "got new header\n"); 316 P9_DPRINTK(P9_DEBUG_TRANS, "got new header\n");
317 317
318 n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */ 318 n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */
319 if (n >= m->client->msize) { 319 if (n >= m->client->msize) {
@@ -324,8 +324,8 @@ static void p9_read_work(struct work_struct *work)
324 } 324 }
325 325
326 tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */ 326 tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */
327 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pkt: size: %d bytes tag: %d\n", 327 P9_DPRINTK(P9_DEBUG_TRANS,
328 m, n, tag); 328 "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag);
329 329
330 m->req = p9_tag_lookup(m->client, tag); 330 m->req = p9_tag_lookup(m->client, tag);
331 if (!m->req) { 331 if (!m->req) {
@@ -351,7 +351,7 @@ static void p9_read_work(struct work_struct *work)
351 351
352 /* not an else because some packets (like clunk) have no payload */ 352 /* not an else because some packets (like clunk) have no payload */
353 if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ 353 if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */
354 P9_DPRINTK(P9_DEBUG_MUX, "got new packet\n"); 354 P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n");
355 355
356 list_del(&m->req->req_list); 356 list_del(&m->req->req_list);
357 p9_client_cb(m->client, m->req); 357 p9_client_cb(m->client, m->req);
@@ -369,7 +369,7 @@ static void p9_read_work(struct work_struct *work)
369 n = p9_fd_poll(m->client, NULL); 369 n = p9_fd_poll(m->client, NULL);
370 370
371 if (n & POLLIN) { 371 if (n & POLLIN) {
372 P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); 372 P9_DPRINTK(P9_DEBUG_TRANS, "sched read work %p\n", m);
373 queue_work(p9_mux_wq, &m->rq); 373 queue_work(p9_mux_wq, &m->rq);
374 } else 374 } else
375 clear_bit(Rworksched, &m->wsched); 375 clear_bit(Rworksched, &m->wsched);
@@ -453,11 +453,11 @@ static void p9_write_work(struct work_struct *work)
453 spin_unlock(&m->client->lock); 453 spin_unlock(&m->client->lock);
454 } 454 }
455 455
456 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, 456 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p pos %d size %d\n", m, m->wpos,
457 m->wsize); 457 m->wsize);
458 clear_bit(Wpending, &m->wsched); 458 clear_bit(Wpending, &m->wsched);
459 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos); 459 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
460 P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err); 460 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
461 if (err == -EAGAIN) { 461 if (err == -EAGAIN) {
462 clear_bit(Wworksched, &m->wsched); 462 clear_bit(Wworksched, &m->wsched);
463 return; 463 return;
@@ -481,7 +481,7 @@ static void p9_write_work(struct work_struct *work)
481 n = p9_fd_poll(m->client, NULL); 481 n = p9_fd_poll(m->client, NULL);
482 482
483 if (n & POLLOUT) { 483 if (n & POLLOUT) {
484 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); 484 P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m);
485 queue_work(p9_mux_wq, &m->wq); 485 queue_work(p9_mux_wq, &m->wq);
486 } else 486 } else
487 clear_bit(Wworksched, &m->wsched); 487 clear_bit(Wworksched, &m->wsched);
@@ -558,7 +558,8 @@ static struct p9_conn *p9_conn_create(struct p9_client *client)
558 int n; 558 int n;
559 struct p9_conn *m; 559 struct p9_conn *m;
560 560
561 P9_DPRINTK(P9_DEBUG_MUX, "client %p msize %d\n", client, client->msize); 561 P9_DPRINTK(P9_DEBUG_TRANS, "client %p msize %d\n", client,
562 client->msize);
562 m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL); 563 m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
563 if (!m) 564 if (!m)
564 return ERR_PTR(-ENOMEM); 565 return ERR_PTR(-ENOMEM);
@@ -575,12 +576,12 @@ static struct p9_conn *p9_conn_create(struct p9_client *client)
575 576
576 n = p9_fd_poll(client, &m->pt); 577 n = p9_fd_poll(client, &m->pt);
577 if (n & POLLIN) { 578 if (n & POLLIN) {
578 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); 579 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can read\n", m);
579 set_bit(Rpending, &m->wsched); 580 set_bit(Rpending, &m->wsched);
580 } 581 }
581 582
582 if (n & POLLOUT) { 583 if (n & POLLOUT) {
583 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); 584 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can write\n", m);
584 set_bit(Wpending, &m->wsched); 585 set_bit(Wpending, &m->wsched);
585 } 586 }
586 587
@@ -602,7 +603,7 @@ static void p9_poll_mux(struct p9_conn *m)
602 603
603 n = p9_fd_poll(m->client, NULL); 604 n = p9_fd_poll(m->client, NULL);
604 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { 605 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
605 P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n); 606 P9_DPRINTK(P9_DEBUG_TRANS, "error mux %p err %d\n", m, n);
606 if (n >= 0) 607 if (n >= 0)
607 n = -ECONNRESET; 608 n = -ECONNRESET;
608 p9_conn_cancel(m, n); 609 p9_conn_cancel(m, n);
@@ -610,19 +611,19 @@ static void p9_poll_mux(struct p9_conn *m)
610 611
611 if (n & POLLIN) { 612 if (n & POLLIN) {
612 set_bit(Rpending, &m->wsched); 613 set_bit(Rpending, &m->wsched);
613 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); 614 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can read\n", m);
614 if (!test_and_set_bit(Rworksched, &m->wsched)) { 615 if (!test_and_set_bit(Rworksched, &m->wsched)) {
615 P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); 616 P9_DPRINTK(P9_DEBUG_TRANS, "sched read work %p\n", m);
616 queue_work(p9_mux_wq, &m->rq); 617 queue_work(p9_mux_wq, &m->rq);
617 } 618 }
618 } 619 }
619 620
620 if (n & POLLOUT) { 621 if (n & POLLOUT) {
621 set_bit(Wpending, &m->wsched); 622 set_bit(Wpending, &m->wsched);
622 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); 623 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can write\n", m);
623 if ((m->wsize || !list_empty(&m->unsent_req_list)) 624 if ((m->wsize || !list_empty(&m->unsent_req_list))
624 && !test_and_set_bit(Wworksched, &m->wsched)) { 625 && !test_and_set_bit(Wworksched, &m->wsched)) {
625 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); 626 P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m);
626 queue_work(p9_mux_wq, &m->wq); 627 queue_work(p9_mux_wq, &m->wq);
627 } 628 }
628 } 629 }
@@ -645,8 +646,8 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
645 struct p9_trans_fd *ts = client->trans; 646 struct p9_trans_fd *ts = client->trans;
646 struct p9_conn *m = ts->conn; 647 struct p9_conn *m = ts->conn;
647 648
648 P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, 649 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", m,
649 req->tc, req->tc->id); 650 current, req->tc, req->tc->id);
650 if (m->err < 0) 651 if (m->err < 0)
651 return m->err; 652 return m->err;
652 653
@@ -672,19 +673,12 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
672 struct p9_trans_fd *ts = client->trans; 673 struct p9_trans_fd *ts = client->trans;
673 struct p9_conn *m = ts->conn; 674 struct p9_conn *m = ts->conn;
674 675
675 P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p\n", m, req); 676 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p req %p\n", m, req);
676 677
677 spin_lock(&client->lock); 678 spin_lock(&client->lock);
678 list_del(&req->req_list); 679 list_del(&req->req_list);
679 spin_unlock(&client->lock); 680 spin_unlock(&client->lock);
680 681
681 /* if a response was received for a request, do nothing */
682 if (req->rc || req->t_err) {
683 P9_DPRINTK(P9_DEBUG_MUX,
684 "mux %p req %p response already received\n", m, req);
685 return 0;
686 }
687
688 if (req->status == REQ_STATUS_UNSENT) { 682 if (req->status == REQ_STATUS_UNSENT) {
689 req->status = REQ_STATUS_FLSHD; 683 req->status = REQ_STATUS_FLSHD;
690 return 0; 684 return 0;
@@ -809,7 +803,7 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket)
809 803
810static void p9_conn_destroy(struct p9_conn *m) 804static void p9_conn_destroy(struct p9_conn *m)
811{ 805{
812 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, 806 P9_DPRINTK(P9_DEBUG_TRANS, "mux %p prev %p next %p\n", m,
813 m->mux_list.prev, m->mux_list.next); 807 m->mux_list.prev, m->mux_list.next);
814 808
815 p9_mux_poll_stop(m); 809 p9_mux_poll_stop(m);
@@ -1060,7 +1054,7 @@ static int p9_poll_proc(void *a)
1060{ 1054{
1061 unsigned long flags; 1055 unsigned long flags;
1062 1056
1063 P9_DPRINTK(P9_DEBUG_MUX, "start %p\n", current); 1057 P9_DPRINTK(P9_DEBUG_TRANS, "start %p\n", current);
1064 repeat: 1058 repeat:
1065 spin_lock_irqsave(&p9_poll_lock, flags); 1059 spin_lock_irqsave(&p9_poll_lock, flags);
1066 while (!list_empty(&p9_poll_pending_list)) { 1060 while (!list_empty(&p9_poll_pending_list)) {
@@ -1078,7 +1072,7 @@ static int p9_poll_proc(void *a)
1078 1072
1079 set_current_state(TASK_INTERRUPTIBLE); 1073 set_current_state(TASK_INTERRUPTIBLE);
1080 if (list_empty(&p9_poll_pending_list)) { 1074 if (list_empty(&p9_poll_pending_list)) {
1081 P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n"); 1075 P9_DPRINTK(P9_DEBUG_TRANS, "sleeping...\n");
1082 schedule(); 1076 schedule();
1083 } 1077 }
1084 __set_current_state(TASK_RUNNING); 1078 __set_current_state(TASK_RUNNING);
@@ -1086,7 +1080,7 @@ static int p9_poll_proc(void *a)
1086 if (!kthread_should_stop()) 1080 if (!kthread_should_stop())
1087 goto repeat; 1081 goto repeat;
1088 1082
1089 P9_DPRINTK(P9_DEBUG_MUX, "finish\n"); 1083 P9_DPRINTK(P9_DEBUG_TRANS, "finish\n");
1090 return 0; 1084 return 0;
1091} 1085}
1092 1086
diff --git a/net/9p/util.c b/net/9p/util.c
index 958fc58cd1ff..dc4ec05ad93d 100644
--- a/net/9p/util.c
+++ b/net/9p/util.c
@@ -105,6 +105,7 @@ retry:
105 else if (error) 105 else if (error)
106 return -1; 106 return -1;
107 107
108 P9_DPRINTK(P9_DEBUG_MUX, " id %d pool %p\n", i, p);
108 return i; 109 return i;
109} 110}
110EXPORT_SYMBOL(p9_idpool_get); 111EXPORT_SYMBOL(p9_idpool_get);
@@ -121,6 +122,9 @@ EXPORT_SYMBOL(p9_idpool_get);
121void p9_idpool_put(int id, struct p9_idpool *p) 122void p9_idpool_put(int id, struct p9_idpool *p)
122{ 123{
123 unsigned long flags; 124 unsigned long flags;
125
126 P9_DPRINTK(P9_DEBUG_MUX, " id %d pool %p\n", id, p);
127
124 spin_lock_irqsave(&p->lock, flags); 128 spin_lock_irqsave(&p->lock, flags);
125 idr_remove(&p->pool, id); 129 idr_remove(&p->pool, id);
126 spin_unlock_irqrestore(&p->lock, flags); 130 spin_unlock_irqrestore(&p->lock, flags);