diff options
-rw-r--r-- | fs/9p/acl.c | 2 | ||||
-rw-r--r-- | fs/9p/v9fs.c | 21 | ||||
-rw-r--r-- | fs/9p/v9fs.h | 1 | ||||
-rw-r--r-- | fs/9p/vfs_dir.c | 19 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 24 | ||||
-rw-r--r-- | include/net/9p/9p.h | 12 | ||||
-rw-r--r-- | include/net/9p/client.h | 71 | ||||
-rw-r--r-- | net/9p/Makefile | 1 | ||||
-rw-r--r-- | net/9p/client.c | 551 | ||||
-rw-r--r-- | net/9p/mod.c | 9 | ||||
-rw-r--r-- | net/9p/protocol.c | 20 | ||||
-rw-r--r-- | net/9p/trans_fd.c | 64 | ||||
-rw-r--r-- | net/9p/trans_rdma.c | 37 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 44 | ||||
-rw-r--r-- | net/9p/trans_xen.c | 17 | ||||
-rw-r--r-- | net/9p/util.c | 140 |
16 files changed, 482 insertions, 551 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 082d227fa56b..6261719f6f2a 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c | |||
@@ -276,7 +276,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, | |||
276 | switch (handler->flags) { | 276 | switch (handler->flags) { |
277 | case ACL_TYPE_ACCESS: | 277 | case ACL_TYPE_ACCESS: |
278 | if (acl) { | 278 | if (acl) { |
279 | struct iattr iattr; | 279 | struct iattr iattr = { 0 }; |
280 | struct posix_acl *old_acl = acl; | 280 | struct posix_acl *old_acl = acl; |
281 | 281 | ||
282 | retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); | 282 | retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 89bac3d2f05b..619128b55837 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -61,6 +61,8 @@ enum { | |||
61 | Opt_cache_loose, Opt_fscache, Opt_mmap, | 61 | Opt_cache_loose, Opt_fscache, Opt_mmap, |
62 | /* Access options */ | 62 | /* Access options */ |
63 | Opt_access, Opt_posixacl, | 63 | Opt_access, Opt_posixacl, |
64 | /* Lock timeout option */ | ||
65 | Opt_locktimeout, | ||
64 | /* Error token */ | 66 | /* Error token */ |
65 | Opt_err | 67 | Opt_err |
66 | }; | 68 | }; |
@@ -80,6 +82,7 @@ static const match_table_t tokens = { | |||
80 | {Opt_cachetag, "cachetag=%s"}, | 82 | {Opt_cachetag, "cachetag=%s"}, |
81 | {Opt_access, "access=%s"}, | 83 | {Opt_access, "access=%s"}, |
82 | {Opt_posixacl, "posixacl"}, | 84 | {Opt_posixacl, "posixacl"}, |
85 | {Opt_locktimeout, "locktimeout=%u"}, | ||
83 | {Opt_err, NULL} | 86 | {Opt_err, NULL} |
84 | }; | 87 | }; |
85 | 88 | ||
@@ -187,6 +190,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) | |||
187 | #ifdef CONFIG_9P_FSCACHE | 190 | #ifdef CONFIG_9P_FSCACHE |
188 | v9ses->cachetag = NULL; | 191 | v9ses->cachetag = NULL; |
189 | #endif | 192 | #endif |
193 | v9ses->session_lock_timeout = P9_LOCK_TIMEOUT; | ||
190 | 194 | ||
191 | if (!opts) | 195 | if (!opts) |
192 | return 0; | 196 | return 0; |
@@ -359,6 +363,23 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) | |||
359 | #endif | 363 | #endif |
360 | break; | 364 | break; |
361 | 365 | ||
366 | case Opt_locktimeout: | ||
367 | r = match_int(&args[0], &option); | ||
368 | if (r < 0) { | ||
369 | p9_debug(P9_DEBUG_ERROR, | ||
370 | "integer field, but no integer?\n"); | ||
371 | ret = r; | ||
372 | continue; | ||
373 | } | ||
374 | if (option < 1) { | ||
375 | p9_debug(P9_DEBUG_ERROR, | ||
376 | "locktimeout must be a greater than zero integer.\n"); | ||
377 | ret = -EINVAL; | ||
378 | continue; | ||
379 | } | ||
380 | v9ses->session_lock_timeout = (long)option * HZ; | ||
381 | break; | ||
382 | |||
362 | default: | 383 | default: |
363 | continue; | 384 | continue; |
364 | } | 385 | } |
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 982e017acadb..129e5243a6bf 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -116,6 +116,7 @@ struct v9fs_session_info { | |||
116 | struct p9_client *clnt; /* 9p client */ | 116 | struct p9_client *clnt; /* 9p client */ |
117 | struct list_head slist; /* list of sessions registered with v9fs */ | 117 | struct list_head slist; /* list of sessions registered with v9fs */ |
118 | struct rw_semaphore rename_sem; | 118 | struct rw_semaphore rename_sem; |
119 | long session_lock_timeout; /* retry interval for blocking locks */ | ||
119 | }; | 120 | }; |
120 | 121 | ||
121 | /* cache_validity flags */ | 122 | /* cache_validity flags */ |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index b0405d6aac85..cb6c4031af55 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -76,15 +76,6 @@ static inline int dt_type(struct p9_wstat *mistat) | |||
76 | return rettype; | 76 | return rettype; |
77 | } | 77 | } |
78 | 78 | ||
79 | static void p9stat_init(struct p9_wstat *stbuf) | ||
80 | { | ||
81 | stbuf->name = NULL; | ||
82 | stbuf->uid = NULL; | ||
83 | stbuf->gid = NULL; | ||
84 | stbuf->muid = NULL; | ||
85 | stbuf->extension = NULL; | ||
86 | } | ||
87 | |||
88 | /** | 79 | /** |
89 | * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir | 80 | * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir |
90 | * @filp: opened file structure | 81 | * @filp: opened file structure |
@@ -114,7 +105,6 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |||
114 | int err = 0; | 105 | int err = 0; |
115 | struct p9_fid *fid; | 106 | struct p9_fid *fid; |
116 | int buflen; | 107 | int buflen; |
117 | int reclen = 0; | ||
118 | struct p9_rdir *rdir; | 108 | struct p9_rdir *rdir; |
119 | struct kvec kvec; | 109 | struct kvec kvec; |
120 | 110 | ||
@@ -145,15 +135,12 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |||
145 | rdir->tail = n; | 135 | rdir->tail = n; |
146 | } | 136 | } |
147 | while (rdir->head < rdir->tail) { | 137 | while (rdir->head < rdir->tail) { |
148 | p9stat_init(&st); | ||
149 | err = p9stat_read(fid->clnt, rdir->buf + rdir->head, | 138 | err = p9stat_read(fid->clnt, rdir->buf + rdir->head, |
150 | rdir->tail - rdir->head, &st); | 139 | rdir->tail - rdir->head, &st); |
151 | if (err) { | 140 | if (err <= 0) { |
152 | p9_debug(P9_DEBUG_VFS, "returned %d\n", err); | 141 | p9_debug(P9_DEBUG_VFS, "returned %d\n", err); |
153 | p9stat_free(&st); | ||
154 | return -EIO; | 142 | return -EIO; |
155 | } | 143 | } |
156 | reclen = st.size+2; | ||
157 | 144 | ||
158 | over = !dir_emit(ctx, st.name, strlen(st.name), | 145 | over = !dir_emit(ctx, st.name, strlen(st.name), |
159 | v9fs_qid2ino(&st.qid), dt_type(&st)); | 146 | v9fs_qid2ino(&st.qid), dt_type(&st)); |
@@ -161,8 +148,8 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |||
161 | if (over) | 148 | if (over) |
162 | return 0; | 149 | return 0; |
163 | 150 | ||
164 | rdir->head += reclen; | 151 | rdir->head += err; |
165 | ctx->pos += reclen; | 152 | ctx->pos += err; |
166 | } | 153 | } |
167 | } | 154 | } |
168 | } | 155 | } |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 5f2e48d41d72..a25efa782fcc 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -154,6 +154,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
154 | uint8_t status = P9_LOCK_ERROR; | 154 | uint8_t status = P9_LOCK_ERROR; |
155 | int res = 0; | 155 | int res = 0; |
156 | unsigned char fl_type; | 156 | unsigned char fl_type; |
157 | struct v9fs_session_info *v9ses; | ||
157 | 158 | ||
158 | fid = filp->private_data; | 159 | fid = filp->private_data; |
159 | BUG_ON(fid == NULL); | 160 | BUG_ON(fid == NULL); |
@@ -189,6 +190,8 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
189 | if (IS_SETLKW(cmd)) | 190 | if (IS_SETLKW(cmd)) |
190 | flock.flags = P9_LOCK_FLAGS_BLOCK; | 191 | flock.flags = P9_LOCK_FLAGS_BLOCK; |
191 | 192 | ||
193 | v9ses = v9fs_inode2v9ses(file_inode(filp)); | ||
194 | |||
192 | /* | 195 | /* |
193 | * if its a blocked request and we get P9_LOCK_BLOCKED as the status | 196 | * if its a blocked request and we get P9_LOCK_BLOCKED as the status |
194 | * for lock request, keep on trying | 197 | * for lock request, keep on trying |
@@ -202,8 +205,17 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
202 | break; | 205 | break; |
203 | if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) | 206 | if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) |
204 | break; | 207 | break; |
205 | if (schedule_timeout_interruptible(P9_LOCK_TIMEOUT) != 0) | 208 | if (schedule_timeout_interruptible(v9ses->session_lock_timeout) |
209 | != 0) | ||
206 | break; | 210 | break; |
211 | /* | ||
212 | * p9_client_lock_dotl overwrites flock.client_id with the | ||
213 | * server message, free and reuse the client name | ||
214 | */ | ||
215 | if (flock.client_id != fid->clnt->name) { | ||
216 | kfree(flock.client_id); | ||
217 | flock.client_id = fid->clnt->name; | ||
218 | } | ||
207 | } | 219 | } |
208 | 220 | ||
209 | /* map 9p status to VFS status */ | 221 | /* map 9p status to VFS status */ |
@@ -216,7 +228,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
216 | break; | 228 | break; |
217 | default: | 229 | default: |
218 | WARN_ONCE(1, "unknown lock status code: %d\n", status); | 230 | WARN_ONCE(1, "unknown lock status code: %d\n", status); |
219 | /* fallthough */ | 231 | /* fall through */ |
220 | case P9_LOCK_ERROR: | 232 | case P9_LOCK_ERROR: |
221 | case P9_LOCK_GRACE: | 233 | case P9_LOCK_GRACE: |
222 | res = -ENOLCK; | 234 | res = -ENOLCK; |
@@ -235,6 +247,8 @@ out_unlock: | |||
235 | locks_lock_file_wait(filp, fl); | 247 | locks_lock_file_wait(filp, fl); |
236 | fl->fl_type = fl_type; | 248 | fl->fl_type = fl_type; |
237 | } | 249 | } |
250 | if (flock.client_id != fid->clnt->name) | ||
251 | kfree(flock.client_id); | ||
238 | out: | 252 | out: |
239 | return res; | 253 | return res; |
240 | } | 254 | } |
@@ -269,7 +283,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) | |||
269 | 283 | ||
270 | res = p9_client_getlock_dotl(fid, &glock); | 284 | res = p9_client_getlock_dotl(fid, &glock); |
271 | if (res < 0) | 285 | if (res < 0) |
272 | return res; | 286 | goto out; |
273 | /* map 9p lock type to os lock type */ | 287 | /* map 9p lock type to os lock type */ |
274 | switch (glock.type) { | 288 | switch (glock.type) { |
275 | case P9_LOCK_TYPE_RDLCK: | 289 | case P9_LOCK_TYPE_RDLCK: |
@@ -290,7 +304,9 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) | |||
290 | fl->fl_end = glock.start + glock.length - 1; | 304 | fl->fl_end = glock.start + glock.length - 1; |
291 | fl->fl_pid = -glock.proc_id; | 305 | fl->fl_pid = -glock.proc_id; |
292 | } | 306 | } |
293 | kfree(glock.client_id); | 307 | out: |
308 | if (glock.client_id != fid->clnt->name) | ||
309 | kfree(glock.client_id); | ||
294 | return res; | 310 | return res; |
295 | } | 311 | } |
296 | 312 | ||
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index b8eb51a661e5..beede1e1a919 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h | |||
@@ -336,6 +336,9 @@ enum p9_qid_t { | |||
336 | #define P9_NOFID (u32)(~0) | 336 | #define P9_NOFID (u32)(~0) |
337 | #define P9_MAXWELEM 16 | 337 | #define P9_MAXWELEM 16 |
338 | 338 | ||
339 | /* Minimal header size: size[4] type[1] tag[2] */ | ||
340 | #define P9_HDRSZ 7 | ||
341 | |||
339 | /* ample room for Twrite/Rread header */ | 342 | /* ample room for Twrite/Rread header */ |
340 | #define P9_IOHDRSZ 24 | 343 | #define P9_IOHDRSZ 24 |
341 | 344 | ||
@@ -558,19 +561,12 @@ struct p9_fcall { | |||
558 | size_t offset; | 561 | size_t offset; |
559 | size_t capacity; | 562 | size_t capacity; |
560 | 563 | ||
564 | struct kmem_cache *cache; | ||
561 | u8 *sdata; | 565 | u8 *sdata; |
562 | }; | 566 | }; |
563 | 567 | ||
564 | struct p9_idpool; | ||
565 | |||
566 | int p9_errstr2errno(char *errstr, int len); | 568 | int p9_errstr2errno(char *errstr, int len); |
567 | 569 | ||
568 | struct p9_idpool *p9_idpool_create(void); | ||
569 | void p9_idpool_destroy(struct p9_idpool *); | ||
570 | int p9_idpool_get(struct p9_idpool *p); | ||
571 | void p9_idpool_put(int id, struct p9_idpool *p); | ||
572 | int p9_idpool_check(int id, struct p9_idpool *p); | ||
573 | |||
574 | int p9_error_init(void); | 570 | int p9_error_init(void); |
575 | int p9_trans_fd_init(void); | 571 | int p9_trans_fd_init(void); |
576 | void p9_trans_fd_exit(void); | 572 | void p9_trans_fd_exit(void); |
diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 0fa0fbab33b0..947a570307a6 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
@@ -64,22 +64,15 @@ enum p9_trans_status { | |||
64 | 64 | ||
65 | /** | 65 | /** |
66 | * enum p9_req_status_t - status of a request | 66 | * enum p9_req_status_t - status of a request |
67 | * @REQ_STATUS_IDLE: request slot unused | ||
68 | * @REQ_STATUS_ALLOC: request has been allocated but not sent | 67 | * @REQ_STATUS_ALLOC: request has been allocated but not sent |
69 | * @REQ_STATUS_UNSENT: request waiting to be sent | 68 | * @REQ_STATUS_UNSENT: request waiting to be sent |
70 | * @REQ_STATUS_SENT: request sent to server | 69 | * @REQ_STATUS_SENT: request sent to server |
71 | * @REQ_STATUS_RCVD: response received from server | 70 | * @REQ_STATUS_RCVD: response received from server |
72 | * @REQ_STATUS_FLSHD: request has been flushed | 71 | * @REQ_STATUS_FLSHD: request has been flushed |
73 | * @REQ_STATUS_ERROR: request encountered an error on the client side | 72 | * @REQ_STATUS_ERROR: request encountered an error on the client side |
74 | * | ||
75 | * The @REQ_STATUS_IDLE state is used to mark a request slot as unused | ||
76 | * but use is actually tracked by the idpool structure which handles tag | ||
77 | * id allocation. | ||
78 | * | ||
79 | */ | 73 | */ |
80 | 74 | ||
81 | enum p9_req_status_t { | 75 | enum p9_req_status_t { |
82 | REQ_STATUS_IDLE, | ||
83 | REQ_STATUS_ALLOC, | 76 | REQ_STATUS_ALLOC, |
84 | REQ_STATUS_UNSENT, | 77 | REQ_STATUS_UNSENT, |
85 | REQ_STATUS_SENT, | 78 | REQ_STATUS_SENT, |
@@ -92,70 +85,46 @@ enum p9_req_status_t { | |||
92 | * struct p9_req_t - request slots | 85 | * struct p9_req_t - request slots |
93 | * @status: status of this request slot | 86 | * @status: status of this request slot |
94 | * @t_err: transport error | 87 | * @t_err: transport error |
95 | * @flush_tag: tag of request being flushed (for flush requests) | ||
96 | * @wq: wait_queue for the client to block on for this request | 88 | * @wq: wait_queue for the client to block on for this request |
97 | * @tc: the request fcall structure | 89 | * @tc: the request fcall structure |
98 | * @rc: the response fcall structure | 90 | * @rc: the response fcall structure |
99 | * @aux: transport specific data (provided for trans_fd migration) | 91 | * @aux: transport specific data (provided for trans_fd migration) |
100 | * @req_list: link for higher level objects to chain requests | 92 | * @req_list: link for higher level objects to chain requests |
101 | * | ||
102 | * Transport use an array to track outstanding requests | ||
103 | * instead of a list. While this may incurr overhead during initial | ||
104 | * allocation or expansion, it makes request lookup much easier as the | ||
105 | * tag id is a index into an array. (We use tag+1 so that we can accommodate | ||
106 | * the -1 tag for the T_VERSION request). | ||
107 | * This also has the nice effect of only having to allocate wait_queues | ||
108 | * once, instead of constantly allocating and freeing them. Its possible | ||
109 | * other resources could benefit from this scheme as well. | ||
110 | * | ||
111 | */ | 93 | */ |
112 | |||
113 | struct p9_req_t { | 94 | struct p9_req_t { |
114 | int status; | 95 | int status; |
115 | int t_err; | 96 | int t_err; |
97 | struct kref refcount; | ||
116 | wait_queue_head_t wq; | 98 | wait_queue_head_t wq; |
117 | struct p9_fcall *tc; | 99 | struct p9_fcall tc; |
118 | struct p9_fcall *rc; | 100 | struct p9_fcall rc; |
119 | void *aux; | 101 | void *aux; |
120 | |||
121 | struct list_head req_list; | 102 | struct list_head req_list; |
122 | }; | 103 | }; |
123 | 104 | ||
124 | /** | 105 | /** |
125 | * struct p9_client - per client instance state | 106 | * struct p9_client - per client instance state |
126 | * @lock: protect @fidlist | 107 | * @lock: protect @fids and @reqs |
127 | * @msize: maximum data size negotiated by protocol | 108 | * @msize: maximum data size negotiated by protocol |
128 | * @dotu: extension flags negotiated by protocol | ||
129 | * @proto_version: 9P protocol version to use | 109 | * @proto_version: 9P protocol version to use |
130 | * @trans_mod: module API instantiated with this client | 110 | * @trans_mod: module API instantiated with this client |
111 | * @status: connection state | ||
131 | * @trans: tranport instance state and API | 112 | * @trans: tranport instance state and API |
132 | * @fids: All active FID handles | 113 | * @fids: All active FID handles |
133 | * @tagpool - transaction id accounting for session | 114 | * @reqs: All active requests. |
134 | * @reqs - 2D array of requests | 115 | * @name: node name used as client id |
135 | * @max_tag - current maximum tag id allocated | ||
136 | * @name - node name used as client id | ||
137 | * | 116 | * |
138 | * The client structure is used to keep track of various per-client | 117 | * The client structure is used to keep track of various per-client |
139 | * state that has been instantiated. | 118 | * state that has been instantiated. |
140 | * In order to minimize per-transaction overhead we use a | ||
141 | * simple array to lookup requests instead of a hash table | ||
142 | * or linked list. In order to support larger number of | ||
143 | * transactions, we make this a 2D array, allocating new rows | ||
144 | * when we need to grow the total number of the transactions. | ||
145 | * | ||
146 | * Each row is 256 requests and we'll support up to 256 rows for | ||
147 | * a total of 64k concurrent requests per session. | ||
148 | * | ||
149 | * Bugs: duplicated data and potentially unnecessary elements. | ||
150 | */ | 119 | */ |
151 | |||
152 | struct p9_client { | 120 | struct p9_client { |
153 | spinlock_t lock; /* protect client structure */ | 121 | spinlock_t lock; |
154 | unsigned int msize; | 122 | unsigned int msize; |
155 | unsigned char proto_version; | 123 | unsigned char proto_version; |
156 | struct p9_trans_module *trans_mod; | 124 | struct p9_trans_module *trans_mod; |
157 | enum p9_trans_status status; | 125 | enum p9_trans_status status; |
158 | void *trans; | 126 | void *trans; |
127 | struct kmem_cache *fcall_cache; | ||
159 | 128 | ||
160 | union { | 129 | union { |
161 | struct { | 130 | struct { |
@@ -170,10 +139,7 @@ struct p9_client { | |||
170 | } trans_opts; | 139 | } trans_opts; |
171 | 140 | ||
172 | struct idr fids; | 141 | struct idr fids; |
173 | 142 | struct idr reqs; | |
174 | struct p9_idpool *tagpool; | ||
175 | struct p9_req_t *reqs[P9_ROW_MAXTAG]; | ||
176 | int max_tag; | ||
177 | 143 | ||
178 | char name[__NEW_UTS_LEN + 1]; | 144 | char name[__NEW_UTS_LEN + 1]; |
179 | }; | 145 | }; |
@@ -266,7 +232,21 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode, | |||
266 | kgid_t gid, struct p9_qid *); | 232 | kgid_t gid, struct p9_qid *); |
267 | int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); | 233 | int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); |
268 | int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl); | 234 | int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl); |
235 | void p9_fcall_fini(struct p9_fcall *fc); | ||
269 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); | 236 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); |
237 | |||
238 | static inline void p9_req_get(struct p9_req_t *r) | ||
239 | { | ||
240 | kref_get(&r->refcount); | ||
241 | } | ||
242 | |||
243 | static inline int p9_req_try_get(struct p9_req_t *r) | ||
244 | { | ||
245 | return kref_get_unless_zero(&r->refcount); | ||
246 | } | ||
247 | |||
248 | int p9_req_put(struct p9_req_t *r); | ||
249 | |||
270 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status); | 250 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status); |
271 | 251 | ||
272 | int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int); | 252 | int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int); |
@@ -279,4 +259,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); | |||
279 | int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); | 259 | int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); |
280 | int p9_client_readlink(struct p9_fid *fid, char **target); | 260 | int p9_client_readlink(struct p9_fid *fid, char **target); |
281 | 261 | ||
262 | int p9_client_init(void); | ||
263 | void p9_client_exit(void); | ||
264 | |||
282 | #endif /* NET_9P_CLIENT_H */ | 265 | #endif /* NET_9P_CLIENT_H */ |
diff --git a/net/9p/Makefile b/net/9p/Makefile index c0486cfc85d9..aa0a5641e5d0 100644 --- a/net/9p/Makefile +++ b/net/9p/Makefile | |||
@@ -8,7 +8,6 @@ obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o | |||
8 | mod.o \ | 8 | mod.o \ |
9 | client.o \ | 9 | client.o \ |
10 | error.o \ | 10 | error.o \ |
11 | util.o \ | ||
12 | protocol.o \ | 11 | protocol.o \ |
13 | trans_fd.o \ | 12 | trans_fd.o \ |
14 | trans_common.o \ | 13 | trans_common.o \ |
diff --git a/net/9p/client.c b/net/9p/client.c index deae53a7dffc..5f23e18eecc0 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -231,144 +231,170 @@ free_and_return: | |||
231 | return ret; | 231 | return ret; |
232 | } | 232 | } |
233 | 233 | ||
234 | static struct p9_fcall *p9_fcall_alloc(int alloc_msize) | 234 | static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc, |
235 | int alloc_msize) | ||
235 | { | 236 | { |
236 | struct p9_fcall *fc; | 237 | if (likely(c->fcall_cache) && alloc_msize == c->msize) { |
237 | fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); | 238 | fc->sdata = kmem_cache_alloc(c->fcall_cache, GFP_NOFS); |
238 | if (!fc) | 239 | fc->cache = c->fcall_cache; |
239 | return NULL; | 240 | } else { |
241 | fc->sdata = kmalloc(alloc_msize, GFP_NOFS); | ||
242 | fc->cache = NULL; | ||
243 | } | ||
244 | if (!fc->sdata) | ||
245 | return -ENOMEM; | ||
240 | fc->capacity = alloc_msize; | 246 | fc->capacity = alloc_msize; |
241 | fc->sdata = (char *) fc + sizeof(struct p9_fcall); | 247 | return 0; |
242 | return fc; | 248 | } |
249 | |||
250 | void p9_fcall_fini(struct p9_fcall *fc) | ||
251 | { | ||
252 | /* sdata can be NULL for interrupted requests in trans_rdma, | ||
253 | * and kmem_cache_free does not do NULL-check for us | ||
254 | */ | ||
255 | if (unlikely(!fc->sdata)) | ||
256 | return; | ||
257 | |||
258 | if (fc->cache) | ||
259 | kmem_cache_free(fc->cache, fc->sdata); | ||
260 | else | ||
261 | kfree(fc->sdata); | ||
243 | } | 262 | } |
263 | EXPORT_SYMBOL(p9_fcall_fini); | ||
264 | |||
265 | static struct kmem_cache *p9_req_cache; | ||
244 | 266 | ||
245 | /** | 267 | /** |
246 | * p9_tag_alloc - lookup/allocate a request by tag | 268 | * p9_req_alloc - Allocate a new request. |
247 | * @c: client session to lookup tag within | 269 | * @c: Client session. |
248 | * @tag: numeric id for transaction | 270 | * @type: Transaction type. |
249 | * | 271 | * @max_size: Maximum packet size for this request. |
250 | * this is a simple array lookup, but will grow the | ||
251 | * request_slots as necessary to accommodate transaction | ||
252 | * ids which did not previously have a slot. | ||
253 | * | ||
254 | * this code relies on the client spinlock to manage locks, its | ||
255 | * possible we should switch to something else, but I'd rather | ||
256 | * stick with something low-overhead for the common case. | ||
257 | * | 272 | * |
273 | * Context: Process context. | ||
274 | * Return: Pointer to new request. | ||
258 | */ | 275 | */ |
259 | |||
260 | static struct p9_req_t * | 276 | static struct p9_req_t * |
261 | p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) | 277 | p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size) |
262 | { | 278 | { |
263 | unsigned long flags; | 279 | struct p9_req_t *req = kmem_cache_alloc(p9_req_cache, GFP_NOFS); |
264 | int row, col; | ||
265 | struct p9_req_t *req; | ||
266 | int alloc_msize = min(c->msize, max_size); | 280 | int alloc_msize = min(c->msize, max_size); |
281 | int tag; | ||
267 | 282 | ||
268 | /* This looks up the original request by tag so we know which | 283 | if (!req) |
269 | * buffer to read the data into */ | 284 | return ERR_PTR(-ENOMEM); |
270 | tag++; | ||
271 | |||
272 | if (tag >= c->max_tag) { | ||
273 | spin_lock_irqsave(&c->lock, flags); | ||
274 | /* check again since original check was outside of lock */ | ||
275 | while (tag >= c->max_tag) { | ||
276 | row = (tag / P9_ROW_MAXTAG); | ||
277 | c->reqs[row] = kcalloc(P9_ROW_MAXTAG, | ||
278 | sizeof(struct p9_req_t), GFP_ATOMIC); | ||
279 | |||
280 | if (!c->reqs[row]) { | ||
281 | pr_err("Couldn't grow tag array\n"); | ||
282 | spin_unlock_irqrestore(&c->lock, flags); | ||
283 | return ERR_PTR(-ENOMEM); | ||
284 | } | ||
285 | for (col = 0; col < P9_ROW_MAXTAG; col++) { | ||
286 | req = &c->reqs[row][col]; | ||
287 | req->status = REQ_STATUS_IDLE; | ||
288 | init_waitqueue_head(&req->wq); | ||
289 | } | ||
290 | c->max_tag += P9_ROW_MAXTAG; | ||
291 | } | ||
292 | spin_unlock_irqrestore(&c->lock, flags); | ||
293 | } | ||
294 | row = tag / P9_ROW_MAXTAG; | ||
295 | col = tag % P9_ROW_MAXTAG; | ||
296 | |||
297 | req = &c->reqs[row][col]; | ||
298 | if (!req->tc) | ||
299 | req->tc = p9_fcall_alloc(alloc_msize); | ||
300 | if (!req->rc) | ||
301 | req->rc = p9_fcall_alloc(alloc_msize); | ||
302 | if (!req->tc || !req->rc) | ||
303 | goto grow_failed; | ||
304 | 285 | ||
305 | p9pdu_reset(req->tc); | 286 | if (p9_fcall_init(c, &req->tc, alloc_msize)) |
306 | p9pdu_reset(req->rc); | 287 | goto free_req; |
288 | if (p9_fcall_init(c, &req->rc, alloc_msize)) | ||
289 | goto free; | ||
307 | 290 | ||
308 | req->tc->tag = tag-1; | 291 | p9pdu_reset(&req->tc); |
292 | p9pdu_reset(&req->rc); | ||
309 | req->status = REQ_STATUS_ALLOC; | 293 | req->status = REQ_STATUS_ALLOC; |
294 | init_waitqueue_head(&req->wq); | ||
295 | INIT_LIST_HEAD(&req->req_list); | ||
296 | |||
297 | idr_preload(GFP_NOFS); | ||
298 | spin_lock_irq(&c->lock); | ||
299 | if (type == P9_TVERSION) | ||
300 | tag = idr_alloc(&c->reqs, req, P9_NOTAG, P9_NOTAG + 1, | ||
301 | GFP_NOWAIT); | ||
302 | else | ||
303 | tag = idr_alloc(&c->reqs, req, 0, P9_NOTAG, GFP_NOWAIT); | ||
304 | req->tc.tag = tag; | ||
305 | spin_unlock_irq(&c->lock); | ||
306 | idr_preload_end(); | ||
307 | if (tag < 0) | ||
308 | goto free; | ||
309 | |||
310 | /* Init ref to two because in the general case there is one ref | ||
311 | * that is put asynchronously by a writer thread, one ref | ||
312 | * temporarily given by p9_tag_lookup and put by p9_client_cb | ||
313 | * in the recv thread, and one ref put by p9_tag_remove in the | ||
314 | * main thread. The only exception is virtio that does not use | ||
315 | * p9_tag_lookup but does not have a writer thread either | ||
316 | * (the write happens synchronously in the request/zc_request | ||
317 | * callback), so p9_client_cb eats the second ref there | ||
318 | * as the pointer is duplicated directly by virtqueue_add_sgs() | ||
319 | */ | ||
320 | refcount_set(&req->refcount.refcount, 2); | ||
310 | 321 | ||
311 | return req; | 322 | return req; |
312 | 323 | ||
313 | grow_failed: | 324 | free: |
314 | pr_err("Couldn't grow tag array\n"); | 325 | p9_fcall_fini(&req->tc); |
315 | kfree(req->tc); | 326 | p9_fcall_fini(&req->rc); |
316 | kfree(req->rc); | 327 | free_req: |
317 | req->tc = req->rc = NULL; | 328 | kmem_cache_free(p9_req_cache, req); |
318 | return ERR_PTR(-ENOMEM); | 329 | return ERR_PTR(-ENOMEM); |
319 | } | 330 | } |
320 | 331 | ||
321 | /** | 332 | /** |
322 | * p9_tag_lookup - lookup a request by tag | 333 | * p9_tag_lookup - Look up a request by tag. |
323 | * @c: client session to lookup tag within | 334 | * @c: Client session. |
324 | * @tag: numeric id for transaction | 335 | * @tag: Transaction ID. |
325 | * | 336 | * |
337 | * Context: Any context. | ||
338 | * Return: A request, or %NULL if there is no request with that tag. | ||
326 | */ | 339 | */ |
327 | |||
328 | struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag) | 340 | struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag) |
329 | { | 341 | { |
330 | int row, col; | 342 | struct p9_req_t *req; |
331 | |||
332 | /* This looks up the original request by tag so we know which | ||
333 | * buffer to read the data into */ | ||
334 | tag++; | ||
335 | |||
336 | if (tag >= c->max_tag) | ||
337 | return NULL; | ||
338 | 343 | ||
339 | row = tag / P9_ROW_MAXTAG; | 344 | rcu_read_lock(); |
340 | col = tag % P9_ROW_MAXTAG; | 345 | again: |
346 | req = idr_find(&c->reqs, tag); | ||
347 | if (req) { | ||
348 | /* We have to be careful with the req found under rcu_read_lock | ||
349 | * Thanks to SLAB_TYPESAFE_BY_RCU we can safely try to get the | ||
350 | * ref again without corrupting other data, then check again | ||
351 | * that the tag matches once we have the ref | ||
352 | */ | ||
353 | if (!p9_req_try_get(req)) | ||
354 | goto again; | ||
355 | if (req->tc.tag != tag) { | ||
356 | p9_req_put(req); | ||
357 | goto again; | ||
358 | } | ||
359 | } | ||
360 | rcu_read_unlock(); | ||
341 | 361 | ||
342 | return &c->reqs[row][col]; | 362 | return req; |
343 | } | 363 | } |
344 | EXPORT_SYMBOL(p9_tag_lookup); | 364 | EXPORT_SYMBOL(p9_tag_lookup); |
345 | 365 | ||
346 | /** | 366 | /** |
347 | * p9_tag_init - setup tags structure and contents | 367 | * p9_tag_remove - Remove a tag. |
348 | * @c: v9fs client struct | 368 | * @c: Client session. |
349 | * | 369 | * @r: Request of reference. |
350 | * This initializes the tags structure for each client instance. | ||
351 | * | 370 | * |
371 | * Context: Any context. | ||
352 | */ | 372 | */ |
373 | static int p9_tag_remove(struct p9_client *c, struct p9_req_t *r) | ||
374 | { | ||
375 | unsigned long flags; | ||
376 | u16 tag = r->tc.tag; | ||
377 | |||
378 | p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag); | ||
379 | spin_lock_irqsave(&c->lock, flags); | ||
380 | idr_remove(&c->reqs, tag); | ||
381 | spin_unlock_irqrestore(&c->lock, flags); | ||
382 | return p9_req_put(r); | ||
383 | } | ||
353 | 384 | ||
354 | static int p9_tag_init(struct p9_client *c) | 385 | static void p9_req_free(struct kref *ref) |
355 | { | 386 | { |
356 | int err = 0; | 387 | struct p9_req_t *r = container_of(ref, struct p9_req_t, refcount); |
388 | p9_fcall_fini(&r->tc); | ||
389 | p9_fcall_fini(&r->rc); | ||
390 | kmem_cache_free(p9_req_cache, r); | ||
391 | } | ||
357 | 392 | ||
358 | c->tagpool = p9_idpool_create(); | 393 | int p9_req_put(struct p9_req_t *r) |
359 | if (IS_ERR(c->tagpool)) { | 394 | { |
360 | err = PTR_ERR(c->tagpool); | 395 | return kref_put(&r->refcount, p9_req_free); |
361 | goto error; | ||
362 | } | ||
363 | err = p9_idpool_get(c->tagpool); /* reserve tag 0 */ | ||
364 | if (err < 0) { | ||
365 | p9_idpool_destroy(c->tagpool); | ||
366 | goto error; | ||
367 | } | ||
368 | c->max_tag = 0; | ||
369 | error: | ||
370 | return err; | ||
371 | } | 396 | } |
397 | EXPORT_SYMBOL(p9_req_put); | ||
372 | 398 | ||
373 | /** | 399 | /** |
374 | * p9_tag_cleanup - cleans up tags structure and reclaims resources | 400 | * p9_tag_cleanup - cleans up tags structure and reclaims resources |
@@ -379,52 +405,17 @@ error: | |||
379 | */ | 405 | */ |
380 | static void p9_tag_cleanup(struct p9_client *c) | 406 | static void p9_tag_cleanup(struct p9_client *c) |
381 | { | 407 | { |
382 | int row, col; | 408 | struct p9_req_t *req; |
383 | 409 | int id; | |
384 | /* check to insure all requests are idle */ | ||
385 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { | ||
386 | for (col = 0; col < P9_ROW_MAXTAG; col++) { | ||
387 | if (c->reqs[row][col].status != REQ_STATUS_IDLE) { | ||
388 | p9_debug(P9_DEBUG_MUX, | ||
389 | "Attempting to cleanup non-free tag %d,%d\n", | ||
390 | row, col); | ||
391 | /* TODO: delay execution of cleanup */ | ||
392 | return; | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | |||
397 | if (c->tagpool) { | ||
398 | p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */ | ||
399 | p9_idpool_destroy(c->tagpool); | ||
400 | } | ||
401 | 410 | ||
402 | /* free requests associated with tags */ | 411 | rcu_read_lock(); |
403 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { | 412 | idr_for_each_entry(&c->reqs, req, id) { |
404 | for (col = 0; col < P9_ROW_MAXTAG; col++) { | 413 | pr_info("Tag %d still in use\n", id); |
405 | kfree(c->reqs[row][col].tc); | 414 | if (p9_tag_remove(c, req) == 0) |
406 | kfree(c->reqs[row][col].rc); | 415 | pr_warn("Packet with tag %d has still references", |
407 | } | 416 | req->tc.tag); |
408 | kfree(c->reqs[row]); | ||
409 | } | 417 | } |
410 | c->max_tag = 0; | 418 | rcu_read_unlock(); |
411 | } | ||
412 | |||
413 | /** | ||
414 | * p9_free_req - free a request and clean-up as necessary | ||
415 | * c: client state | ||
416 | * r: request to release | ||
417 | * | ||
418 | */ | ||
419 | |||
420 | static void p9_free_req(struct p9_client *c, struct p9_req_t *r) | ||
421 | { | ||
422 | int tag = r->tc->tag; | ||
423 | p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag); | ||
424 | |||
425 | r->status = REQ_STATUS_IDLE; | ||
426 | if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool)) | ||
427 | p9_idpool_put(tag, c->tagpool); | ||
428 | } | 419 | } |
429 | 420 | ||
430 | /** | 421 | /** |
@@ -435,7 +426,7 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) | |||
435 | */ | 426 | */ |
436 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) | 427 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) |
437 | { | 428 | { |
438 | p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); | 429 | p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc.tag); |
439 | 430 | ||
440 | /* | 431 | /* |
441 | * This barrier is needed to make sure any change made to req before | 432 | * This barrier is needed to make sure any change made to req before |
@@ -445,7 +436,8 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) | |||
445 | req->status = status; | 436 | req->status = status; |
446 | 437 | ||
447 | wake_up(&req->wq); | 438 | wake_up(&req->wq); |
448 | p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); | 439 | p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag); |
440 | p9_req_put(req); | ||
449 | } | 441 | } |
450 | EXPORT_SYMBOL(p9_client_cb); | 442 | EXPORT_SYMBOL(p9_client_cb); |
451 | 443 | ||
@@ -516,18 +508,18 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
516 | int err; | 508 | int err; |
517 | int ecode; | 509 | int ecode; |
518 | 510 | ||
519 | err = p9_parse_header(req->rc, NULL, &type, NULL, 0); | 511 | err = p9_parse_header(&req->rc, NULL, &type, NULL, 0); |
520 | if (req->rc->size >= c->msize) { | 512 | if (req->rc.size >= c->msize) { |
521 | p9_debug(P9_DEBUG_ERROR, | 513 | p9_debug(P9_DEBUG_ERROR, |
522 | "requested packet size too big: %d\n", | 514 | "requested packet size too big: %d\n", |
523 | req->rc->size); | 515 | req->rc.size); |
524 | return -EIO; | 516 | return -EIO; |
525 | } | 517 | } |
526 | /* | 518 | /* |
527 | * dump the response from server | 519 | * dump the response from server |
528 | * This should be after check errors which poplulate pdu_fcall. | 520 | * This should be after check errors which poplulate pdu_fcall. |
529 | */ | 521 | */ |
530 | trace_9p_protocol_dump(c, req->rc); | 522 | trace_9p_protocol_dump(c, &req->rc); |
531 | if (err) { | 523 | if (err) { |
532 | p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); | 524 | p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); |
533 | return err; | 525 | return err; |
@@ -537,7 +529,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
537 | 529 | ||
538 | if (!p9_is_proto_dotl(c)) { | 530 | if (!p9_is_proto_dotl(c)) { |
539 | char *ename; | 531 | char *ename; |
540 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", | 532 | err = p9pdu_readf(&req->rc, c->proto_version, "s?d", |
541 | &ename, &ecode); | 533 | &ename, &ecode); |
542 | if (err) | 534 | if (err) |
543 | goto out_err; | 535 | goto out_err; |
@@ -553,7 +545,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
553 | } | 545 | } |
554 | kfree(ename); | 546 | kfree(ename); |
555 | } else { | 547 | } else { |
556 | err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); | 548 | err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode); |
557 | err = -ecode; | 549 | err = -ecode; |
558 | 550 | ||
559 | p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); | 551 | p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); |
@@ -587,12 +579,12 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | |||
587 | int8_t type; | 579 | int8_t type; |
588 | char *ename = NULL; | 580 | char *ename = NULL; |
589 | 581 | ||
590 | err = p9_parse_header(req->rc, NULL, &type, NULL, 0); | 582 | err = p9_parse_header(&req->rc, NULL, &type, NULL, 0); |
591 | /* | 583 | /* |
592 | * dump the response from server | 584 | * dump the response from server |
593 | * This should be after parse_header which poplulate pdu_fcall. | 585 | * This should be after parse_header which poplulate pdu_fcall. |
594 | */ | 586 | */ |
595 | trace_9p_protocol_dump(c, req->rc); | 587 | trace_9p_protocol_dump(c, &req->rc); |
596 | if (err) { | 588 | if (err) { |
597 | p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); | 589 | p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); |
598 | return err; | 590 | return err; |
@@ -607,13 +599,13 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | |||
607 | /* 7 = header size for RERROR; */ | 599 | /* 7 = header size for RERROR; */ |
608 | int inline_len = in_hdrlen - 7; | 600 | int inline_len = in_hdrlen - 7; |
609 | 601 | ||
610 | len = req->rc->size - req->rc->offset; | 602 | len = req->rc.size - req->rc.offset; |
611 | if (len > (P9_ZC_HDR_SZ - 7)) { | 603 | if (len > (P9_ZC_HDR_SZ - 7)) { |
612 | err = -EFAULT; | 604 | err = -EFAULT; |
613 | goto out_err; | 605 | goto out_err; |
614 | } | 606 | } |
615 | 607 | ||
616 | ename = &req->rc->sdata[req->rc->offset]; | 608 | ename = &req->rc.sdata[req->rc.offset]; |
617 | if (len > inline_len) { | 609 | if (len > inline_len) { |
618 | /* We have error in external buffer */ | 610 | /* We have error in external buffer */ |
619 | if (!copy_from_iter_full(ename + inline_len, | 611 | if (!copy_from_iter_full(ename + inline_len, |
@@ -623,7 +615,7 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | |||
623 | } | 615 | } |
624 | } | 616 | } |
625 | ename = NULL; | 617 | ename = NULL; |
626 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", | 618 | err = p9pdu_readf(&req->rc, c->proto_version, "s?d", |
627 | &ename, &ecode); | 619 | &ename, &ecode); |
628 | if (err) | 620 | if (err) |
629 | goto out_err; | 621 | goto out_err; |
@@ -639,7 +631,7 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | |||
639 | } | 631 | } |
640 | kfree(ename); | 632 | kfree(ename); |
641 | } else { | 633 | } else { |
642 | err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); | 634 | err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode); |
643 | err = -ecode; | 635 | err = -ecode; |
644 | 636 | ||
645 | p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); | 637 | p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); |
@@ -672,7 +664,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) | |||
672 | int16_t oldtag; | 664 | int16_t oldtag; |
673 | int err; | 665 | int err; |
674 | 666 | ||
675 | err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1); | 667 | err = p9_parse_header(&oldreq->tc, NULL, NULL, &oldtag, 1); |
676 | if (err) | 668 | if (err) |
677 | return err; | 669 | return err; |
678 | 670 | ||
@@ -686,11 +678,12 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) | |||
686 | * if we haven't received a response for oldreq, | 678 | * if we haven't received a response for oldreq, |
687 | * remove it from the list | 679 | * remove it from the list |
688 | */ | 680 | */ |
689 | if (oldreq->status == REQ_STATUS_SENT) | 681 | if (oldreq->status == REQ_STATUS_SENT) { |
690 | if (c->trans_mod->cancelled) | 682 | if (c->trans_mod->cancelled) |
691 | c->trans_mod->cancelled(c, oldreq); | 683 | c->trans_mod->cancelled(c, oldreq); |
684 | } | ||
692 | 685 | ||
693 | p9_free_req(c, req); | 686 | p9_tag_remove(c, req); |
694 | return 0; | 687 | return 0; |
695 | } | 688 | } |
696 | 689 | ||
@@ -698,7 +691,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, | |||
698 | int8_t type, int req_size, | 691 | int8_t type, int req_size, |
699 | const char *fmt, va_list ap) | 692 | const char *fmt, va_list ap) |
700 | { | 693 | { |
701 | int tag, err; | 694 | int err; |
702 | struct p9_req_t *req; | 695 | struct p9_req_t *req; |
703 | 696 | ||
704 | p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type); | 697 | p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type); |
@@ -711,27 +704,22 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, | |||
711 | if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) | 704 | if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) |
712 | return ERR_PTR(-EIO); | 705 | return ERR_PTR(-EIO); |
713 | 706 | ||
714 | tag = P9_NOTAG; | 707 | req = p9_tag_alloc(c, type, req_size); |
715 | if (type != P9_TVERSION) { | ||
716 | tag = p9_idpool_get(c->tagpool); | ||
717 | if (tag < 0) | ||
718 | return ERR_PTR(-ENOMEM); | ||
719 | } | ||
720 | |||
721 | req = p9_tag_alloc(c, tag, req_size); | ||
722 | if (IS_ERR(req)) | 708 | if (IS_ERR(req)) |
723 | return req; | 709 | return req; |
724 | 710 | ||
725 | /* marshall the data */ | 711 | /* marshall the data */ |
726 | p9pdu_prepare(req->tc, tag, type); | 712 | p9pdu_prepare(&req->tc, req->tc.tag, type); |
727 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); | 713 | err = p9pdu_vwritef(&req->tc, c->proto_version, fmt, ap); |
728 | if (err) | 714 | if (err) |
729 | goto reterr; | 715 | goto reterr; |
730 | p9pdu_finalize(c, req->tc); | 716 | p9pdu_finalize(c, &req->tc); |
731 | trace_9p_client_req(c, type, tag); | 717 | trace_9p_client_req(c, type, req->tc.tag); |
732 | return req; | 718 | return req; |
733 | reterr: | 719 | reterr: |
734 | p9_free_req(c, req); | 720 | p9_tag_remove(c, req); |
721 | /* We have to put also the 2nd reference as it won't be used */ | ||
722 | p9_req_put(req); | ||
735 | return ERR_PTR(err); | 723 | return ERR_PTR(err); |
736 | } | 724 | } |
737 | 725 | ||
@@ -741,7 +729,7 @@ reterr: | |||
741 | * @type: type of request | 729 | * @type: type of request |
742 | * @fmt: protocol format string (see protocol.c) | 730 | * @fmt: protocol format string (see protocol.c) |
743 | * | 731 | * |
744 | * Returns request structure (which client must free using p9_free_req) | 732 | * Returns request structure (which client must free using p9_tag_remove) |
745 | */ | 733 | */ |
746 | 734 | ||
747 | static struct p9_req_t * | 735 | static struct p9_req_t * |
@@ -766,6 +754,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
766 | 754 | ||
767 | err = c->trans_mod->request(c, req); | 755 | err = c->trans_mod->request(c, req); |
768 | if (err < 0) { | 756 | if (err < 0) { |
757 | /* write won't happen */ | ||
758 | p9_req_put(req); | ||
769 | if (err != -ERESTARTSYS && err != -EFAULT) | 759 | if (err != -ERESTARTSYS && err != -EFAULT) |
770 | c->status = Disconnected; | 760 | c->status = Disconnected; |
771 | goto recalc_sigpending; | 761 | goto recalc_sigpending; |
@@ -813,11 +803,11 @@ recalc_sigpending: | |||
813 | goto reterr; | 803 | goto reterr; |
814 | 804 | ||
815 | err = p9_check_errors(c, req); | 805 | err = p9_check_errors(c, req); |
816 | trace_9p_client_res(c, type, req->rc->tag, err); | 806 | trace_9p_client_res(c, type, req->rc.tag, err); |
817 | if (!err) | 807 | if (!err) |
818 | return req; | 808 | return req; |
819 | reterr: | 809 | reterr: |
820 | p9_free_req(c, req); | 810 | p9_tag_remove(c, req); |
821 | return ERR_PTR(safe_errno(err)); | 811 | return ERR_PTR(safe_errno(err)); |
822 | } | 812 | } |
823 | 813 | ||
@@ -832,7 +822,7 @@ reterr: | |||
832 | * @hdrlen: reader header size, This is the size of response protocol data | 822 | * @hdrlen: reader header size, This is the size of response protocol data |
833 | * @fmt: protocol format string (see protocol.c) | 823 | * @fmt: protocol format string (see protocol.c) |
834 | * | 824 | * |
835 | * Returns request structure (which client must free using p9_free_req) | 825 | * Returns request structure (which client must free using p9_tag_remove) |
836 | */ | 826 | */ |
837 | static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, | 827 | static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, |
838 | struct iov_iter *uidata, | 828 | struct iov_iter *uidata, |
@@ -895,11 +885,11 @@ recalc_sigpending: | |||
895 | goto reterr; | 885 | goto reterr; |
896 | 886 | ||
897 | err = p9_check_zc_errors(c, req, uidata, in_hdrlen); | 887 | err = p9_check_zc_errors(c, req, uidata, in_hdrlen); |
898 | trace_9p_client_res(c, type, req->rc->tag, err); | 888 | trace_9p_client_res(c, type, req->rc.tag, err); |
899 | if (!err) | 889 | if (!err) |
900 | return req; | 890 | return req; |
901 | reterr: | 891 | reterr: |
902 | p9_free_req(c, req); | 892 | p9_tag_remove(c, req); |
903 | return ERR_PTR(safe_errno(err)); | 893 | return ERR_PTR(safe_errno(err)); |
904 | } | 894 | } |
905 | 895 | ||
@@ -978,10 +968,10 @@ static int p9_client_version(struct p9_client *c) | |||
978 | if (IS_ERR(req)) | 968 | if (IS_ERR(req)) |
979 | return PTR_ERR(req); | 969 | return PTR_ERR(req); |
980 | 970 | ||
981 | err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); | 971 | err = p9pdu_readf(&req->rc, c->proto_version, "ds", &msize, &version); |
982 | if (err) { | 972 | if (err) { |
983 | p9_debug(P9_DEBUG_9P, "version error %d\n", err); | 973 | p9_debug(P9_DEBUG_9P, "version error %d\n", err); |
984 | trace_9p_protocol_dump(c, req->rc); | 974 | trace_9p_protocol_dump(c, &req->rc); |
985 | goto error; | 975 | goto error; |
986 | } | 976 | } |
987 | 977 | ||
@@ -1002,7 +992,7 @@ static int p9_client_version(struct p9_client *c) | |||
1002 | 992 | ||
1003 | error: | 993 | error: |
1004 | kfree(version); | 994 | kfree(version); |
1005 | p9_free_req(c, req); | 995 | p9_tag_remove(c, req); |
1006 | 996 | ||
1007 | return err; | 997 | return err; |
1008 | } | 998 | } |
@@ -1020,20 +1010,18 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
1020 | 1010 | ||
1021 | clnt->trans_mod = NULL; | 1011 | clnt->trans_mod = NULL; |
1022 | clnt->trans = NULL; | 1012 | clnt->trans = NULL; |
1013 | clnt->fcall_cache = NULL; | ||
1023 | 1014 | ||
1024 | client_id = utsname()->nodename; | 1015 | client_id = utsname()->nodename; |
1025 | memcpy(clnt->name, client_id, strlen(client_id) + 1); | 1016 | memcpy(clnt->name, client_id, strlen(client_id) + 1); |
1026 | 1017 | ||
1027 | spin_lock_init(&clnt->lock); | 1018 | spin_lock_init(&clnt->lock); |
1028 | idr_init(&clnt->fids); | 1019 | idr_init(&clnt->fids); |
1029 | 1020 | idr_init(&clnt->reqs); | |
1030 | err = p9_tag_init(clnt); | ||
1031 | if (err < 0) | ||
1032 | goto free_client; | ||
1033 | 1021 | ||
1034 | err = parse_opts(options, clnt); | 1022 | err = parse_opts(options, clnt); |
1035 | if (err < 0) | 1023 | if (err < 0) |
1036 | goto destroy_tagpool; | 1024 | goto free_client; |
1037 | 1025 | ||
1038 | if (!clnt->trans_mod) | 1026 | if (!clnt->trans_mod) |
1039 | clnt->trans_mod = v9fs_get_default_trans(); | 1027 | clnt->trans_mod = v9fs_get_default_trans(); |
@@ -1042,7 +1030,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
1042 | err = -EPROTONOSUPPORT; | 1030 | err = -EPROTONOSUPPORT; |
1043 | p9_debug(P9_DEBUG_ERROR, | 1031 | p9_debug(P9_DEBUG_ERROR, |
1044 | "No transport defined or default transport\n"); | 1032 | "No transport defined or default transport\n"); |
1045 | goto destroy_tagpool; | 1033 | goto free_client; |
1046 | } | 1034 | } |
1047 | 1035 | ||
1048 | p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", | 1036 | p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", |
@@ -1059,14 +1047,21 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
1059 | if (err) | 1047 | if (err) |
1060 | goto close_trans; | 1048 | goto close_trans; |
1061 | 1049 | ||
1050 | /* P9_HDRSZ + 4 is the smallest packet header we can have that is | ||
1051 | * followed by data accessed from userspace by read | ||
1052 | */ | ||
1053 | clnt->fcall_cache = | ||
1054 | kmem_cache_create_usercopy("9p-fcall-cache", clnt->msize, | ||
1055 | 0, 0, P9_HDRSZ + 4, | ||
1056 | clnt->msize - (P9_HDRSZ + 4), | ||
1057 | NULL); | ||
1058 | |||
1062 | return clnt; | 1059 | return clnt; |
1063 | 1060 | ||
1064 | close_trans: | 1061 | close_trans: |
1065 | clnt->trans_mod->close(clnt); | 1062 | clnt->trans_mod->close(clnt); |
1066 | put_trans: | 1063 | put_trans: |
1067 | v9fs_put_trans(clnt->trans_mod); | 1064 | v9fs_put_trans(clnt->trans_mod); |
1068 | destroy_tagpool: | ||
1069 | p9_idpool_destroy(clnt->tagpool); | ||
1070 | free_client: | 1065 | free_client: |
1071 | kfree(clnt); | 1066 | kfree(clnt); |
1072 | return ERR_PTR(err); | 1067 | return ERR_PTR(err); |
@@ -1092,6 +1087,7 @@ void p9_client_destroy(struct p9_client *clnt) | |||
1092 | 1087 | ||
1093 | p9_tag_cleanup(clnt); | 1088 | p9_tag_cleanup(clnt); |
1094 | 1089 | ||
1090 | kmem_cache_destroy(clnt->fcall_cache); | ||
1095 | kfree(clnt); | 1091 | kfree(clnt); |
1096 | } | 1092 | } |
1097 | EXPORT_SYMBOL(p9_client_destroy); | 1093 | EXPORT_SYMBOL(p9_client_destroy); |
@@ -1135,10 +1131,10 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | |||
1135 | goto error; | 1131 | goto error; |
1136 | } | 1132 | } |
1137 | 1133 | ||
1138 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); | 1134 | err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", &qid); |
1139 | if (err) { | 1135 | if (err) { |
1140 | trace_9p_protocol_dump(clnt, req->rc); | 1136 | trace_9p_protocol_dump(clnt, &req->rc); |
1141 | p9_free_req(clnt, req); | 1137 | p9_tag_remove(clnt, req); |
1142 | goto error; | 1138 | goto error; |
1143 | } | 1139 | } |
1144 | 1140 | ||
@@ -1147,7 +1143,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | |||
1147 | 1143 | ||
1148 | memmove(&fid->qid, &qid, sizeof(struct p9_qid)); | 1144 | memmove(&fid->qid, &qid, sizeof(struct p9_qid)); |
1149 | 1145 | ||
1150 | p9_free_req(clnt, req); | 1146 | p9_tag_remove(clnt, req); |
1151 | return fid; | 1147 | return fid; |
1152 | 1148 | ||
1153 | error: | 1149 | error: |
@@ -1192,13 +1188,13 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, | |||
1192 | goto error; | 1188 | goto error; |
1193 | } | 1189 | } |
1194 | 1190 | ||
1195 | err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); | 1191 | err = p9pdu_readf(&req->rc, clnt->proto_version, "R", &nwqids, &wqids); |
1196 | if (err) { | 1192 | if (err) { |
1197 | trace_9p_protocol_dump(clnt, req->rc); | 1193 | trace_9p_protocol_dump(clnt, &req->rc); |
1198 | p9_free_req(clnt, req); | 1194 | p9_tag_remove(clnt, req); |
1199 | goto clunk_fid; | 1195 | goto clunk_fid; |
1200 | } | 1196 | } |
1201 | p9_free_req(clnt, req); | 1197 | p9_tag_remove(clnt, req); |
1202 | 1198 | ||
1203 | p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids); | 1199 | p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids); |
1204 | 1200 | ||
@@ -1259,9 +1255,9 @@ int p9_client_open(struct p9_fid *fid, int mode) | |||
1259 | goto error; | 1255 | goto error; |
1260 | } | 1256 | } |
1261 | 1257 | ||
1262 | err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); | 1258 | err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", &qid, &iounit); |
1263 | if (err) { | 1259 | if (err) { |
1264 | trace_9p_protocol_dump(clnt, req->rc); | 1260 | trace_9p_protocol_dump(clnt, &req->rc); |
1265 | goto free_and_error; | 1261 | goto free_and_error; |
1266 | } | 1262 | } |
1267 | 1263 | ||
@@ -1273,7 +1269,7 @@ int p9_client_open(struct p9_fid *fid, int mode) | |||
1273 | fid->iounit = iounit; | 1269 | fid->iounit = iounit; |
1274 | 1270 | ||
1275 | free_and_error: | 1271 | free_and_error: |
1276 | p9_free_req(clnt, req); | 1272 | p9_tag_remove(clnt, req); |
1277 | error: | 1273 | error: |
1278 | return err; | 1274 | return err; |
1279 | } | 1275 | } |
@@ -1303,9 +1299,9 @@ int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 | |||
1303 | goto error; | 1299 | goto error; |
1304 | } | 1300 | } |
1305 | 1301 | ||
1306 | err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit); | 1302 | err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", qid, &iounit); |
1307 | if (err) { | 1303 | if (err) { |
1308 | trace_9p_protocol_dump(clnt, req->rc); | 1304 | trace_9p_protocol_dump(clnt, &req->rc); |
1309 | goto free_and_error; | 1305 | goto free_and_error; |
1310 | } | 1306 | } |
1311 | 1307 | ||
@@ -1318,7 +1314,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 | |||
1318 | ofid->iounit = iounit; | 1314 | ofid->iounit = iounit; |
1319 | 1315 | ||
1320 | free_and_error: | 1316 | free_and_error: |
1321 | p9_free_req(clnt, req); | 1317 | p9_tag_remove(clnt, req); |
1322 | error: | 1318 | error: |
1323 | return err; | 1319 | return err; |
1324 | } | 1320 | } |
@@ -1348,9 +1344,9 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode, | |||
1348 | goto error; | 1344 | goto error; |
1349 | } | 1345 | } |
1350 | 1346 | ||
1351 | err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); | 1347 | err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", &qid, &iounit); |
1352 | if (err) { | 1348 | if (err) { |
1353 | trace_9p_protocol_dump(clnt, req->rc); | 1349 | trace_9p_protocol_dump(clnt, &req->rc); |
1354 | goto free_and_error; | 1350 | goto free_and_error; |
1355 | } | 1351 | } |
1356 | 1352 | ||
@@ -1363,7 +1359,7 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode, | |||
1363 | fid->iounit = iounit; | 1359 | fid->iounit = iounit; |
1364 | 1360 | ||
1365 | free_and_error: | 1361 | free_and_error: |
1366 | p9_free_req(clnt, req); | 1362 | p9_tag_remove(clnt, req); |
1367 | error: | 1363 | error: |
1368 | return err; | 1364 | return err; |
1369 | } | 1365 | } |
@@ -1387,9 +1383,9 @@ int p9_client_symlink(struct p9_fid *dfid, const char *name, | |||
1387 | goto error; | 1383 | goto error; |
1388 | } | 1384 | } |
1389 | 1385 | ||
1390 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); | 1386 | err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid); |
1391 | if (err) { | 1387 | if (err) { |
1392 | trace_9p_protocol_dump(clnt, req->rc); | 1388 | trace_9p_protocol_dump(clnt, &req->rc); |
1393 | goto free_and_error; | 1389 | goto free_and_error; |
1394 | } | 1390 | } |
1395 | 1391 | ||
@@ -1397,7 +1393,7 @@ int p9_client_symlink(struct p9_fid *dfid, const char *name, | |||
1397 | qid->type, (unsigned long long)qid->path, qid->version); | 1393 | qid->type, (unsigned long long)qid->path, qid->version); |
1398 | 1394 | ||
1399 | free_and_error: | 1395 | free_and_error: |
1400 | p9_free_req(clnt, req); | 1396 | p9_tag_remove(clnt, req); |
1401 | error: | 1397 | error: |
1402 | return err; | 1398 | return err; |
1403 | } | 1399 | } |
@@ -1417,7 +1413,7 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, const char *newna | |||
1417 | return PTR_ERR(req); | 1413 | return PTR_ERR(req); |
1418 | 1414 | ||
1419 | p9_debug(P9_DEBUG_9P, "<<< RLINK\n"); | 1415 | p9_debug(P9_DEBUG_9P, "<<< RLINK\n"); |
1420 | p9_free_req(clnt, req); | 1416 | p9_tag_remove(clnt, req); |
1421 | return 0; | 1417 | return 0; |
1422 | } | 1418 | } |
1423 | EXPORT_SYMBOL(p9_client_link); | 1419 | EXPORT_SYMBOL(p9_client_link); |
@@ -1441,7 +1437,7 @@ int p9_client_fsync(struct p9_fid *fid, int datasync) | |||
1441 | 1437 | ||
1442 | p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid); | 1438 | p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid); |
1443 | 1439 | ||
1444 | p9_free_req(clnt, req); | 1440 | p9_tag_remove(clnt, req); |
1445 | 1441 | ||
1446 | error: | 1442 | error: |
1447 | return err; | 1443 | return err; |
@@ -1476,7 +1472,7 @@ again: | |||
1476 | 1472 | ||
1477 | p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid); | 1473 | p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid); |
1478 | 1474 | ||
1479 | p9_free_req(clnt, req); | 1475 | p9_tag_remove(clnt, req); |
1480 | error: | 1476 | error: |
1481 | /* | 1477 | /* |
1482 | * Fid is not valid even after a failed clunk | 1478 | * Fid is not valid even after a failed clunk |
@@ -1510,7 +1506,7 @@ int p9_client_remove(struct p9_fid *fid) | |||
1510 | 1506 | ||
1511 | p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid); | 1507 | p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid); |
1512 | 1508 | ||
1513 | p9_free_req(clnt, req); | 1509 | p9_tag_remove(clnt, req); |
1514 | error: | 1510 | error: |
1515 | if (err == -ERESTARTSYS) | 1511 | if (err == -ERESTARTSYS) |
1516 | p9_client_clunk(fid); | 1512 | p9_client_clunk(fid); |
@@ -1537,7 +1533,7 @@ int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags) | |||
1537 | } | 1533 | } |
1538 | p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name); | 1534 | p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name); |
1539 | 1535 | ||
1540 | p9_free_req(clnt, req); | 1536 | p9_tag_remove(clnt, req); |
1541 | error: | 1537 | error: |
1542 | return err; | 1538 | return err; |
1543 | } | 1539 | } |
@@ -1585,11 +1581,11 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err) | |||
1585 | break; | 1581 | break; |
1586 | } | 1582 | } |
1587 | 1583 | ||
1588 | *err = p9pdu_readf(req->rc, clnt->proto_version, | 1584 | *err = p9pdu_readf(&req->rc, clnt->proto_version, |
1589 | "D", &count, &dataptr); | 1585 | "D", &count, &dataptr); |
1590 | if (*err) { | 1586 | if (*err) { |
1591 | trace_9p_protocol_dump(clnt, req->rc); | 1587 | trace_9p_protocol_dump(clnt, &req->rc); |
1592 | p9_free_req(clnt, req); | 1588 | p9_tag_remove(clnt, req); |
1593 | break; | 1589 | break; |
1594 | } | 1590 | } |
1595 | if (rsize < count) { | 1591 | if (rsize < count) { |
@@ -1599,7 +1595,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err) | |||
1599 | 1595 | ||
1600 | p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); | 1596 | p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); |
1601 | if (!count) { | 1597 | if (!count) { |
1602 | p9_free_req(clnt, req); | 1598 | p9_tag_remove(clnt, req); |
1603 | break; | 1599 | break; |
1604 | } | 1600 | } |
1605 | 1601 | ||
@@ -1609,7 +1605,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err) | |||
1609 | offset += n; | 1605 | offset += n; |
1610 | if (n != count) { | 1606 | if (n != count) { |
1611 | *err = -EFAULT; | 1607 | *err = -EFAULT; |
1612 | p9_free_req(clnt, req); | 1608 | p9_tag_remove(clnt, req); |
1613 | break; | 1609 | break; |
1614 | } | 1610 | } |
1615 | } else { | 1611 | } else { |
@@ -1617,7 +1613,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err) | |||
1617 | total += count; | 1613 | total += count; |
1618 | offset += count; | 1614 | offset += count; |
1619 | } | 1615 | } |
1620 | p9_free_req(clnt, req); | 1616 | p9_tag_remove(clnt, req); |
1621 | } | 1617 | } |
1622 | return total; | 1618 | return total; |
1623 | } | 1619 | } |
@@ -1658,10 +1654,10 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) | |||
1658 | break; | 1654 | break; |
1659 | } | 1655 | } |
1660 | 1656 | ||
1661 | *err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); | 1657 | *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &count); |
1662 | if (*err) { | 1658 | if (*err) { |
1663 | trace_9p_protocol_dump(clnt, req->rc); | 1659 | trace_9p_protocol_dump(clnt, &req->rc); |
1664 | p9_free_req(clnt, req); | 1660 | p9_tag_remove(clnt, req); |
1665 | break; | 1661 | break; |
1666 | } | 1662 | } |
1667 | if (rsize < count) { | 1663 | if (rsize < count) { |
@@ -1671,7 +1667,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) | |||
1671 | 1667 | ||
1672 | p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); | 1668 | p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); |
1673 | 1669 | ||
1674 | p9_free_req(clnt, req); | 1670 | p9_tag_remove(clnt, req); |
1675 | iov_iter_advance(from, count); | 1671 | iov_iter_advance(from, count); |
1676 | total += count; | 1672 | total += count; |
1677 | offset += count; | 1673 | offset += count; |
@@ -1702,10 +1698,10 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1702 | goto error; | 1698 | goto error; |
1703 | } | 1699 | } |
1704 | 1700 | ||
1705 | err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); | 1701 | err = p9pdu_readf(&req->rc, clnt->proto_version, "wS", &ignored, ret); |
1706 | if (err) { | 1702 | if (err) { |
1707 | trace_9p_protocol_dump(clnt, req->rc); | 1703 | trace_9p_protocol_dump(clnt, &req->rc); |
1708 | p9_free_req(clnt, req); | 1704 | p9_tag_remove(clnt, req); |
1709 | goto error; | 1705 | goto error; |
1710 | } | 1706 | } |
1711 | 1707 | ||
@@ -1722,7 +1718,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1722 | from_kgid(&init_user_ns, ret->n_gid), | 1718 | from_kgid(&init_user_ns, ret->n_gid), |
1723 | from_kuid(&init_user_ns, ret->n_muid)); | 1719 | from_kuid(&init_user_ns, ret->n_muid)); |
1724 | 1720 | ||
1725 | p9_free_req(clnt, req); | 1721 | p9_tag_remove(clnt, req); |
1726 | return ret; | 1722 | return ret; |
1727 | 1723 | ||
1728 | error: | 1724 | error: |
@@ -1755,10 +1751,10 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, | |||
1755 | goto error; | 1751 | goto error; |
1756 | } | 1752 | } |
1757 | 1753 | ||
1758 | err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret); | 1754 | err = p9pdu_readf(&req->rc, clnt->proto_version, "A", ret); |
1759 | if (err) { | 1755 | if (err) { |
1760 | trace_9p_protocol_dump(clnt, req->rc); | 1756 | trace_9p_protocol_dump(clnt, &req->rc); |
1761 | p9_free_req(clnt, req); | 1757 | p9_tag_remove(clnt, req); |
1762 | goto error; | 1758 | goto error; |
1763 | } | 1759 | } |
1764 | 1760 | ||
@@ -1783,7 +1779,7 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, | |||
1783 | ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec, | 1779 | ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec, |
1784 | ret->st_gen, ret->st_data_version); | 1780 | ret->st_gen, ret->st_data_version); |
1785 | 1781 | ||
1786 | p9_free_req(clnt, req); | 1782 | p9_tag_remove(clnt, req); |
1787 | return ret; | 1783 | return ret; |
1788 | 1784 | ||
1789 | error: | 1785 | error: |
@@ -1852,7 +1848,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
1852 | 1848 | ||
1853 | p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid); | 1849 | p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid); |
1854 | 1850 | ||
1855 | p9_free_req(clnt, req); | 1851 | p9_tag_remove(clnt, req); |
1856 | error: | 1852 | error: |
1857 | return err; | 1853 | return err; |
1858 | } | 1854 | } |
@@ -1884,7 +1880,7 @@ int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr) | |||
1884 | goto error; | 1880 | goto error; |
1885 | } | 1881 | } |
1886 | p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid); | 1882 | p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid); |
1887 | p9_free_req(clnt, req); | 1883 | p9_tag_remove(clnt, req); |
1888 | error: | 1884 | error: |
1889 | return err; | 1885 | return err; |
1890 | } | 1886 | } |
@@ -1907,12 +1903,12 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb) | |||
1907 | goto error; | 1903 | goto error; |
1908 | } | 1904 | } |
1909 | 1905 | ||
1910 | err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type, | 1906 | err = p9pdu_readf(&req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type, |
1911 | &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail, | 1907 | &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail, |
1912 | &sb->files, &sb->ffree, &sb->fsid, &sb->namelen); | 1908 | &sb->files, &sb->ffree, &sb->fsid, &sb->namelen); |
1913 | if (err) { | 1909 | if (err) { |
1914 | trace_9p_protocol_dump(clnt, req->rc); | 1910 | trace_9p_protocol_dump(clnt, &req->rc); |
1915 | p9_free_req(clnt, req); | 1911 | p9_tag_remove(clnt, req); |
1916 | goto error; | 1912 | goto error; |
1917 | } | 1913 | } |
1918 | 1914 | ||
@@ -1923,7 +1919,7 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb) | |||
1923 | sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree, | 1919 | sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree, |
1924 | sb->fsid, (long int)sb->namelen); | 1920 | sb->fsid, (long int)sb->namelen); |
1925 | 1921 | ||
1926 | p9_free_req(clnt, req); | 1922 | p9_tag_remove(clnt, req); |
1927 | error: | 1923 | error: |
1928 | return err; | 1924 | return err; |
1929 | } | 1925 | } |
@@ -1951,7 +1947,7 @@ int p9_client_rename(struct p9_fid *fid, | |||
1951 | 1947 | ||
1952 | p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid); | 1948 | p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid); |
1953 | 1949 | ||
1954 | p9_free_req(clnt, req); | 1950 | p9_tag_remove(clnt, req); |
1955 | error: | 1951 | error: |
1956 | return err; | 1952 | return err; |
1957 | } | 1953 | } |
@@ -1981,7 +1977,7 @@ int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, | |||
1981 | p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n", | 1977 | p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n", |
1982 | newdirfid->fid, new_name); | 1978 | newdirfid->fid, new_name); |
1983 | 1979 | ||
1984 | p9_free_req(clnt, req); | 1980 | p9_tag_remove(clnt, req); |
1985 | error: | 1981 | error: |
1986 | return err; | 1982 | return err; |
1987 | } | 1983 | } |
@@ -2015,13 +2011,13 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, | |||
2015 | err = PTR_ERR(req); | 2011 | err = PTR_ERR(req); |
2016 | goto error; | 2012 | goto error; |
2017 | } | 2013 | } |
2018 | err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size); | 2014 | err = p9pdu_readf(&req->rc, clnt->proto_version, "q", attr_size); |
2019 | if (err) { | 2015 | if (err) { |
2020 | trace_9p_protocol_dump(clnt, req->rc); | 2016 | trace_9p_protocol_dump(clnt, &req->rc); |
2021 | p9_free_req(clnt, req); | 2017 | p9_tag_remove(clnt, req); |
2022 | goto clunk_fid; | 2018 | goto clunk_fid; |
2023 | } | 2019 | } |
2024 | p9_free_req(clnt, req); | 2020 | p9_tag_remove(clnt, req); |
2025 | p9_debug(P9_DEBUG_9P, "<<< RXATTRWALK fid %d size %llu\n", | 2021 | p9_debug(P9_DEBUG_9P, "<<< RXATTRWALK fid %d size %llu\n", |
2026 | attr_fid->fid, *attr_size); | 2022 | attr_fid->fid, *attr_size); |
2027 | return attr_fid; | 2023 | return attr_fid; |
@@ -2055,7 +2051,7 @@ int p9_client_xattrcreate(struct p9_fid *fid, const char *name, | |||
2055 | goto error; | 2051 | goto error; |
2056 | } | 2052 | } |
2057 | p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid); | 2053 | p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid); |
2058 | p9_free_req(clnt, req); | 2054 | p9_tag_remove(clnt, req); |
2059 | error: | 2055 | error: |
2060 | return err; | 2056 | return err; |
2061 | } | 2057 | } |
@@ -2103,9 +2099,9 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | |||
2103 | goto error; | 2099 | goto error; |
2104 | } | 2100 | } |
2105 | 2101 | ||
2106 | err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); | 2102 | err = p9pdu_readf(&req->rc, clnt->proto_version, "D", &count, &dataptr); |
2107 | if (err) { | 2103 | if (err) { |
2108 | trace_9p_protocol_dump(clnt, req->rc); | 2104 | trace_9p_protocol_dump(clnt, &req->rc); |
2109 | goto free_and_error; | 2105 | goto free_and_error; |
2110 | } | 2106 | } |
2111 | if (rsize < count) { | 2107 | if (rsize < count) { |
@@ -2118,11 +2114,11 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | |||
2118 | if (non_zc) | 2114 | if (non_zc) |
2119 | memmove(data, dataptr, count); | 2115 | memmove(data, dataptr, count); |
2120 | 2116 | ||
2121 | p9_free_req(clnt, req); | 2117 | p9_tag_remove(clnt, req); |
2122 | return count; | 2118 | return count; |
2123 | 2119 | ||
2124 | free_and_error: | 2120 | free_and_error: |
2125 | p9_free_req(clnt, req); | 2121 | p9_tag_remove(clnt, req); |
2126 | error: | 2122 | error: |
2127 | return err; | 2123 | return err; |
2128 | } | 2124 | } |
@@ -2144,16 +2140,16 @@ int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode, | |||
2144 | if (IS_ERR(req)) | 2140 | if (IS_ERR(req)) |
2145 | return PTR_ERR(req); | 2141 | return PTR_ERR(req); |
2146 | 2142 | ||
2147 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); | 2143 | err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid); |
2148 | if (err) { | 2144 | if (err) { |
2149 | trace_9p_protocol_dump(clnt, req->rc); | 2145 | trace_9p_protocol_dump(clnt, &req->rc); |
2150 | goto error; | 2146 | goto error; |
2151 | } | 2147 | } |
2152 | p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type, | 2148 | p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type, |
2153 | (unsigned long long)qid->path, qid->version); | 2149 | (unsigned long long)qid->path, qid->version); |
2154 | 2150 | ||
2155 | error: | 2151 | error: |
2156 | p9_free_req(clnt, req); | 2152 | p9_tag_remove(clnt, req); |
2157 | return err; | 2153 | return err; |
2158 | 2154 | ||
2159 | } | 2155 | } |
@@ -2175,16 +2171,16 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode, | |||
2175 | if (IS_ERR(req)) | 2171 | if (IS_ERR(req)) |
2176 | return PTR_ERR(req); | 2172 | return PTR_ERR(req); |
2177 | 2173 | ||
2178 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); | 2174 | err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid); |
2179 | if (err) { | 2175 | if (err) { |
2180 | trace_9p_protocol_dump(clnt, req->rc); | 2176 | trace_9p_protocol_dump(clnt, &req->rc); |
2181 | goto error; | 2177 | goto error; |
2182 | } | 2178 | } |
2183 | p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type, | 2179 | p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type, |
2184 | (unsigned long long)qid->path, qid->version); | 2180 | (unsigned long long)qid->path, qid->version); |
2185 | 2181 | ||
2186 | error: | 2182 | error: |
2187 | p9_free_req(clnt, req); | 2183 | p9_tag_remove(clnt, req); |
2188 | return err; | 2184 | return err; |
2189 | 2185 | ||
2190 | } | 2186 | } |
@@ -2210,14 +2206,14 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) | |||
2210 | if (IS_ERR(req)) | 2206 | if (IS_ERR(req)) |
2211 | return PTR_ERR(req); | 2207 | return PTR_ERR(req); |
2212 | 2208 | ||
2213 | err = p9pdu_readf(req->rc, clnt->proto_version, "b", status); | 2209 | err = p9pdu_readf(&req->rc, clnt->proto_version, "b", status); |
2214 | if (err) { | 2210 | if (err) { |
2215 | trace_9p_protocol_dump(clnt, req->rc); | 2211 | trace_9p_protocol_dump(clnt, &req->rc); |
2216 | goto error; | 2212 | goto error; |
2217 | } | 2213 | } |
2218 | p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); | 2214 | p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); |
2219 | error: | 2215 | error: |
2220 | p9_free_req(clnt, req); | 2216 | p9_tag_remove(clnt, req); |
2221 | return err; | 2217 | return err; |
2222 | 2218 | ||
2223 | } | 2219 | } |
@@ -2241,18 +2237,18 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) | |||
2241 | if (IS_ERR(req)) | 2237 | if (IS_ERR(req)) |
2242 | return PTR_ERR(req); | 2238 | return PTR_ERR(req); |
2243 | 2239 | ||
2244 | err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type, | 2240 | err = p9pdu_readf(&req->rc, clnt->proto_version, "bqqds", &glock->type, |
2245 | &glock->start, &glock->length, &glock->proc_id, | 2241 | &glock->start, &glock->length, &glock->proc_id, |
2246 | &glock->client_id); | 2242 | &glock->client_id); |
2247 | if (err) { | 2243 | if (err) { |
2248 | trace_9p_protocol_dump(clnt, req->rc); | 2244 | trace_9p_protocol_dump(clnt, &req->rc); |
2249 | goto error; | 2245 | goto error; |
2250 | } | 2246 | } |
2251 | p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " | 2247 | p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " |
2252 | "proc_id %d client_id %s\n", glock->type, glock->start, | 2248 | "proc_id %d client_id %s\n", glock->type, glock->start, |
2253 | glock->length, glock->proc_id, glock->client_id); | 2249 | glock->length, glock->proc_id, glock->client_id); |
2254 | error: | 2250 | error: |
2255 | p9_free_req(clnt, req); | 2251 | p9_tag_remove(clnt, req); |
2256 | return err; | 2252 | return err; |
2257 | } | 2253 | } |
2258 | EXPORT_SYMBOL(p9_client_getlock_dotl); | 2254 | EXPORT_SYMBOL(p9_client_getlock_dotl); |
@@ -2271,14 +2267,25 @@ int p9_client_readlink(struct p9_fid *fid, char **target) | |||
2271 | if (IS_ERR(req)) | 2267 | if (IS_ERR(req)) |
2272 | return PTR_ERR(req); | 2268 | return PTR_ERR(req); |
2273 | 2269 | ||
2274 | err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); | 2270 | err = p9pdu_readf(&req->rc, clnt->proto_version, "s", target); |
2275 | if (err) { | 2271 | if (err) { |
2276 | trace_9p_protocol_dump(clnt, req->rc); | 2272 | trace_9p_protocol_dump(clnt, &req->rc); |
2277 | goto error; | 2273 | goto error; |
2278 | } | 2274 | } |
2279 | p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); | 2275 | p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); |
2280 | error: | 2276 | error: |
2281 | p9_free_req(clnt, req); | 2277 | p9_tag_remove(clnt, req); |
2282 | return err; | 2278 | return err; |
2283 | } | 2279 | } |
2284 | EXPORT_SYMBOL(p9_client_readlink); | 2280 | EXPORT_SYMBOL(p9_client_readlink); |
2281 | |||
2282 | int __init p9_client_init(void) | ||
2283 | { | ||
2284 | p9_req_cache = KMEM_CACHE(p9_req_t, SLAB_TYPESAFE_BY_RCU); | ||
2285 | return p9_req_cache ? 0 : -ENOMEM; | ||
2286 | } | ||
2287 | |||
2288 | void __exit p9_client_exit(void) | ||
2289 | { | ||
2290 | kmem_cache_destroy(p9_req_cache); | ||
2291 | } | ||
diff --git a/net/9p/mod.c b/net/9p/mod.c index 253ba824a325..0da56d6af73b 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c | |||
@@ -171,11 +171,17 @@ void v9fs_put_trans(struct p9_trans_module *m) | |||
171 | */ | 171 | */ |
172 | static int __init init_p9(void) | 172 | static int __init init_p9(void) |
173 | { | 173 | { |
174 | int ret; | ||
175 | |||
176 | ret = p9_client_init(); | ||
177 | if (ret) | ||
178 | return ret; | ||
179 | |||
174 | p9_error_init(); | 180 | p9_error_init(); |
175 | pr_info("Installing 9P2000 support\n"); | 181 | pr_info("Installing 9P2000 support\n"); |
176 | p9_trans_fd_init(); | 182 | p9_trans_fd_init(); |
177 | 183 | ||
178 | return 0; | 184 | return ret; |
179 | } | 185 | } |
180 | 186 | ||
181 | /** | 187 | /** |
@@ -188,6 +194,7 @@ static void __exit exit_p9(void) | |||
188 | pr_info("Unloading 9P2000 support\n"); | 194 | pr_info("Unloading 9P2000 support\n"); |
189 | 195 | ||
190 | p9_trans_fd_exit(); | 196 | p9_trans_fd_exit(); |
197 | p9_client_exit(); | ||
191 | } | 198 | } |
192 | 199 | ||
193 | module_init(init_p9) | 200 | module_init(init_p9) |
diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 4a1e1dd30b52..462ba144cb39 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
@@ -46,10 +46,15 @@ p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); | |||
46 | void p9stat_free(struct p9_wstat *stbuf) | 46 | void p9stat_free(struct p9_wstat *stbuf) |
47 | { | 47 | { |
48 | kfree(stbuf->name); | 48 | kfree(stbuf->name); |
49 | stbuf->name = NULL; | ||
49 | kfree(stbuf->uid); | 50 | kfree(stbuf->uid); |
51 | stbuf->uid = NULL; | ||
50 | kfree(stbuf->gid); | 52 | kfree(stbuf->gid); |
53 | stbuf->gid = NULL; | ||
51 | kfree(stbuf->muid); | 54 | kfree(stbuf->muid); |
55 | stbuf->muid = NULL; | ||
52 | kfree(stbuf->extension); | 56 | kfree(stbuf->extension); |
57 | stbuf->extension = NULL; | ||
53 | } | 58 | } |
54 | EXPORT_SYMBOL(p9stat_free); | 59 | EXPORT_SYMBOL(p9stat_free); |
55 | 60 | ||
@@ -566,9 +571,10 @@ int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st) | |||
566 | if (ret) { | 571 | if (ret) { |
567 | p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); | 572 | p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); |
568 | trace_9p_protocol_dump(clnt, &fake_pdu); | 573 | trace_9p_protocol_dump(clnt, &fake_pdu); |
574 | return ret; | ||
569 | } | 575 | } |
570 | 576 | ||
571 | return ret; | 577 | return fake_pdu.offset; |
572 | } | 578 | } |
573 | EXPORT_SYMBOL(p9stat_read); | 579 | EXPORT_SYMBOL(p9stat_read); |
574 | 580 | ||
@@ -617,13 +623,19 @@ int p9dirent_read(struct p9_client *clnt, char *buf, int len, | |||
617 | if (ret) { | 623 | if (ret) { |
618 | p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); | 624 | p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); |
619 | trace_9p_protocol_dump(clnt, &fake_pdu); | 625 | trace_9p_protocol_dump(clnt, &fake_pdu); |
620 | goto out; | 626 | return ret; |
621 | } | 627 | } |
622 | 628 | ||
623 | strcpy(dirent->d_name, nameptr); | 629 | ret = strscpy(dirent->d_name, nameptr, sizeof(dirent->d_name)); |
630 | if (ret < 0) { | ||
631 | p9_debug(P9_DEBUG_ERROR, | ||
632 | "On the wire dirent name too long: %s\n", | ||
633 | nameptr); | ||
634 | kfree(nameptr); | ||
635 | return ret; | ||
636 | } | ||
624 | kfree(nameptr); | 637 | kfree(nameptr); |
625 | 638 | ||
626 | out: | ||
627 | return fake_pdu.offset; | 639 | return fake_pdu.offset; |
628 | } | 640 | } |
629 | EXPORT_SYMBOL(p9dirent_read); | 641 | EXPORT_SYMBOL(p9dirent_read); |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index e2ef3c782c53..f868cf6fba79 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -131,7 +131,8 @@ struct p9_conn { | |||
131 | int err; | 131 | int err; |
132 | struct list_head req_list; | 132 | struct list_head req_list; |
133 | struct list_head unsent_req_list; | 133 | struct list_head unsent_req_list; |
134 | struct p9_req_t *req; | 134 | struct p9_req_t *rreq; |
135 | struct p9_req_t *wreq; | ||
135 | char tmp_buf[7]; | 136 | char tmp_buf[7]; |
136 | struct p9_fcall rc; | 137 | struct p9_fcall rc; |
137 | int wpos; | 138 | int wpos; |
@@ -291,7 +292,6 @@ static void p9_read_work(struct work_struct *work) | |||
291 | __poll_t n; | 292 | __poll_t n; |
292 | int err; | 293 | int err; |
293 | struct p9_conn *m; | 294 | struct p9_conn *m; |
294 | int status = REQ_STATUS_ERROR; | ||
295 | 295 | ||
296 | m = container_of(work, struct p9_conn, rq); | 296 | m = container_of(work, struct p9_conn, rq); |
297 | 297 | ||
@@ -322,7 +322,7 @@ static void p9_read_work(struct work_struct *work) | |||
322 | m->rc.offset += err; | 322 | m->rc.offset += err; |
323 | 323 | ||
324 | /* header read in */ | 324 | /* header read in */ |
325 | if ((!m->req) && (m->rc.offset == m->rc.capacity)) { | 325 | if ((!m->rreq) && (m->rc.offset == m->rc.capacity)) { |
326 | p9_debug(P9_DEBUG_TRANS, "got new header\n"); | 326 | p9_debug(P9_DEBUG_TRANS, "got new header\n"); |
327 | 327 | ||
328 | /* Header size */ | 328 | /* Header size */ |
@@ -346,23 +346,23 @@ static void p9_read_work(struct work_struct *work) | |||
346 | "mux %p pkt: size: %d bytes tag: %d\n", | 346 | "mux %p pkt: size: %d bytes tag: %d\n", |
347 | m, m->rc.size, m->rc.tag); | 347 | m, m->rc.size, m->rc.tag); |
348 | 348 | ||
349 | m->req = p9_tag_lookup(m->client, m->rc.tag); | 349 | m->rreq = p9_tag_lookup(m->client, m->rc.tag); |
350 | if (!m->req || (m->req->status != REQ_STATUS_SENT)) { | 350 | if (!m->rreq || (m->rreq->status != REQ_STATUS_SENT)) { |
351 | p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", | 351 | p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", |
352 | m->rc.tag); | 352 | m->rc.tag); |
353 | err = -EIO; | 353 | err = -EIO; |
354 | goto error; | 354 | goto error; |
355 | } | 355 | } |
356 | 356 | ||
357 | if (m->req->rc == NULL) { | 357 | if (!m->rreq->rc.sdata) { |
358 | p9_debug(P9_DEBUG_ERROR, | 358 | p9_debug(P9_DEBUG_ERROR, |
359 | "No recv fcall for tag %d (req %p), disconnecting!\n", | 359 | "No recv fcall for tag %d (req %p), disconnecting!\n", |
360 | m->rc.tag, m->req); | 360 | m->rc.tag, m->rreq); |
361 | m->req = NULL; | 361 | m->rreq = NULL; |
362 | err = -EIO; | 362 | err = -EIO; |
363 | goto error; | 363 | goto error; |
364 | } | 364 | } |
365 | m->rc.sdata = (char *)m->req->rc + sizeof(struct p9_fcall); | 365 | m->rc.sdata = m->rreq->rc.sdata; |
366 | memcpy(m->rc.sdata, m->tmp_buf, m->rc.capacity); | 366 | memcpy(m->rc.sdata, m->tmp_buf, m->rc.capacity); |
367 | m->rc.capacity = m->rc.size; | 367 | m->rc.capacity = m->rc.size; |
368 | } | 368 | } |
@@ -370,20 +370,27 @@ static void p9_read_work(struct work_struct *work) | |||
370 | /* packet is read in | 370 | /* packet is read in |
371 | * not an else because some packets (like clunk) have no payload | 371 | * not an else because some packets (like clunk) have no payload |
372 | */ | 372 | */ |
373 | if ((m->req) && (m->rc.offset == m->rc.capacity)) { | 373 | if ((m->rreq) && (m->rc.offset == m->rc.capacity)) { |
374 | p9_debug(P9_DEBUG_TRANS, "got new packet\n"); | 374 | p9_debug(P9_DEBUG_TRANS, "got new packet\n"); |
375 | m->req->rc->size = m->rc.offset; | 375 | m->rreq->rc.size = m->rc.offset; |
376 | spin_lock(&m->client->lock); | 376 | spin_lock(&m->client->lock); |
377 | if (m->req->status != REQ_STATUS_ERROR) | 377 | if (m->rreq->status == REQ_STATUS_SENT) { |
378 | status = REQ_STATUS_RCVD; | 378 | list_del(&m->rreq->req_list); |
379 | list_del(&m->req->req_list); | 379 | p9_client_cb(m->client, m->rreq, REQ_STATUS_RCVD); |
380 | /* update req->status while holding client->lock */ | 380 | } else { |
381 | p9_client_cb(m->client, m->req, status); | 381 | spin_unlock(&m->client->lock); |
382 | p9_debug(P9_DEBUG_ERROR, | ||
383 | "Request tag %d errored out while we were reading the reply\n", | ||
384 | m->rc.tag); | ||
385 | err = -EIO; | ||
386 | goto error; | ||
387 | } | ||
382 | spin_unlock(&m->client->lock); | 388 | spin_unlock(&m->client->lock); |
383 | m->rc.sdata = NULL; | 389 | m->rc.sdata = NULL; |
384 | m->rc.offset = 0; | 390 | m->rc.offset = 0; |
385 | m->rc.capacity = 0; | 391 | m->rc.capacity = 0; |
386 | m->req = NULL; | 392 | p9_req_put(m->rreq); |
393 | m->rreq = NULL; | ||
387 | } | 394 | } |
388 | 395 | ||
389 | end_clear: | 396 | end_clear: |
@@ -469,9 +476,11 @@ static void p9_write_work(struct work_struct *work) | |||
469 | p9_debug(P9_DEBUG_TRANS, "move req %p\n", req); | 476 | p9_debug(P9_DEBUG_TRANS, "move req %p\n", req); |
470 | list_move_tail(&req->req_list, &m->req_list); | 477 | list_move_tail(&req->req_list, &m->req_list); |
471 | 478 | ||
472 | m->wbuf = req->tc->sdata; | 479 | m->wbuf = req->tc.sdata; |
473 | m->wsize = req->tc->size; | 480 | m->wsize = req->tc.size; |
474 | m->wpos = 0; | 481 | m->wpos = 0; |
482 | p9_req_get(req); | ||
483 | m->wreq = req; | ||
475 | spin_unlock(&m->client->lock); | 484 | spin_unlock(&m->client->lock); |
476 | } | 485 | } |
477 | 486 | ||
@@ -492,8 +501,11 @@ static void p9_write_work(struct work_struct *work) | |||
492 | } | 501 | } |
493 | 502 | ||
494 | m->wpos += err; | 503 | m->wpos += err; |
495 | if (m->wpos == m->wsize) | 504 | if (m->wpos == m->wsize) { |
496 | m->wpos = m->wsize = 0; | 505 | m->wpos = m->wsize = 0; |
506 | p9_req_put(m->wreq); | ||
507 | m->wreq = NULL; | ||
508 | } | ||
497 | 509 | ||
498 | end_clear: | 510 | end_clear: |
499 | clear_bit(Wworksched, &m->wsched); | 511 | clear_bit(Wworksched, &m->wsched); |
@@ -663,7 +675,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) | |||
663 | struct p9_conn *m = &ts->conn; | 675 | struct p9_conn *m = &ts->conn; |
664 | 676 | ||
665 | p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", | 677 | p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", |
666 | m, current, req->tc, req->tc->id); | 678 | m, current, &req->tc, req->tc.id); |
667 | if (m->err < 0) | 679 | if (m->err < 0) |
668 | return m->err; | 680 | return m->err; |
669 | 681 | ||
@@ -694,6 +706,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) | |||
694 | if (req->status == REQ_STATUS_UNSENT) { | 706 | if (req->status == REQ_STATUS_UNSENT) { |
695 | list_del(&req->req_list); | 707 | list_del(&req->req_list); |
696 | req->status = REQ_STATUS_FLSHD; | 708 | req->status = REQ_STATUS_FLSHD; |
709 | p9_req_put(req); | ||
697 | ret = 0; | 710 | ret = 0; |
698 | } | 711 | } |
699 | spin_unlock(&client->lock); | 712 | spin_unlock(&client->lock); |
@@ -711,6 +724,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) | |||
711 | spin_lock(&client->lock); | 724 | spin_lock(&client->lock); |
712 | list_del(&req->req_list); | 725 | list_del(&req->req_list); |
713 | spin_unlock(&client->lock); | 726 | spin_unlock(&client->lock); |
727 | p9_req_put(req); | ||
714 | 728 | ||
715 | return 0; | 729 | return 0; |
716 | } | 730 | } |
@@ -862,7 +876,15 @@ static void p9_conn_destroy(struct p9_conn *m) | |||
862 | 876 | ||
863 | p9_mux_poll_stop(m); | 877 | p9_mux_poll_stop(m); |
864 | cancel_work_sync(&m->rq); | 878 | cancel_work_sync(&m->rq); |
879 | if (m->rreq) { | ||
880 | p9_req_put(m->rreq); | ||
881 | m->rreq = NULL; | ||
882 | } | ||
865 | cancel_work_sync(&m->wq); | 883 | cancel_work_sync(&m->wq); |
884 | if (m->wreq) { | ||
885 | p9_req_put(m->wreq); | ||
886 | m->wreq = NULL; | ||
887 | } | ||
866 | 888 | ||
867 | p9_conn_cancel(m, -ECONNRESET); | 889 | p9_conn_cancel(m, -ECONNRESET); |
868 | 890 | ||
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index b513cffeeb3c..119103bfa82e 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
@@ -122,7 +122,7 @@ struct p9_rdma_context { | |||
122 | dma_addr_t busa; | 122 | dma_addr_t busa; |
123 | union { | 123 | union { |
124 | struct p9_req_t *req; | 124 | struct p9_req_t *req; |
125 | struct p9_fcall *rc; | 125 | struct p9_fcall rc; |
126 | }; | 126 | }; |
127 | }; | 127 | }; |
128 | 128 | ||
@@ -274,8 +274,7 @@ p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) | |||
274 | case RDMA_CM_EVENT_DISCONNECTED: | 274 | case RDMA_CM_EVENT_DISCONNECTED: |
275 | if (rdma) | 275 | if (rdma) |
276 | rdma->state = P9_RDMA_CLOSED; | 276 | rdma->state = P9_RDMA_CLOSED; |
277 | if (c) | 277 | c->status = Disconnected; |
278 | c->status = Disconnected; | ||
279 | break; | 278 | break; |
280 | 279 | ||
281 | case RDMA_CM_EVENT_TIMEWAIT_EXIT: | 280 | case RDMA_CM_EVENT_TIMEWAIT_EXIT: |
@@ -320,8 +319,8 @@ recv_done(struct ib_cq *cq, struct ib_wc *wc) | |||
320 | if (wc->status != IB_WC_SUCCESS) | 319 | if (wc->status != IB_WC_SUCCESS) |
321 | goto err_out; | 320 | goto err_out; |
322 | 321 | ||
323 | c->rc->size = wc->byte_len; | 322 | c->rc.size = wc->byte_len; |
324 | err = p9_parse_header(c->rc, NULL, NULL, &tag, 1); | 323 | err = p9_parse_header(&c->rc, NULL, NULL, &tag, 1); |
325 | if (err) | 324 | if (err) |
326 | goto err_out; | 325 | goto err_out; |
327 | 326 | ||
@@ -331,12 +330,13 @@ recv_done(struct ib_cq *cq, struct ib_wc *wc) | |||
331 | 330 | ||
332 | /* Check that we have not yet received a reply for this request. | 331 | /* Check that we have not yet received a reply for this request. |
333 | */ | 332 | */ |
334 | if (unlikely(req->rc)) { | 333 | if (unlikely(req->rc.sdata)) { |
335 | pr_err("Duplicate reply for request %d", tag); | 334 | pr_err("Duplicate reply for request %d", tag); |
336 | goto err_out; | 335 | goto err_out; |
337 | } | 336 | } |
338 | 337 | ||
339 | req->rc = c->rc; | 338 | req->rc.size = c->rc.size; |
339 | req->rc.sdata = c->rc.sdata; | ||
340 | p9_client_cb(client, req, REQ_STATUS_RCVD); | 340 | p9_client_cb(client, req, REQ_STATUS_RCVD); |
341 | 341 | ||
342 | out: | 342 | out: |
@@ -361,9 +361,10 @@ send_done(struct ib_cq *cq, struct ib_wc *wc) | |||
361 | container_of(wc->wr_cqe, struct p9_rdma_context, cqe); | 361 | container_of(wc->wr_cqe, struct p9_rdma_context, cqe); |
362 | 362 | ||
363 | ib_dma_unmap_single(rdma->cm_id->device, | 363 | ib_dma_unmap_single(rdma->cm_id->device, |
364 | c->busa, c->req->tc->size, | 364 | c->busa, c->req->tc.size, |
365 | DMA_TO_DEVICE); | 365 | DMA_TO_DEVICE); |
366 | up(&rdma->sq_sem); | 366 | up(&rdma->sq_sem); |
367 | p9_req_put(c->req); | ||
367 | kfree(c); | 368 | kfree(c); |
368 | } | 369 | } |
369 | 370 | ||
@@ -401,7 +402,7 @@ post_recv(struct p9_client *client, struct p9_rdma_context *c) | |||
401 | struct ib_sge sge; | 402 | struct ib_sge sge; |
402 | 403 | ||
403 | c->busa = ib_dma_map_single(rdma->cm_id->device, | 404 | c->busa = ib_dma_map_single(rdma->cm_id->device, |
404 | c->rc->sdata, client->msize, | 405 | c->rc.sdata, client->msize, |
405 | DMA_FROM_DEVICE); | 406 | DMA_FROM_DEVICE); |
406 | if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) | 407 | if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) |
407 | goto error; | 408 | goto error; |
@@ -443,9 +444,9 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) | |||
443 | **/ | 444 | **/ |
444 | if (unlikely(atomic_read(&rdma->excess_rc) > 0)) { | 445 | if (unlikely(atomic_read(&rdma->excess_rc) > 0)) { |
445 | if ((atomic_sub_return(1, &rdma->excess_rc) >= 0)) { | 446 | if ((atomic_sub_return(1, &rdma->excess_rc) >= 0)) { |
446 | /* Got one ! */ | 447 | /* Got one! */ |
447 | kfree(req->rc); | 448 | p9_fcall_fini(&req->rc); |
448 | req->rc = NULL; | 449 | req->rc.sdata = NULL; |
449 | goto dont_need_post_recv; | 450 | goto dont_need_post_recv; |
450 | } else { | 451 | } else { |
451 | /* We raced and lost. */ | 452 | /* We raced and lost. */ |
@@ -459,7 +460,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) | |||
459 | err = -ENOMEM; | 460 | err = -ENOMEM; |
460 | goto recv_error; | 461 | goto recv_error; |
461 | } | 462 | } |
462 | rpl_context->rc = req->rc; | 463 | rpl_context->rc.sdata = req->rc.sdata; |
463 | 464 | ||
464 | /* | 465 | /* |
465 | * Post a receive buffer for this request. We need to ensure | 466 | * Post a receive buffer for this request. We need to ensure |
@@ -475,11 +476,11 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) | |||
475 | 476 | ||
476 | err = post_recv(client, rpl_context); | 477 | err = post_recv(client, rpl_context); |
477 | if (err) { | 478 | if (err) { |
478 | p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); | 479 | p9_debug(P9_DEBUG_ERROR, "POST RECV failed: %d\n", err); |
479 | goto recv_error; | 480 | goto recv_error; |
480 | } | 481 | } |
481 | /* remove posted receive buffer from request structure */ | 482 | /* remove posted receive buffer from request structure */ |
482 | req->rc = NULL; | 483 | req->rc.sdata = NULL; |
483 | 484 | ||
484 | dont_need_post_recv: | 485 | dont_need_post_recv: |
485 | /* Post the request */ | 486 | /* Post the request */ |
@@ -491,7 +492,7 @@ dont_need_post_recv: | |||
491 | c->req = req; | 492 | c->req = req; |
492 | 493 | ||
493 | c->busa = ib_dma_map_single(rdma->cm_id->device, | 494 | c->busa = ib_dma_map_single(rdma->cm_id->device, |
494 | c->req->tc->sdata, c->req->tc->size, | 495 | c->req->tc.sdata, c->req->tc.size, |
495 | DMA_TO_DEVICE); | 496 | DMA_TO_DEVICE); |
496 | if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) { | 497 | if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) { |
497 | err = -EIO; | 498 | err = -EIO; |
@@ -501,7 +502,7 @@ dont_need_post_recv: | |||
501 | c->cqe.done = send_done; | 502 | c->cqe.done = send_done; |
502 | 503 | ||
503 | sge.addr = c->busa; | 504 | sge.addr = c->busa; |
504 | sge.length = c->req->tc->size; | 505 | sge.length = c->req->tc.size; |
505 | sge.lkey = rdma->pd->local_dma_lkey; | 506 | sge.lkey = rdma->pd->local_dma_lkey; |
506 | 507 | ||
507 | wr.next = NULL; | 508 | wr.next = NULL; |
@@ -544,7 +545,7 @@ dont_need_post_recv: | |||
544 | recv_error: | 545 | recv_error: |
545 | kfree(rpl_context); | 546 | kfree(rpl_context); |
546 | spin_lock_irqsave(&rdma->req_lock, flags); | 547 | spin_lock_irqsave(&rdma->req_lock, flags); |
547 | if (rdma->state < P9_RDMA_CLOSING) { | 548 | if (err != -EINTR && rdma->state < P9_RDMA_CLOSING) { |
548 | rdma->state = P9_RDMA_CLOSING; | 549 | rdma->state = P9_RDMA_CLOSING; |
549 | spin_unlock_irqrestore(&rdma->req_lock, flags); | 550 | spin_unlock_irqrestore(&rdma->req_lock, flags); |
550 | rdma_disconnect(rdma->cm_id); | 551 | rdma_disconnect(rdma->cm_id); |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 7728b0acde09..eb596c2ed546 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -155,7 +155,7 @@ static void req_done(struct virtqueue *vq) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | if (len) { | 157 | if (len) { |
158 | req->rc->size = len; | 158 | req->rc.size = len; |
159 | p9_client_cb(chan->client, req, REQ_STATUS_RCVD); | 159 | p9_client_cb(chan->client, req, REQ_STATUS_RCVD); |
160 | } | 160 | } |
161 | } | 161 | } |
@@ -207,6 +207,13 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) | |||
207 | return 1; | 207 | return 1; |
208 | } | 208 | } |
209 | 209 | ||
210 | /* Reply won't come, so drop req ref */ | ||
211 | static int p9_virtio_cancelled(struct p9_client *client, struct p9_req_t *req) | ||
212 | { | ||
213 | p9_req_put(req); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
210 | /** | 217 | /** |
211 | * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer, | 218 | * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer, |
212 | * this takes a list of pages. | 219 | * this takes a list of pages. |
@@ -273,12 +280,12 @@ req_retry: | |||
273 | out_sgs = in_sgs = 0; | 280 | out_sgs = in_sgs = 0; |
274 | /* Handle out VirtIO ring buffers */ | 281 | /* Handle out VirtIO ring buffers */ |
275 | out = pack_sg_list(chan->sg, 0, | 282 | out = pack_sg_list(chan->sg, 0, |
276 | VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); | 283 | VIRTQUEUE_NUM, req->tc.sdata, req->tc.size); |
277 | if (out) | 284 | if (out) |
278 | sgs[out_sgs++] = chan->sg; | 285 | sgs[out_sgs++] = chan->sg; |
279 | 286 | ||
280 | in = pack_sg_list(chan->sg, out, | 287 | in = pack_sg_list(chan->sg, out, |
281 | VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity); | 288 | VIRTQUEUE_NUM, req->rc.sdata, req->rc.capacity); |
282 | if (in) | 289 | if (in) |
283 | sgs[out_sgs + in_sgs++] = chan->sg + out; | 290 | sgs[out_sgs + in_sgs++] = chan->sg + out; |
284 | 291 | ||
@@ -404,6 +411,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, | |||
404 | struct scatterlist *sgs[4]; | 411 | struct scatterlist *sgs[4]; |
405 | size_t offs; | 412 | size_t offs; |
406 | int need_drop = 0; | 413 | int need_drop = 0; |
414 | int kicked = 0; | ||
407 | 415 | ||
408 | p9_debug(P9_DEBUG_TRANS, "virtio request\n"); | 416 | p9_debug(P9_DEBUG_TRANS, "virtio request\n"); |
409 | 417 | ||
@@ -411,29 +419,33 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, | |||
411 | __le32 sz; | 419 | __le32 sz; |
412 | int n = p9_get_mapped_pages(chan, &out_pages, uodata, | 420 | int n = p9_get_mapped_pages(chan, &out_pages, uodata, |
413 | outlen, &offs, &need_drop); | 421 | outlen, &offs, &need_drop); |
414 | if (n < 0) | 422 | if (n < 0) { |
415 | return n; | 423 | err = n; |
424 | goto err_out; | ||
425 | } | ||
416 | out_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE); | 426 | out_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE); |
417 | if (n != outlen) { | 427 | if (n != outlen) { |
418 | __le32 v = cpu_to_le32(n); | 428 | __le32 v = cpu_to_le32(n); |
419 | memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4); | 429 | memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4); |
420 | outlen = n; | 430 | outlen = n; |
421 | } | 431 | } |
422 | /* The size field of the message must include the length of the | 432 | /* The size field of the message must include the length of the |
423 | * header and the length of the data. We didn't actually know | 433 | * header and the length of the data. We didn't actually know |
424 | * the length of the data until this point so add it in now. | 434 | * the length of the data until this point so add it in now. |
425 | */ | 435 | */ |
426 | sz = cpu_to_le32(req->tc->size + outlen); | 436 | sz = cpu_to_le32(req->tc.size + outlen); |
427 | memcpy(&req->tc->sdata[0], &sz, sizeof(sz)); | 437 | memcpy(&req->tc.sdata[0], &sz, sizeof(sz)); |
428 | } else if (uidata) { | 438 | } else if (uidata) { |
429 | int n = p9_get_mapped_pages(chan, &in_pages, uidata, | 439 | int n = p9_get_mapped_pages(chan, &in_pages, uidata, |
430 | inlen, &offs, &need_drop); | 440 | inlen, &offs, &need_drop); |
431 | if (n < 0) | 441 | if (n < 0) { |
432 | return n; | 442 | err = n; |
443 | goto err_out; | ||
444 | } | ||
433 | in_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE); | 445 | in_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE); |
434 | if (n != inlen) { | 446 | if (n != inlen) { |
435 | __le32 v = cpu_to_le32(n); | 447 | __le32 v = cpu_to_le32(n); |
436 | memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4); | 448 | memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4); |
437 | inlen = n; | 449 | inlen = n; |
438 | } | 450 | } |
439 | } | 451 | } |
@@ -445,7 +457,7 @@ req_retry_pinned: | |||
445 | 457 | ||
446 | /* out data */ | 458 | /* out data */ |
447 | out = pack_sg_list(chan->sg, 0, | 459 | out = pack_sg_list(chan->sg, 0, |
448 | VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); | 460 | VIRTQUEUE_NUM, req->tc.sdata, req->tc.size); |
449 | 461 | ||
450 | if (out) | 462 | if (out) |
451 | sgs[out_sgs++] = chan->sg; | 463 | sgs[out_sgs++] = chan->sg; |
@@ -464,7 +476,7 @@ req_retry_pinned: | |||
464 | * alloced memory and payload onto the user buffer. | 476 | * alloced memory and payload onto the user buffer. |
465 | */ | 477 | */ |
466 | in = pack_sg_list(chan->sg, out, | 478 | in = pack_sg_list(chan->sg, out, |
467 | VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len); | 479 | VIRTQUEUE_NUM, req->rc.sdata, in_hdr_len); |
468 | if (in) | 480 | if (in) |
469 | sgs[out_sgs + in_sgs++] = chan->sg + out; | 481 | sgs[out_sgs + in_sgs++] = chan->sg + out; |
470 | 482 | ||
@@ -498,6 +510,7 @@ req_retry_pinned: | |||
498 | } | 510 | } |
499 | virtqueue_kick(chan->vq); | 511 | virtqueue_kick(chan->vq); |
500 | spin_unlock_irqrestore(&chan->lock, flags); | 512 | spin_unlock_irqrestore(&chan->lock, flags); |
513 | kicked = 1; | ||
501 | p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); | 514 | p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); |
502 | err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); | 515 | err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); |
503 | /* | 516 | /* |
@@ -518,6 +531,10 @@ err_out: | |||
518 | } | 531 | } |
519 | kvfree(in_pages); | 532 | kvfree(in_pages); |
520 | kvfree(out_pages); | 533 | kvfree(out_pages); |
534 | if (!kicked) { | ||
535 | /* reply won't come */ | ||
536 | p9_req_put(req); | ||
537 | } | ||
521 | return err; | 538 | return err; |
522 | } | 539 | } |
523 | 540 | ||
@@ -750,6 +767,7 @@ static struct p9_trans_module p9_virtio_trans = { | |||
750 | .request = p9_virtio_request, | 767 | .request = p9_virtio_request, |
751 | .zc_request = p9_virtio_zc_request, | 768 | .zc_request = p9_virtio_zc_request, |
752 | .cancel = p9_virtio_cancel, | 769 | .cancel = p9_virtio_cancel, |
770 | .cancelled = p9_virtio_cancelled, | ||
753 | /* | 771 | /* |
754 | * We leave one entry for input and one entry for response | 772 | * We leave one entry for input and one entry for response |
755 | * headers. We also skip one more entry to accomodate, address | 773 | * headers. We also skip one more entry to accomodate, address |
diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index c2d54ac76bfd..e2fbf3677b9b 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c | |||
@@ -141,7 +141,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) | |||
141 | struct xen_9pfs_front_priv *priv = NULL; | 141 | struct xen_9pfs_front_priv *priv = NULL; |
142 | RING_IDX cons, prod, masked_cons, masked_prod; | 142 | RING_IDX cons, prod, masked_cons, masked_prod; |
143 | unsigned long flags; | 143 | unsigned long flags; |
144 | u32 size = p9_req->tc->size; | 144 | u32 size = p9_req->tc.size; |
145 | struct xen_9pfs_dataring *ring; | 145 | struct xen_9pfs_dataring *ring; |
146 | int num; | 146 | int num; |
147 | 147 | ||
@@ -154,7 +154,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) | |||
154 | if (!priv || priv->client != client) | 154 | if (!priv || priv->client != client) |
155 | return -EINVAL; | 155 | return -EINVAL; |
156 | 156 | ||
157 | num = p9_req->tc->tag % priv->num_rings; | 157 | num = p9_req->tc.tag % priv->num_rings; |
158 | ring = &priv->rings[num]; | 158 | ring = &priv->rings[num]; |
159 | 159 | ||
160 | again: | 160 | again: |
@@ -176,7 +176,7 @@ again: | |||
176 | masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE); | 176 | masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE); |
177 | masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE); | 177 | masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE); |
178 | 178 | ||
179 | xen_9pfs_write_packet(ring->data.out, p9_req->tc->sdata, size, | 179 | xen_9pfs_write_packet(ring->data.out, p9_req->tc.sdata, size, |
180 | &masked_prod, masked_cons, XEN_9PFS_RING_SIZE); | 180 | &masked_prod, masked_cons, XEN_9PFS_RING_SIZE); |
181 | 181 | ||
182 | p9_req->status = REQ_STATUS_SENT; | 182 | p9_req->status = REQ_STATUS_SENT; |
@@ -185,6 +185,7 @@ again: | |||
185 | ring->intf->out_prod = prod; | 185 | ring->intf->out_prod = prod; |
186 | spin_unlock_irqrestore(&ring->lock, flags); | 186 | spin_unlock_irqrestore(&ring->lock, flags); |
187 | notify_remote_via_irq(ring->irq); | 187 | notify_remote_via_irq(ring->irq); |
188 | p9_req_put(p9_req); | ||
188 | 189 | ||
189 | return 0; | 190 | return 0; |
190 | } | 191 | } |
@@ -229,12 +230,12 @@ static void p9_xen_response(struct work_struct *work) | |||
229 | continue; | 230 | continue; |
230 | } | 231 | } |
231 | 232 | ||
232 | memcpy(req->rc, &h, sizeof(h)); | 233 | memcpy(&req->rc, &h, sizeof(h)); |
233 | req->rc->offset = 0; | 234 | req->rc.offset = 0; |
234 | 235 | ||
235 | masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE); | 236 | masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE); |
236 | /* Then, read the whole packet (including the header) */ | 237 | /* Then, read the whole packet (including the header) */ |
237 | xen_9pfs_read_packet(req->rc->sdata, ring->data.in, h.size, | 238 | xen_9pfs_read_packet(req->rc.sdata, ring->data.in, h.size, |
238 | masked_prod, &masked_cons, | 239 | masked_prod, &masked_cons, |
239 | XEN_9PFS_RING_SIZE); | 240 | XEN_9PFS_RING_SIZE); |
240 | 241 | ||
@@ -391,8 +392,8 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev, | |||
391 | unsigned int max_rings, max_ring_order, len = 0; | 392 | unsigned int max_rings, max_ring_order, len = 0; |
392 | 393 | ||
393 | versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len); | 394 | versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len); |
394 | if (!len) | 395 | if (IS_ERR(versions)) |
395 | return -EINVAL; | 396 | return PTR_ERR(versions); |
396 | if (strcmp(versions, "1")) { | 397 | if (strcmp(versions, "1")) { |
397 | kfree(versions); | 398 | kfree(versions); |
398 | return -EINVAL; | 399 | return -EINVAL; |
diff --git a/net/9p/util.c b/net/9p/util.c deleted file mode 100644 index 55ad98277e85..000000000000 --- a/net/9p/util.c +++ /dev/null | |||
@@ -1,140 +0,0 @@ | |||
1 | /* | ||
2 | * net/9p/util.c | ||
3 | * | ||
4 | * This file contains some helper functions | ||
5 | * | ||
6 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | ||
8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 | ||
12 | * as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to: | ||
21 | * Free Software Foundation | ||
22 | * 51 Franklin Street, Fifth Floor | ||
23 | * Boston, MA 02111-1301 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/fs.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/parser.h> | ||
32 | #include <linux/idr.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <net/9p/9p.h> | ||
35 | |||
36 | /** | ||
37 | * struct p9_idpool - per-connection accounting for tag idpool | ||
38 | * @lock: protects the pool | ||
39 | * @pool: idr to allocate tag id from | ||
40 | * | ||
41 | */ | ||
42 | |||
43 | struct p9_idpool { | ||
44 | spinlock_t lock; | ||
45 | struct idr pool; | ||
46 | }; | ||
47 | |||
48 | /** | ||
49 | * p9_idpool_create - create a new per-connection id pool | ||
50 | * | ||
51 | */ | ||
52 | |||
53 | struct p9_idpool *p9_idpool_create(void) | ||
54 | { | ||
55 | struct p9_idpool *p; | ||
56 | |||
57 | p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL); | ||
58 | if (!p) | ||
59 | return ERR_PTR(-ENOMEM); | ||
60 | |||
61 | spin_lock_init(&p->lock); | ||
62 | idr_init(&p->pool); | ||
63 | |||
64 | return p; | ||
65 | } | ||
66 | EXPORT_SYMBOL(p9_idpool_create); | ||
67 | |||
68 | /** | ||
69 | * p9_idpool_destroy - create a new per-connection id pool | ||
70 | * @p: idpool to destroy | ||
71 | */ | ||
72 | |||
73 | void p9_idpool_destroy(struct p9_idpool *p) | ||
74 | { | ||
75 | idr_destroy(&p->pool); | ||
76 | kfree(p); | ||
77 | } | ||
78 | EXPORT_SYMBOL(p9_idpool_destroy); | ||
79 | |||
80 | /** | ||
81 | * p9_idpool_get - allocate numeric id from pool | ||
82 | * @p: pool to allocate from | ||
83 | * | ||
84 | * Bugs: This seems to be an awful generic function, should it be in idr.c with | ||
85 | * the lock included in struct idr? | ||
86 | */ | ||
87 | |||
88 | int p9_idpool_get(struct p9_idpool *p) | ||
89 | { | ||
90 | int i; | ||
91 | unsigned long flags; | ||
92 | |||
93 | idr_preload(GFP_NOFS); | ||
94 | spin_lock_irqsave(&p->lock, flags); | ||
95 | |||
96 | /* no need to store exactly p, we just need something non-null */ | ||
97 | i = idr_alloc(&p->pool, p, 0, 0, GFP_NOWAIT); | ||
98 | |||
99 | spin_unlock_irqrestore(&p->lock, flags); | ||
100 | idr_preload_end(); | ||
101 | if (i < 0) | ||
102 | return -1; | ||
103 | |||
104 | p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", i, p); | ||
105 | return i; | ||
106 | } | ||
107 | EXPORT_SYMBOL(p9_idpool_get); | ||
108 | |||
109 | /** | ||
110 | * p9_idpool_put - release numeric id from pool | ||
111 | * @id: numeric id which is being released | ||
112 | * @p: pool to release id into | ||
113 | * | ||
114 | * Bugs: This seems to be an awful generic function, should it be in idr.c with | ||
115 | * the lock included in struct idr? | ||
116 | */ | ||
117 | |||
118 | void p9_idpool_put(int id, struct p9_idpool *p) | ||
119 | { | ||
120 | unsigned long flags; | ||
121 | |||
122 | p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", id, p); | ||
123 | |||
124 | spin_lock_irqsave(&p->lock, flags); | ||
125 | idr_remove(&p->pool, id); | ||
126 | spin_unlock_irqrestore(&p->lock, flags); | ||
127 | } | ||
128 | EXPORT_SYMBOL(p9_idpool_put); | ||
129 | |||
130 | /** | ||
131 | * p9_idpool_check - check if the specified id is available | ||
132 | * @id: id to check | ||
133 | * @p: pool to check | ||
134 | */ | ||
135 | |||
136 | int p9_idpool_check(int id, struct p9_idpool *p) | ||
137 | { | ||
138 | return idr_find(&p->pool, id) != NULL; | ||
139 | } | ||
140 | EXPORT_SYMBOL(p9_idpool_check); | ||