diff options
author | Or Gerlitz <ogerlitz@voltaire.com> | 2010-02-08 08:17:11 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2010-02-24 12:41:09 -0500 |
commit | 1cef4659850eeb862c248c7670e404d7a1711ed1 (patch) | |
tree | 3fa1699654b4aceab045bcf2d8acd5d2ecaf4c41 /drivers/infiniband | |
parent | 676ad585531e965416fd958747894541dabcec96 (diff) |
IB/iser: Revert commit bba7ebb "avoid recv buffer exhaustion"
We will make a major change in the recv buffer posting logic, after
which the problem commit bba7ebb "avoid recv buffer exhaustion caused
by unexpected PDUs" comes to solve doesn't exist any more, so revert it.
Signed-off-by: Or Gerlitz <ogerlitz@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.h | 3 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_initiator.c | 132 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_verbs.c | 1 |
3 files changed, 41 insertions, 95 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index 9d529cae1f0d..e8dfdcfa1daf 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h | |||
@@ -252,9 +252,6 @@ struct iser_conn { | |||
252 | wait_queue_head_t wait; /* waitq for conn/disconn */ | 252 | wait_queue_head_t wait; /* waitq for conn/disconn */ |
253 | atomic_t post_recv_buf_count; /* posted rx count */ | 253 | atomic_t post_recv_buf_count; /* posted rx count */ |
254 | atomic_t post_send_buf_count; /* posted tx count */ | 254 | atomic_t post_send_buf_count; /* posted tx count */ |
255 | atomic_t unexpected_pdu_count;/* count of received * | ||
256 | * unexpected pdus * | ||
257 | * not yet retired */ | ||
258 | char name[ISER_OBJECT_NAME_SIZE]; | 255 | char name[ISER_OBJECT_NAME_SIZE]; |
259 | struct iser_page_vec *page_vec; /* represents SG to fmr maps* | 256 | struct iser_page_vec *page_vec; /* represents SG to fmr maps* |
260 | * maps serialized as tx is*/ | 257 | * maps serialized as tx is*/ |
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index 9de640200ad3..5f42fbe3080c 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c | |||
@@ -183,8 +183,14 @@ static int iser_post_receive_control(struct iscsi_conn *conn) | |||
183 | struct iser_regd_buf *regd_data; | 183 | struct iser_regd_buf *regd_data; |
184 | struct iser_dto *recv_dto = NULL; | 184 | struct iser_dto *recv_dto = NULL; |
185 | struct iser_device *device = iser_conn->ib_conn->device; | 185 | struct iser_device *device = iser_conn->ib_conn->device; |
186 | int rx_data_size, err; | 186 | int rx_data_size, err = 0; |
187 | int posts, outstanding_unexp_pdus; | 187 | |
188 | rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO); | ||
189 | if (rx_desc == NULL) { | ||
190 | iser_err("Failed to alloc desc for post recv\n"); | ||
191 | return -ENOMEM; | ||
192 | } | ||
193 | rx_desc->type = ISCSI_RX; | ||
188 | 194 | ||
189 | /* for the login sequence we must support rx of upto 8K; login is done | 195 | /* for the login sequence we must support rx of upto 8K; login is done |
190 | * after conn create/bind (connect) and conn stop/bind (reconnect), | 196 | * after conn create/bind (connect) and conn stop/bind (reconnect), |
@@ -195,80 +201,46 @@ static int iser_post_receive_control(struct iscsi_conn *conn) | |||
195 | else /* FIXME till user space sets conn->max_recv_dlength correctly */ | 201 | else /* FIXME till user space sets conn->max_recv_dlength correctly */ |
196 | rx_data_size = 128; | 202 | rx_data_size = 128; |
197 | 203 | ||
198 | outstanding_unexp_pdus = | 204 | rx_desc->data = kmalloc(rx_data_size, GFP_NOIO); |
199 | atomic_xchg(&iser_conn->ib_conn->unexpected_pdu_count, 0); | 205 | if (rx_desc->data == NULL) { |
200 | 206 | iser_err("Failed to alloc data buf for post recv\n"); | |
201 | /* | 207 | err = -ENOMEM; |
202 | * in addition to the response buffer, replace those consumed by | 208 | goto post_rx_kmalloc_failure; |
203 | * unexpected pdus. | 209 | } |
204 | */ | ||
205 | for (posts = 0; posts < 1 + outstanding_unexp_pdus; posts++) { | ||
206 | rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO); | ||
207 | if (rx_desc == NULL) { | ||
208 | iser_err("Failed to alloc desc for post recv %d\n", | ||
209 | posts); | ||
210 | err = -ENOMEM; | ||
211 | goto post_rx_cache_alloc_failure; | ||
212 | } | ||
213 | rx_desc->type = ISCSI_RX; | ||
214 | rx_desc->data = kmalloc(rx_data_size, GFP_NOIO); | ||
215 | if (rx_desc->data == NULL) { | ||
216 | iser_err("Failed to alloc data buf for post recv %d\n", | ||
217 | posts); | ||
218 | err = -ENOMEM; | ||
219 | goto post_rx_kmalloc_failure; | ||
220 | } | ||
221 | 210 | ||
222 | recv_dto = &rx_desc->dto; | 211 | recv_dto = &rx_desc->dto; |
223 | recv_dto->ib_conn = iser_conn->ib_conn; | 212 | recv_dto->ib_conn = iser_conn->ib_conn; |
224 | recv_dto->regd_vector_len = 0; | 213 | recv_dto->regd_vector_len = 0; |
225 | 214 | ||
226 | regd_hdr = &rx_desc->hdr_regd_buf; | 215 | regd_hdr = &rx_desc->hdr_regd_buf; |
227 | memset(regd_hdr, 0, sizeof(struct iser_regd_buf)); | 216 | memset(regd_hdr, 0, sizeof(struct iser_regd_buf)); |
228 | regd_hdr->device = device; | 217 | regd_hdr->device = device; |
229 | regd_hdr->virt_addr = rx_desc; /* == &rx_desc->iser_header */ | 218 | regd_hdr->virt_addr = rx_desc; /* == &rx_desc->iser_header */ |
230 | regd_hdr->data_size = ISER_TOTAL_HEADERS_LEN; | 219 | regd_hdr->data_size = ISER_TOTAL_HEADERS_LEN; |
231 | 220 | ||
232 | iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE); | 221 | iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE); |
233 | 222 | ||
234 | iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0); | 223 | iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0); |
235 | 224 | ||
236 | regd_data = &rx_desc->data_regd_buf; | 225 | regd_data = &rx_desc->data_regd_buf; |
237 | memset(regd_data, 0, sizeof(struct iser_regd_buf)); | 226 | memset(regd_data, 0, sizeof(struct iser_regd_buf)); |
238 | regd_data->device = device; | 227 | regd_data->device = device; |
239 | regd_data->virt_addr = rx_desc->data; | 228 | regd_data->virt_addr = rx_desc->data; |
240 | regd_data->data_size = rx_data_size; | 229 | regd_data->data_size = rx_data_size; |
241 | 230 | ||
242 | iser_reg_single(device, regd_data, DMA_FROM_DEVICE); | 231 | iser_reg_single(device, regd_data, DMA_FROM_DEVICE); |
243 | 232 | ||
244 | iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0); | 233 | iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0); |
245 | 234 | ||
246 | err = iser_post_recv(rx_desc); | 235 | err = iser_post_recv(rx_desc); |
247 | if (err) { | 236 | if (!err) |
248 | iser_err("Failed iser_post_recv for post %d\n", posts); | 237 | return 0; |
249 | goto post_rx_post_recv_failure; | ||
250 | } | ||
251 | } | ||
252 | /* all posts successful */ | ||
253 | return 0; | ||
254 | 238 | ||
255 | post_rx_post_recv_failure: | 239 | /* iser_post_recv failed */ |
256 | iser_dto_buffs_release(recv_dto); | 240 | iser_dto_buffs_release(recv_dto); |
257 | kfree(rx_desc->data); | 241 | kfree(rx_desc->data); |
258 | post_rx_kmalloc_failure: | 242 | post_rx_kmalloc_failure: |
259 | kmem_cache_free(ig.desc_cache, rx_desc); | 243 | kmem_cache_free(ig.desc_cache, rx_desc); |
260 | post_rx_cache_alloc_failure: | ||
261 | if (posts > 0) { | ||
262 | /* | ||
263 | * response buffer posted, but did not replace all unexpected | ||
264 | * pdu recv bufs. Ignore error, retry occurs next send | ||
265 | */ | ||
266 | outstanding_unexp_pdus -= (posts - 1); | ||
267 | err = 0; | ||
268 | } | ||
269 | atomic_add(outstanding_unexp_pdus, | ||
270 | &iser_conn->ib_conn->unexpected_pdu_count); | ||
271 | |||
272 | return err; | 244 | return err; |
273 | } | 245 | } |
274 | 246 | ||
@@ -302,10 +274,8 @@ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn) | |||
302 | struct iscsi_iser_conn *iser_conn = conn->dd_data; | 274 | struct iscsi_iser_conn *iser_conn = conn->dd_data; |
303 | 275 | ||
304 | int i; | 276 | int i; |
305 | /* | 277 | /* no need to keep it in a var, we are after login so if this should |
306 | * FIXME this value should be declared to the target during login with | 278 | * be negotiated, by now the result should be available here */ |
307 | * the MaxOutstandingUnexpectedPDUs key when supported | ||
308 | */ | ||
309 | int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS; | 279 | int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS; |
310 | 280 | ||
311 | iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num); | 281 | iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num); |
@@ -507,7 +477,6 @@ int iser_send_control(struct iscsi_conn *conn, | |||
507 | int err = 0; | 477 | int err = 0; |
508 | struct iser_regd_buf *regd_buf; | 478 | struct iser_regd_buf *regd_buf; |
509 | struct iser_device *device; | 479 | struct iser_device *device; |
510 | unsigned char opcode; | ||
511 | 480 | ||
512 | if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { | 481 | if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { |
513 | iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); | 482 | iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); |
@@ -542,15 +511,10 @@ int iser_send_control(struct iscsi_conn *conn, | |||
542 | data_seg_len); | 511 | data_seg_len); |
543 | } | 512 | } |
544 | 513 | ||
545 | opcode = task->hdr->opcode & ISCSI_OPCODE_MASK; | 514 | if (iser_post_receive_control(conn) != 0) { |
546 | 515 | iser_err("post_rcv_buff failed!\n"); | |
547 | /* post recv buffer for response if one is expected */ | 516 | err = -ENOMEM; |
548 | if (!(opcode == ISCSI_OP_NOOP_OUT && task->hdr->itt == RESERVED_ITT)) { | 517 | goto send_control_error; |
549 | if (iser_post_receive_control(conn) != 0) { | ||
550 | iser_err("post_rcv_buff failed!\n"); | ||
551 | err = -ENOMEM; | ||
552 | goto send_control_error; | ||
553 | } | ||
554 | } | 518 | } |
555 | 519 | ||
556 | err = iser_post_send(mdesc); | 520 | err = iser_post_send(mdesc); |
@@ -621,20 +585,6 @@ void iser_rcv_completion(struct iser_desc *rx_desc, | |||
621 | * parallel to the execution of iser_conn_term. So the code that waits * | 585 | * parallel to the execution of iser_conn_term. So the code that waits * |
622 | * for the posted rx bufs refcount to become zero handles everything */ | 586 | * for the posted rx bufs refcount to become zero handles everything */ |
623 | atomic_dec(&conn->ib_conn->post_recv_buf_count); | 587 | atomic_dec(&conn->ib_conn->post_recv_buf_count); |
624 | |||
625 | /* | ||
626 | * if an unexpected PDU was received then the recv wr consumed must | ||
627 | * be replaced, this is done in the next send of a control-type PDU | ||
628 | */ | ||
629 | if (opcode == ISCSI_OP_NOOP_IN && hdr->itt == RESERVED_ITT) { | ||
630 | /* nop-in with itt = 0xffffffff */ | ||
631 | atomic_inc(&conn->ib_conn->unexpected_pdu_count); | ||
632 | } | ||
633 | else if (opcode == ISCSI_OP_ASYNC_EVENT) { | ||
634 | /* asyncronous message */ | ||
635 | atomic_inc(&conn->ib_conn->unexpected_pdu_count); | ||
636 | } | ||
637 | /* a reject PDU consumes the recv buf posted for the response */ | ||
638 | } | 588 | } |
639 | 589 | ||
640 | void iser_snd_completion(struct iser_desc *tx_desc) | 590 | void iser_snd_completion(struct iser_desc *tx_desc) |
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 8579f32ce38e..7092503a10e3 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -491,7 +491,6 @@ void iser_conn_init(struct iser_conn *ib_conn) | |||
491 | init_waitqueue_head(&ib_conn->wait); | 491 | init_waitqueue_head(&ib_conn->wait); |
492 | atomic_set(&ib_conn->post_recv_buf_count, 0); | 492 | atomic_set(&ib_conn->post_recv_buf_count, 0); |
493 | atomic_set(&ib_conn->post_send_buf_count, 0); | 493 | atomic_set(&ib_conn->post_send_buf_count, 0); |
494 | atomic_set(&ib_conn->unexpected_pdu_count, 0); | ||
495 | atomic_set(&ib_conn->refcount, 1); | 494 | atomic_set(&ib_conn->refcount, 1); |
496 | INIT_LIST_HEAD(&ib_conn->conn_list); | 495 | INIT_LIST_HEAD(&ib_conn->conn_list); |
497 | spin_lock_init(&ib_conn->lock); | 496 | spin_lock_init(&ib_conn->lock); |