aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);