diff options
Diffstat (limited to 'net/sunrpc/xprtrdma/svc_rdma_recvfrom.c')
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 102 |
1 files changed, 31 insertions, 71 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index c22d6b6f2db4..06ab4841537b 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
@@ -260,11 +260,16 @@ static int rdma_read_max_sge(struct svcxprt_rdma *xprt, int sge_count) | |||
260 | * On our side, we need to read into a pagelist. The first page immediately | 260 | * On our side, we need to read into a pagelist. The first page immediately |
261 | * follows the RPC header. | 261 | * follows the RPC header. |
262 | * | 262 | * |
263 | * This function returns 1 to indicate success. The data is not yet in | 263 | * This function returns: |
264 | * 0 - No error and no read-list found. | ||
265 | * | ||
266 | * 1 - Successful read-list processing. The data is not yet in | ||
264 | * the pagelist and therefore the RPC request must be deferred. The | 267 | * the pagelist and therefore the RPC request must be deferred. The |
265 | * I/O completion will enqueue the transport again and | 268 | * I/O completion will enqueue the transport again and |
266 | * svc_rdma_recvfrom will complete the request. | 269 | * svc_rdma_recvfrom will complete the request. |
267 | * | 270 | * |
271 | * <0 - Error processing/posting read-list. | ||
272 | * | ||
268 | * NOTE: The ctxt must not be touched after the last WR has been posted | 273 | * NOTE: The ctxt must not be touched after the last WR has been posted |
269 | * because the I/O completion processing may occur on another | 274 | * because the I/O completion processing may occur on another |
270 | * processor and free / modify the context. Ne touche pas! | 275 | * processor and free / modify the context. Ne touche pas! |
@@ -284,7 +289,6 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, | |||
284 | u64 sgl_offset; | 289 | u64 sgl_offset; |
285 | struct rpcrdma_read_chunk *ch; | 290 | struct rpcrdma_read_chunk *ch; |
286 | struct svc_rdma_op_ctxt *ctxt = NULL; | 291 | struct svc_rdma_op_ctxt *ctxt = NULL; |
287 | struct svc_rdma_op_ctxt *head; | ||
288 | struct svc_rdma_op_ctxt *tmp_sge_ctxt; | 292 | struct svc_rdma_op_ctxt *tmp_sge_ctxt; |
289 | struct svc_rdma_op_ctxt *tmp_ch_ctxt; | 293 | struct svc_rdma_op_ctxt *tmp_ch_ctxt; |
290 | struct chunk_sge *ch_sge_ary; | 294 | struct chunk_sge *ch_sge_ary; |
@@ -302,25 +306,19 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, | |||
302 | ch_sge_ary = (struct chunk_sge *)tmp_ch_ctxt->sge; | 306 | ch_sge_ary = (struct chunk_sge *)tmp_ch_ctxt->sge; |
303 | 307 | ||
304 | svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count); | 308 | svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count); |
309 | if (ch_count > RPCSVC_MAXPAGES) | ||
310 | return -EINVAL; | ||
305 | sge_count = rdma_rcl_to_sge(xprt, rqstp, hdr_ctxt, rmsgp, | 311 | sge_count = rdma_rcl_to_sge(xprt, rqstp, hdr_ctxt, rmsgp, |
306 | sge, ch_sge_ary, | 312 | sge, ch_sge_ary, |
307 | ch_count, byte_count); | 313 | ch_count, byte_count); |
308 | head = svc_rdma_get_context(xprt); | ||
309 | sgl_offset = 0; | 314 | sgl_offset = 0; |
310 | ch_no = 0; | 315 | ch_no = 0; |
311 | 316 | ||
312 | for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 317 | for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
313 | ch->rc_discrim != 0; ch++, ch_no++) { | 318 | ch->rc_discrim != 0; ch++, ch_no++) { |
314 | next_sge: | 319 | next_sge: |
315 | if (!ctxt) | 320 | ctxt = svc_rdma_get_context(xprt); |
316 | ctxt = head; | ||
317 | else { | ||
318 | ctxt->next = svc_rdma_get_context(xprt); | ||
319 | ctxt = ctxt->next; | ||
320 | } | ||
321 | ctxt->next = NULL; | ||
322 | ctxt->direction = DMA_FROM_DEVICE; | 321 | ctxt->direction = DMA_FROM_DEVICE; |
323 | clear_bit(RDMACTXT_F_READ_DONE, &ctxt->flags); | ||
324 | clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); | 322 | clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); |
325 | 323 | ||
326 | /* Prepare READ WR */ | 324 | /* Prepare READ WR */ |
@@ -347,20 +345,15 @@ next_sge: | |||
347 | * the client and the RPC needs to be enqueued. | 345 | * the client and the RPC needs to be enqueued. |
348 | */ | 346 | */ |
349 | set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); | 347 | set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); |
350 | ctxt->next = hdr_ctxt; | 348 | ctxt->read_hdr = hdr_ctxt; |
351 | hdr_ctxt->next = head; | ||
352 | } | 349 | } |
353 | /* Post the read */ | 350 | /* Post the read */ |
354 | err = svc_rdma_send(xprt, &read_wr); | 351 | err = svc_rdma_send(xprt, &read_wr); |
355 | if (err) { | 352 | if (err) { |
356 | printk(KERN_ERR "svcrdma: Error posting send = %d\n", | 353 | printk(KERN_ERR "svcrdma: Error %d posting RDMA_READ\n", |
357 | err); | 354 | err); |
358 | /* | 355 | set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); |
359 | * Break the circular list so free knows when | 356 | svc_rdma_put_context(ctxt, 0); |
360 | * to stop if the error happened to occur on | ||
361 | * the last read | ||
362 | */ | ||
363 | ctxt->next = NULL; | ||
364 | goto out; | 357 | goto out; |
365 | } | 358 | } |
366 | atomic_inc(&rdma_stat_read); | 359 | atomic_inc(&rdma_stat_read); |
@@ -371,7 +364,7 @@ next_sge: | |||
371 | goto next_sge; | 364 | goto next_sge; |
372 | } | 365 | } |
373 | sgl_offset = 0; | 366 | sgl_offset = 0; |
374 | err = 0; | 367 | err = 1; |
375 | } | 368 | } |
376 | 369 | ||
377 | out: | 370 | out: |
@@ -389,25 +382,12 @@ next_sge: | |||
389 | while (rqstp->rq_resused) | 382 | while (rqstp->rq_resused) |
390 | rqstp->rq_respages[--rqstp->rq_resused] = NULL; | 383 | rqstp->rq_respages[--rqstp->rq_resused] = NULL; |
391 | 384 | ||
392 | if (err) { | 385 | return err; |
393 | printk(KERN_ERR "svcrdma : RDMA_READ error = %d\n", err); | ||
394 | set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); | ||
395 | /* Free the linked list of read contexts */ | ||
396 | while (head != NULL) { | ||
397 | ctxt = head->next; | ||
398 | svc_rdma_put_context(head, 1); | ||
399 | head = ctxt; | ||
400 | } | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | return 1; | ||
405 | } | 386 | } |
406 | 387 | ||
407 | static int rdma_read_complete(struct svc_rqst *rqstp, | 388 | static int rdma_read_complete(struct svc_rqst *rqstp, |
408 | struct svc_rdma_op_ctxt *data) | 389 | struct svc_rdma_op_ctxt *head) |
409 | { | 390 | { |
410 | struct svc_rdma_op_ctxt *head = data->next; | ||
411 | int page_no; | 391 | int page_no; |
412 | int ret; | 392 | int ret; |
413 | 393 | ||
@@ -433,21 +413,12 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
433 | rqstp->rq_arg.len = head->arg.len; | 413 | rqstp->rq_arg.len = head->arg.len; |
434 | rqstp->rq_arg.buflen = head->arg.buflen; | 414 | rqstp->rq_arg.buflen = head->arg.buflen; |
435 | 415 | ||
416 | /* Free the context */ | ||
417 | svc_rdma_put_context(head, 0); | ||
418 | |||
436 | /* XXX: What should this be? */ | 419 | /* XXX: What should this be? */ |
437 | rqstp->rq_prot = IPPROTO_MAX; | 420 | rqstp->rq_prot = IPPROTO_MAX; |
438 | 421 | svc_xprt_copy_addrs(rqstp, rqstp->rq_xprt); | |
439 | /* | ||
440 | * Free the contexts we used to build the RDMA_READ. We have | ||
441 | * to be careful here because the context list uses the same | ||
442 | * next pointer used to chain the contexts associated with the | ||
443 | * RDMA_READ | ||
444 | */ | ||
445 | data->next = NULL; /* terminate circular list */ | ||
446 | do { | ||
447 | data = head->next; | ||
448 | svc_rdma_put_context(head, 0); | ||
449 | head = data; | ||
450 | } while (head != NULL); | ||
451 | 422 | ||
452 | ret = rqstp->rq_arg.head[0].iov_len | 423 | ret = rqstp->rq_arg.head[0].iov_len |
453 | + rqstp->rq_arg.page_len | 424 | + rqstp->rq_arg.page_len |
@@ -457,8 +428,6 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
457 | ret, rqstp->rq_arg.len, rqstp->rq_arg.head[0].iov_base, | 428 | ret, rqstp->rq_arg.len, rqstp->rq_arg.head[0].iov_base, |
458 | rqstp->rq_arg.head[0].iov_len); | 429 | rqstp->rq_arg.head[0].iov_len); |
459 | 430 | ||
460 | /* Indicate that we've consumed an RQ credit */ | ||
461 | rqstp->rq_xprt_ctxt = rqstp->rq_xprt; | ||
462 | svc_xprt_received(rqstp->rq_xprt); | 431 | svc_xprt_received(rqstp->rq_xprt); |
463 | return ret; | 432 | return ret; |
464 | } | 433 | } |
@@ -480,13 +449,6 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) | |||
480 | 449 | ||
481 | dprintk("svcrdma: rqstp=%p\n", rqstp); | 450 | dprintk("svcrdma: rqstp=%p\n", rqstp); |
482 | 451 | ||
483 | /* | ||
484 | * The rq_xprt_ctxt indicates if we've consumed an RQ credit | ||
485 | * or not. It is used in the rdma xpo_release_rqst function to | ||
486 | * determine whether or not to return an RQ WQE to the RQ. | ||
487 | */ | ||
488 | rqstp->rq_xprt_ctxt = NULL; | ||
489 | |||
490 | spin_lock_bh(&rdma_xprt->sc_read_complete_lock); | 452 | spin_lock_bh(&rdma_xprt->sc_read_complete_lock); |
491 | if (!list_empty(&rdma_xprt->sc_read_complete_q)) { | 453 | if (!list_empty(&rdma_xprt->sc_read_complete_q)) { |
492 | ctxt = list_entry(rdma_xprt->sc_read_complete_q.next, | 454 | ctxt = list_entry(rdma_xprt->sc_read_complete_q.next, |
@@ -537,21 +499,22 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) | |||
537 | /* If the request is invalid, reply with an error */ | 499 | /* If the request is invalid, reply with an error */ |
538 | if (len < 0) { | 500 | if (len < 0) { |
539 | if (len == -ENOSYS) | 501 | if (len == -ENOSYS) |
540 | (void)svc_rdma_send_error(rdma_xprt, rmsgp, ERR_VERS); | 502 | svc_rdma_send_error(rdma_xprt, rmsgp, ERR_VERS); |
541 | goto close_out; | 503 | goto close_out; |
542 | } | 504 | } |
543 | 505 | ||
544 | /* Read read-list data. If we would need to wait, defer | 506 | /* Read read-list data. */ |
545 | * it. Not that in this case, we don't return the RQ credit | 507 | ret = rdma_read_xdr(rdma_xprt, rmsgp, rqstp, ctxt); |
546 | * until after the read completes. | 508 | if (ret > 0) { |
547 | */ | 509 | /* read-list posted, defer until data received from client. */ |
548 | if (rdma_read_xdr(rdma_xprt, rmsgp, rqstp, ctxt)) { | ||
549 | svc_xprt_received(xprt); | 510 | svc_xprt_received(xprt); |
550 | return 0; | 511 | return 0; |
551 | } | 512 | } |
552 | 513 | if (ret < 0) { | |
553 | /* Indicate we've consumed an RQ credit */ | 514 | /* Post of read-list failed, free context. */ |
554 | rqstp->rq_xprt_ctxt = rqstp->rq_xprt; | 515 | svc_rdma_put_context(ctxt, 1); |
516 | return 0; | ||
517 | } | ||
555 | 518 | ||
556 | ret = rqstp->rq_arg.head[0].iov_len | 519 | ret = rqstp->rq_arg.head[0].iov_len |
557 | + rqstp->rq_arg.page_len | 520 | + rqstp->rq_arg.page_len |
@@ -569,11 +532,8 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) | |||
569 | return ret; | 532 | return ret; |
570 | 533 | ||
571 | close_out: | 534 | close_out: |
572 | if (ctxt) { | 535 | if (ctxt) |
573 | svc_rdma_put_context(ctxt, 1); | 536 | svc_rdma_put_context(ctxt, 1); |
574 | /* Indicate we've consumed an RQ credit */ | ||
575 | rqstp->rq_xprt_ctxt = rqstp->rq_xprt; | ||
576 | } | ||
577 | dprintk("svcrdma: transport %p is closing\n", xprt); | 537 | dprintk("svcrdma: transport %p is closing\n", xprt); |
578 | /* | 538 | /* |
579 | * Set the close bit and enqueue it. svc_recv will see the | 539 | * Set the close bit and enqueue it. svc_recv will see the |