diff options
-rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 88 | ||||
-rw-r--r-- | include/scsi/osd_initiator.h | 5 |
2 files changed, 50 insertions, 43 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 | } |
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index 39d6d1097153..a8f370126632 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h | |||
@@ -142,6 +142,7 @@ struct osd_request { | |||
142 | struct _osd_io_info { | 142 | struct _osd_io_info { |
143 | struct bio *bio; | 143 | struct bio *bio; |
144 | u64 total_bytes; | 144 | u64 total_bytes; |
145 | u64 residual; | ||
145 | struct request *req; | 146 | struct request *req; |
146 | struct _osd_req_data_segment *last_seg; | 147 | struct _osd_req_data_segment *last_seg; |
147 | u8 *pad_buff; | 148 | u8 *pad_buff; |
@@ -150,12 +151,14 @@ struct osd_request { | |||
150 | gfp_t alloc_flags; | 151 | gfp_t alloc_flags; |
151 | unsigned timeout; | 152 | unsigned timeout; |
152 | unsigned retries; | 153 | unsigned retries; |
154 | unsigned sense_len; | ||
153 | u8 sense[OSD_MAX_SENSE_LEN]; | 155 | u8 sense[OSD_MAX_SENSE_LEN]; |
154 | enum osd_attributes_mode attributes_mode; | 156 | enum osd_attributes_mode attributes_mode; |
155 | 157 | ||
156 | osd_req_done_fn *async_done; | 158 | osd_req_done_fn *async_done; |
157 | void *async_private; | 159 | void *async_private; |
158 | int async_error; | 160 | int async_error; |
161 | int req_errors; | ||
159 | }; | 162 | }; |
160 | 163 | ||
161 | static inline bool osd_req_is_ver1(struct osd_request *or) | 164 | static inline bool osd_req_is_ver1(struct osd_request *or) |
@@ -297,8 +300,6 @@ enum osd_err_priority { | |||
297 | }; | 300 | }; |
298 | 301 | ||
299 | struct osd_sense_info { | 302 | struct osd_sense_info { |
300 | u64 out_resid; /* Zero on success otherwise out residual */ | ||
301 | u64 in_resid; /* Zero on success otherwise in residual */ | ||
302 | enum osd_err_priority osd_err_pri; | 303 | enum osd_err_priority osd_err_pri; |
303 | 304 | ||
304 | int key; /* one of enum scsi_sense_keys */ | 305 | int key; /* one of enum scsi_sense_keys */ |