diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 88 |
1 files changed, 47 insertions, 41 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 950202a70bcf..24223473f573 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c | |||
@@ -432,30 +432,23 @@ static void _osd_free_seg(struct osd_request *or __unused, | |||
432 | seg->alloc_size = 0; | 432 | seg->alloc_size = 0; |
433 | } | 433 | } |
434 | 434 | ||
435 | static void _put_request(struct request *rq , bool is_async) | 435 | static void _put_request(struct request *rq) |
436 | { | 436 | { |
437 | if (is_async) { | 437 | /* |
438 | WARN_ON(rq->bio); | 438 | * If osd_finalize_request() was called but the request was not |
439 | __blk_put_request(rq->q, rq); | 439 | * executed through the block layer, then we must release BIOs. |
440 | } else { | 440 | * TODO: Keep error code in or->async_error. Need to audit all |
441 | /* | 441 | * code paths. |
442 | * If osd_finalize_request() was called but the request was not | 442 | */ |
443 | * executed through the block layer, then we must release BIOs. | 443 | if (unlikely(rq->bio)) |
444 | * TODO: Keep error code in or->async_error. Need to audit all | 444 | blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq)); |
445 | * code paths. | 445 | else |
446 | */ | 446 | blk_put_request(rq); |
447 | if (unlikely(rq->bio)) | ||
448 | blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq)); | ||
449 | else | ||
450 | blk_put_request(rq); | ||
451 | } | ||
452 | } | 447 | } |
453 | 448 | ||
454 | void osd_end_request(struct osd_request *or) | 449 | void osd_end_request(struct osd_request *or) |
455 | { | 450 | { |
456 | struct request *rq = or->request; | 451 | struct request *rq = or->request; |
457 | /* IMPORTANT: make sure this agrees with osd_execute_request_async */ | ||
458 | bool is_async = (or->request->end_io_data == or); | ||
459 | 452 | ||
460 | _osd_free_seg(or, &or->set_attr); | 453 | _osd_free_seg(or, &or->set_attr); |
461 | _osd_free_seg(or, &or->enc_get_attr); | 454 | _osd_free_seg(or, &or->enc_get_attr); |
@@ -463,20 +456,34 @@ void osd_end_request(struct osd_request *or) | |||
463 | 456 | ||
464 | if (rq) { | 457 | if (rq) { |
465 | if (rq->next_rq) { | 458 | if (rq->next_rq) { |
466 | _put_request(rq->next_rq, is_async); | 459 | _put_request(rq->next_rq); |
467 | rq->next_rq = NULL; | 460 | rq->next_rq = NULL; |
468 | } | 461 | } |
469 | 462 | ||
470 | _put_request(rq, is_async); | 463 | _put_request(rq); |
471 | } | 464 | } |
472 | _osd_request_free(or); | 465 | _osd_request_free(or); |
473 | } | 466 | } |
474 | EXPORT_SYMBOL(osd_end_request); | 467 | EXPORT_SYMBOL(osd_end_request); |
475 | 468 | ||
469 | static void _set_error_resid(struct osd_request *or, struct request *req, | ||
470 | int error) | ||
471 | { | ||
472 | or->async_error = error; | ||
473 | or->req_errors = req->errors ? : error; | ||
474 | or->sense_len = req->sense_len; | ||
475 | if (or->out.req) | ||
476 | or->out.residual = or->out.req->resid_len; | ||
477 | if (or->in.req) | ||
478 | or->in.residual = or->in.req->resid_len; | ||
479 | } | ||
480 | |||
476 | int osd_execute_request(struct osd_request *or) | 481 | int osd_execute_request(struct osd_request *or) |
477 | { | 482 | { |
478 | return or->async_error = | 483 | int error = blk_execute_rq(or->request->q, NULL, or->request, 0); |
479 | blk_execute_rq(or->request->q, NULL, or->request, 0); | 484 | |
485 | _set_error_resid(or, or->request, error); | ||
486 | return error; | ||
480 | } | 487 | } |
481 | EXPORT_SYMBOL(osd_execute_request); | 488 | EXPORT_SYMBOL(osd_execute_request); |
482 | 489 | ||
@@ -484,15 +491,17 @@ static void osd_request_async_done(struct request *req, int error) | |||
484 | { | 491 | { |
485 | struct osd_request *or = req->end_io_data; | 492 | struct osd_request *or = req->end_io_data; |
486 | 493 | ||
487 | or->async_error = error; | 494 | _set_error_resid(or, req, error); |
488 | 495 | if (req->next_rq) { | |
489 | if (unlikely(error)) { | 496 | __blk_put_request(req->q, req->next_rq); |
490 | OSD_DEBUG("osd_request_async_done error recieved %d " | 497 | req->next_rq = NULL; |
491 | "errors 0x%x\n", error, req->errors); | ||
492 | if (!req->errors) /* don't miss out on this one */ | ||
493 | req->errors = error; | ||
494 | } | 498 | } |
495 | 499 | ||
500 | __blk_put_request(req->q, req); | ||
501 | or->request = NULL; | ||
502 | or->in.req = NULL; | ||
503 | or->out.req = NULL; | ||
504 | |||
496 | if (or->async_done) | 505 | if (or->async_done) |
497 | or->async_done(or, or->async_private); | 506 | or->async_done(or, or->async_private); |
498 | else | 507 | else |
@@ -1489,21 +1498,18 @@ int osd_req_decode_sense_full(struct osd_request *or, | |||
1489 | #endif | 1498 | #endif |
1490 | int ret; | 1499 | int ret; |
1491 | 1500 | ||
1492 | if (likely(!or->request->errors)) { | 1501 | if (likely(!or->req_errors)) |
1493 | osi->out_resid = 0; | ||
1494 | osi->in_resid = 0; | ||
1495 | return 0; | 1502 | return 0; |
1496 | } | ||
1497 | 1503 | ||
1498 | osi = osi ? : &local_osi; | 1504 | osi = osi ? : &local_osi; |
1499 | memset(osi, 0, sizeof(*osi)); | 1505 | memset(osi, 0, sizeof(*osi)); |
1500 | 1506 | ||
1501 | ssdb = or->request->sense; | 1507 | ssdb = (typeof(ssdb))or->sense; |
1502 | sense_len = or->request->sense_len; | 1508 | sense_len = or->sense_len; |
1503 | if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) { | 1509 | if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) { |
1504 | OSD_ERR("Block-layer returned error(0x%x) but " | 1510 | OSD_ERR("Block-layer returned error(0x%x) but " |
1505 | "sense_len(%u) || key(%d) is empty\n", | 1511 | "sense_len(%u) || key(%d) is empty\n", |
1506 | or->request->errors, sense_len, ssdb->sense_key); | 1512 | or->req_errors, sense_len, ssdb->sense_key); |
1507 | goto analyze; | 1513 | goto analyze; |
1508 | } | 1514 | } |
1509 | 1515 | ||
@@ -1525,7 +1531,7 @@ int osd_req_decode_sense_full(struct osd_request *or, | |||
1525 | "additional_code=0x%x async_error=%d errors=0x%x\n", | 1531 | "additional_code=0x%x async_error=%d errors=0x%x\n", |
1526 | osi->key, original_sense_len, sense_len, | 1532 | osi->key, original_sense_len, sense_len, |
1527 | osi->additional_code, or->async_error, | 1533 | osi->additional_code, or->async_error, |
1528 | or->request->errors); | 1534 | or->req_errors); |
1529 | 1535 | ||
1530 | if (original_sense_len < sense_len) | 1536 | if (original_sense_len < sense_len) |
1531 | sense_len = original_sense_len; | 1537 | sense_len = original_sense_len; |
@@ -1695,10 +1701,10 @@ analyze: | |||
1695 | ret = -EIO; | 1701 | ret = -EIO; |
1696 | } | 1702 | } |
1697 | 1703 | ||
1698 | if (or->out.req) | 1704 | if (!or->out.residual) |
1699 | osi->out_resid = or->out.req->resid_len ?: or->out.total_bytes; | 1705 | or->out.residual = or->out.total_bytes; |
1700 | if (or->in.req) | 1706 | if (!or->in.residual) |
1701 | osi->in_resid = or->in.req->resid_len ?: or->in.total_bytes; | 1707 | or->in.residual = or->in.total_bytes; |
1702 | 1708 | ||
1703 | return ret; | 1709 | return ret; |
1704 | } | 1710 | } |