aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osd/osd_initiator.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/osd/osd_initiator.c')
-rw-r--r--drivers/scsi/osd/osd_initiator.c181
1 files changed, 136 insertions, 45 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 7a117c18114c..ee4b6914667f 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -39,6 +39,8 @@
39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */ 40 */
41 41
42#include <linux/slab.h>
43
42#include <scsi/osd_initiator.h> 44#include <scsi/osd_initiator.h>
43#include <scsi/osd_sec.h> 45#include <scsi/osd_sec.h>
44#include <scsi/osd_attributes.h> 46#include <scsi/osd_attributes.h>
@@ -73,7 +75,8 @@ static const char *_osd_ver_desc(struct osd_request *or)
73 75
74#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len) 76#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
75 77
76static int _osd_print_system_info(struct osd_dev *od, void *caps) 78static int _osd_get_print_system_info(struct osd_dev *od,
79 void *caps, struct osd_dev_info *odi)
77{ 80{
78 struct osd_request *or; 81 struct osd_request *or;
79 struct osd_attr get_attrs[] = { 82 struct osd_attr get_attrs[] = {
@@ -137,8 +140,12 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps)
137 OSD_INFO("PRODUCT_SERIAL_NUMBER [%s]\n", 140 OSD_INFO("PRODUCT_SERIAL_NUMBER [%s]\n",
138 (char *)pFirst); 141 (char *)pFirst);
139 142
140 pFirst = get_attrs[a].val_ptr; 143 odi->osdname_len = get_attrs[a].len;
141 OSD_INFO("OSD_NAME [%s]\n", (char *)pFirst); 144 /* Avoid NULL for memcmp optimization 0-length is good enough */
145 odi->osdname = kzalloc(odi->osdname_len + 1, GFP_KERNEL);
146 if (odi->osdname_len)
147 memcpy(odi->osdname, get_attrs[a].val_ptr, odi->osdname_len);
148 OSD_INFO("OSD_NAME [%s]\n", odi->osdname);
142 a++; 149 a++;
143 150
144 pFirst = get_attrs[a++].val_ptr; 151 pFirst = get_attrs[a++].val_ptr;
@@ -171,6 +178,14 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps)
171 sid_dump, sizeof(sid_dump), true); 178 sid_dump, sizeof(sid_dump), true);
172 OSD_INFO("OSD_SYSTEM_ID(%d)\n" 179 OSD_INFO("OSD_SYSTEM_ID(%d)\n"
173 " [%s]\n", len, sid_dump); 180 " [%s]\n", len, sid_dump);
181
182 if (unlikely(len > sizeof(odi->systemid))) {
183 OSD_ERR("OSD Target error: OSD_SYSTEM_ID too long(%d). "
184 "device idetification might not work\n", len);
185 len = sizeof(odi->systemid);
186 }
187 odi->systemid_len = len;
188 memcpy(odi->systemid, get_attrs[a].val_ptr, len);
174 a++; 189 a++;
175 } 190 }
176out: 191out:
@@ -178,16 +193,17 @@ out:
178 return ret; 193 return ret;
179} 194}
180 195
181int osd_auto_detect_ver(struct osd_dev *od, void *caps) 196int osd_auto_detect_ver(struct osd_dev *od,
197 void *caps, struct osd_dev_info *odi)
182{ 198{
183 int ret; 199 int ret;
184 200
185 /* Auto-detect the osd version */ 201 /* Auto-detect the osd version */
186 ret = _osd_print_system_info(od, caps); 202 ret = _osd_get_print_system_info(od, caps, odi);
187 if (ret) { 203 if (ret) {
188 osd_dev_set_ver(od, OSD_VER1); 204 osd_dev_set_ver(od, OSD_VER1);
189 OSD_DEBUG("converting to OSD1\n"); 205 OSD_DEBUG("converting to OSD1\n");
190 ret = _osd_print_system_info(od, caps); 206 ret = _osd_get_print_system_info(od, caps, odi);
191 } 207 }
192 208
193 return ret; 209 return ret;
@@ -418,30 +434,23 @@ static void _osd_free_seg(struct osd_request *or __unused,
418 seg->alloc_size = 0; 434 seg->alloc_size = 0;
419} 435}
420 436
421static void _put_request(struct request *rq , bool is_async) 437static void _put_request(struct request *rq)
422{ 438{
423 if (is_async) { 439 /*
424 WARN_ON(rq->bio); 440 * If osd_finalize_request() was called but the request was not
425 __blk_put_request(rq->q, rq); 441 * executed through the block layer, then we must release BIOs.
426 } else { 442 * TODO: Keep error code in or->async_error. Need to audit all
427 /* 443 * code paths.
428 * If osd_finalize_request() was called but the request was not 444 */
429 * executed through the block layer, then we must release BIOs. 445 if (unlikely(rq->bio))
430 * TODO: Keep error code in or->async_error. Need to audit all 446 blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
431 * code paths. 447 else
432 */ 448 blk_put_request(rq);
433 if (unlikely(rq->bio))
434 blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
435 else
436 blk_put_request(rq);
437 }
438} 449}
439 450
440void osd_end_request(struct osd_request *or) 451void osd_end_request(struct osd_request *or)
441{ 452{
442 struct request *rq = or->request; 453 struct request *rq = or->request;
443 /* IMPORTANT: make sure this agrees with osd_execute_request_async */
444 bool is_async = (or->request->end_io_data == or);
445 454
446 _osd_free_seg(or, &or->set_attr); 455 _osd_free_seg(or, &or->set_attr);
447 _osd_free_seg(or, &or->enc_get_attr); 456 _osd_free_seg(or, &or->enc_get_attr);
@@ -449,19 +458,34 @@ void osd_end_request(struct osd_request *or)
449 458
450 if (rq) { 459 if (rq) {
451 if (rq->next_rq) { 460 if (rq->next_rq) {
452 _put_request(rq->next_rq, is_async); 461 _put_request(rq->next_rq);
453 rq->next_rq = NULL; 462 rq->next_rq = NULL;
454 } 463 }
455 464
456 _put_request(rq, is_async); 465 _put_request(rq);
457 } 466 }
458 _osd_request_free(or); 467 _osd_request_free(or);
459} 468}
460EXPORT_SYMBOL(osd_end_request); 469EXPORT_SYMBOL(osd_end_request);
461 470
471static void _set_error_resid(struct osd_request *or, struct request *req,
472 int error)
473{
474 or->async_error = error;
475 or->req_errors = req->errors ? : error;
476 or->sense_len = req->sense_len;
477 if (or->out.req)
478 or->out.residual = or->out.req->resid_len;
479 if (or->in.req)
480 or->in.residual = or->in.req->resid_len;
481}
482
462int osd_execute_request(struct osd_request *or) 483int osd_execute_request(struct osd_request *or)
463{ 484{
464 return blk_execute_rq(or->request->q, NULL, or->request, 0); 485 int error = blk_execute_rq(or->request->q, NULL, or->request, 0);
486
487 _set_error_resid(or, or->request, error);
488 return error;
465} 489}
466EXPORT_SYMBOL(osd_execute_request); 490EXPORT_SYMBOL(osd_execute_request);
467 491
@@ -469,10 +493,16 @@ static void osd_request_async_done(struct request *req, int error)
469{ 493{
470 struct osd_request *or = req->end_io_data; 494 struct osd_request *or = req->end_io_data;
471 495
472 or->async_error = error; 496 _set_error_resid(or, req, error);
497 if (req->next_rq) {
498 __blk_put_request(req->q, req->next_rq);
499 req->next_rq = NULL;
500 }
473 501
474 if (error) 502 __blk_put_request(req->q, req);
475 OSD_DEBUG("osd_request_async_done error recieved %d\n", error); 503 or->request = NULL;
504 or->in.req = NULL;
505 or->out.req = NULL;
476 506
477 if (or->async_done) 507 if (or->async_done)
478 or->async_done(or, or->async_private); 508 or->async_done(or, or->async_private);
@@ -1153,6 +1183,7 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
1153 "c=%d r=%d n=%d\n", 1183 "c=%d r=%d n=%d\n",
1154 cur_bytes, returned_bytes, n); 1184 cur_bytes, returned_bytes, n);
1155 oa->val_ptr = NULL; 1185 oa->val_ptr = NULL;
1186 cur_bytes = returned_bytes; /* break the caller loop */
1156 break; 1187 break;
1157 } 1188 }
1158 1189
@@ -1404,6 +1435,10 @@ int osd_finalize_request(struct osd_request *or,
1404 cdbh->command_specific_options |= or->attributes_mode; 1435 cdbh->command_specific_options |= or->attributes_mode;
1405 if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) { 1436 if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
1406 ret = _osd_req_finalize_attr_page(or); 1437 ret = _osd_req_finalize_attr_page(or);
1438 if (ret) {
1439 OSD_DEBUG("_osd_req_finalize_attr_page failed\n");
1440 return ret;
1441 }
1407 } else { 1442 } else {
1408 /* TODO: I think that for the GET_ATTR command these 2 should 1443 /* TODO: I think that for the GET_ATTR command these 2 should
1409 * be reversed to keep them in execution order (for embeded 1444 * be reversed to keep them in execution order (for embeded
@@ -1436,6 +1471,15 @@ int osd_finalize_request(struct osd_request *or,
1436} 1471}
1437EXPORT_SYMBOL(osd_finalize_request); 1472EXPORT_SYMBOL(osd_finalize_request);
1438 1473
1474static bool _is_osd_security_code(int code)
1475{
1476 return (code == osd_security_audit_value_frozen) ||
1477 (code == osd_security_working_key_frozen) ||
1478 (code == osd_nonce_not_unique) ||
1479 (code == osd_nonce_timestamp_out_of_range) ||
1480 (code == osd_invalid_dataout_buffer_integrity_check_value);
1481}
1482
1439#define OSD_SENSE_PRINT1(fmt, a...) \ 1483#define OSD_SENSE_PRINT1(fmt, a...) \
1440 do { \ 1484 do { \
1441 if (__cur_sense_need_output) \ 1485 if (__cur_sense_need_output) \
@@ -1458,27 +1502,29 @@ int osd_req_decode_sense_full(struct osd_request *or,
1458#else 1502#else
1459 bool __cur_sense_need_output = !silent; 1503 bool __cur_sense_need_output = !silent;
1460#endif 1504#endif
1505 int ret;
1461 1506
1462 if (!or->request->errors) 1507 if (likely(!or->req_errors))
1463 return 0; 1508 return 0;
1464 1509
1465 ssdb = or->request->sense; 1510 osi = osi ? : &local_osi;
1466 sense_len = or->request->sense_len; 1511 memset(osi, 0, sizeof(*osi));
1512
1513 ssdb = (typeof(ssdb))or->sense;
1514 sense_len = or->sense_len;
1467 if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) { 1515 if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) {
1468 OSD_ERR("Block-layer returned error(0x%x) but " 1516 OSD_ERR("Block-layer returned error(0x%x) but "
1469 "sense_len(%u) || key(%d) is empty\n", 1517 "sense_len(%u) || key(%d) is empty\n",
1470 or->request->errors, sense_len, ssdb->sense_key); 1518 or->req_errors, sense_len, ssdb->sense_key);
1471 return -EIO; 1519 goto analyze;
1472 } 1520 }
1473 1521
1474 if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) { 1522 if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
1475 OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n", 1523 OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
1476 ssdb->response_code, sense_len); 1524 ssdb->response_code, sense_len);
1477 return -EIO; 1525 goto analyze;
1478 } 1526 }
1479 1527
1480 osi = osi ? : &local_osi;
1481 memset(osi, 0, sizeof(*osi));
1482 osi->key = ssdb->sense_key; 1528 osi->key = ssdb->sense_key;
1483 osi->additional_code = be16_to_cpu(ssdb->additional_sense_code); 1529 osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
1484 original_sense_len = ssdb->additional_sense_length + 8; 1530 original_sense_len = ssdb->additional_sense_length + 8;
@@ -1488,9 +1534,10 @@ int osd_req_decode_sense_full(struct osd_request *or,
1488 __cur_sense_need_output = (osi->key > scsi_sk_recovered_error); 1534 __cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
1489#endif 1535#endif
1490 OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) " 1536 OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
1491 "additional_code=0x%x\n", 1537 "additional_code=0x%x async_error=%d errors=0x%x\n",
1492 osi->key, original_sense_len, sense_len, 1538 osi->key, original_sense_len, sense_len,
1493 osi->additional_code); 1539 osi->additional_code, or->async_error,
1540 or->req_errors);
1494 1541
1495 if (original_sense_len < sense_len) 1542 if (original_sense_len < sense_len)
1496 sense_len = original_sense_len; 1543 sense_len = original_sense_len;
@@ -1569,15 +1616,14 @@ int osd_req_decode_sense_full(struct osd_request *or,
1569 { 1616 {
1570 struct osd_sense_attributes_data_descriptor 1617 struct osd_sense_attributes_data_descriptor
1571 *osadd = cur_descriptor; 1618 *osadd = cur_descriptor;
1572 int len = min(cur_len, sense_len); 1619 unsigned len = min(cur_len, sense_len);
1573 int i = 0;
1574 struct osd_sense_attr *pattr = osadd->sense_attrs; 1620 struct osd_sense_attr *pattr = osadd->sense_attrs;
1575 1621
1576 while (len < 0) { 1622 while (len >= sizeof(*pattr)) {
1577 u32 attr_page = be32_to_cpu(pattr->attr_page); 1623 u32 attr_page = be32_to_cpu(pattr->attr_page);
1578 u32 attr_id = be32_to_cpu(pattr->attr_id); 1624 u32 attr_id = be32_to_cpu(pattr->attr_id);
1579 1625
1580 if (i++ == 0) { 1626 if (!osi->attr.attr_page) {
1581 osi->attr.attr_page = attr_page; 1627 osi->attr.attr_page = attr_page;
1582 osi->attr.attr_id = attr_id; 1628 osi->attr.attr_id = attr_id;
1583 } 1629 }
@@ -1588,6 +1634,8 @@ int osd_req_decode_sense_full(struct osd_request *or,
1588 bad_attr_list++; 1634 bad_attr_list++;
1589 max_attr--; 1635 max_attr--;
1590 } 1636 }
1637
1638 len -= sizeof(*pattr);
1591 OSD_SENSE_PRINT2( 1639 OSD_SENSE_PRINT2(
1592 "osd_sense_attribute_identification" 1640 "osd_sense_attribute_identification"
1593 "attr_page=0x%x attr_id=0x%x\n", 1641 "attr_page=0x%x attr_id=0x%x\n",
@@ -1621,7 +1669,50 @@ int osd_req_decode_sense_full(struct osd_request *or,
1621 cur_descriptor += cur_len; 1669 cur_descriptor += cur_len;
1622 } 1670 }
1623 1671
1624 return (osi->key > scsi_sk_recovered_error) ? -EIO : 0; 1672analyze:
1673 if (!osi->key) {
1674 /* scsi sense is Empty, the request was never issued to target
1675 * linux return code might tell us what happened.
1676 */
1677 if (or->async_error == -ENOMEM)
1678 osi->osd_err_pri = OSD_ERR_PRI_RESOURCE;
1679 else
1680 osi->osd_err_pri = OSD_ERR_PRI_UNREACHABLE;
1681 ret = or->async_error;
1682 } else if (osi->key <= scsi_sk_recovered_error) {
1683 osi->osd_err_pri = 0;
1684 ret = 0;
1685 } else if (osi->additional_code == scsi_invalid_field_in_cdb) {
1686 if (osi->cdb_field_offset == OSD_CFO_STARTING_BYTE) {
1687 osi->osd_err_pri = OSD_ERR_PRI_CLEAR_PAGES;
1688 ret = -EFAULT; /* caller should recover from this */
1689 } else if (osi->cdb_field_offset == OSD_CFO_OBJECT_ID) {
1690 osi->osd_err_pri = OSD_ERR_PRI_NOT_FOUND;
1691 ret = -ENOENT;
1692 } else if (osi->cdb_field_offset == OSD_CFO_PERMISSIONS) {
1693 osi->osd_err_pri = OSD_ERR_PRI_NO_ACCESS;
1694 ret = -EACCES;
1695 } else {
1696 osi->osd_err_pri = OSD_ERR_PRI_BAD_CRED;
1697 ret = -EINVAL;
1698 }
1699 } else if (osi->additional_code == osd_quota_error) {
1700 osi->osd_err_pri = OSD_ERR_PRI_NO_SPACE;
1701 ret = -ENOSPC;
1702 } else if (_is_osd_security_code(osi->additional_code)) {
1703 osi->osd_err_pri = OSD_ERR_PRI_BAD_CRED;
1704 ret = -EINVAL;
1705 } else {
1706 osi->osd_err_pri = OSD_ERR_PRI_EIO;
1707 ret = -EIO;
1708 }
1709
1710 if (!or->out.residual)
1711 or->out.residual = or->out.total_bytes;
1712 if (!or->in.residual)
1713 or->in.residual = or->in.total_bytes;
1714
1715 return ret;
1625} 1716}
1626EXPORT_SYMBOL(osd_req_decode_sense_full); 1717EXPORT_SYMBOL(osd_req_decode_sense_full);
1627 1718