diff options
Diffstat (limited to 'drivers/target/iscsi/iscsi_target_util.c')
-rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 274 |
1 files changed, 22 insertions, 252 deletions
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index a1acb016790..f00137f377b 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -243,7 +243,7 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr( | |||
243 | if (!cmd->tmr_req) { | 243 | if (!cmd->tmr_req) { |
244 | pr_err("Unable to allocate memory for" | 244 | pr_err("Unable to allocate memory for" |
245 | " Task Management command!\n"); | 245 | " Task Management command!\n"); |
246 | return NULL; | 246 | goto out; |
247 | } | 247 | } |
248 | /* | 248 | /* |
249 | * TASK_REASSIGN for ERL=2 / connection stays inside of | 249 | * TASK_REASSIGN for ERL=2 / connection stays inside of |
@@ -298,8 +298,6 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr( | |||
298 | return cmd; | 298 | return cmd; |
299 | out: | 299 | out: |
300 | iscsit_release_cmd(cmd); | 300 | iscsit_release_cmd(cmd); |
301 | if (se_cmd) | ||
302 | transport_free_se_cmd(se_cmd); | ||
303 | return NULL; | 301 | return NULL; |
304 | } | 302 | } |
305 | 303 | ||
@@ -877,40 +875,6 @@ void iscsit_inc_session_usage_count(struct iscsi_session *sess) | |||
877 | } | 875 | } |
878 | 876 | ||
879 | /* | 877 | /* |
880 | * Used before iscsi_do[rx,tx]_data() to determine iov and [rx,tx]_marker | ||
881 | * array counts needed for sync and steering. | ||
882 | */ | ||
883 | static int iscsit_determine_sync_and_steering_counts( | ||
884 | struct iscsi_conn *conn, | ||
885 | struct iscsi_data_count *count) | ||
886 | { | ||
887 | u32 length = count->data_length; | ||
888 | u32 marker, markint; | ||
889 | |||
890 | count->sync_and_steering = 1; | ||
891 | |||
892 | marker = (count->type == ISCSI_RX_DATA) ? | ||
893 | conn->of_marker : conn->if_marker; | ||
894 | markint = (count->type == ISCSI_RX_DATA) ? | ||
895 | (conn->conn_ops->OFMarkInt * 4) : | ||
896 | (conn->conn_ops->IFMarkInt * 4); | ||
897 | count->ss_iov_count = count->iov_count; | ||
898 | |||
899 | while (length > 0) { | ||
900 | if (length >= marker) { | ||
901 | count->ss_iov_count += 3; | ||
902 | count->ss_marker_count += 2; | ||
903 | |||
904 | length -= marker; | ||
905 | marker = markint; | ||
906 | } else | ||
907 | length = 0; | ||
908 | } | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | /* | ||
914 | * Setup conn->if_marker and conn->of_marker values based upon | 878 | * Setup conn->if_marker and conn->of_marker values based upon |
915 | * the initial marker-less interval. (see iSCSI v19 A.2) | 879 | * the initial marker-less interval. (see iSCSI v19 A.2) |
916 | */ | 880 | */ |
@@ -1292,7 +1256,7 @@ int iscsit_fe_sendpage_sg( | |||
1292 | struct kvec iov; | 1256 | struct kvec iov; |
1293 | u32 tx_hdr_size, data_len; | 1257 | u32 tx_hdr_size, data_len; |
1294 | u32 offset = cmd->first_data_sg_off; | 1258 | u32 offset = cmd->first_data_sg_off; |
1295 | int tx_sent; | 1259 | int tx_sent, iov_off; |
1296 | 1260 | ||
1297 | send_hdr: | 1261 | send_hdr: |
1298 | tx_hdr_size = ISCSI_HDR_LEN; | 1262 | tx_hdr_size = ISCSI_HDR_LEN; |
@@ -1312,9 +1276,19 @@ send_hdr: | |||
1312 | } | 1276 | } |
1313 | 1277 | ||
1314 | data_len = cmd->tx_size - tx_hdr_size - cmd->padding; | 1278 | data_len = cmd->tx_size - tx_hdr_size - cmd->padding; |
1315 | if (conn->conn_ops->DataDigest) | 1279 | /* |
1280 | * Set iov_off used by padding and data digest tx_data() calls below | ||
1281 | * in order to determine proper offset into cmd->iov_data[] | ||
1282 | */ | ||
1283 | if (conn->conn_ops->DataDigest) { | ||
1316 | data_len -= ISCSI_CRC_LEN; | 1284 | data_len -= ISCSI_CRC_LEN; |
1317 | 1285 | if (cmd->padding) | |
1286 | iov_off = (cmd->iov_data_count - 2); | ||
1287 | else | ||
1288 | iov_off = (cmd->iov_data_count - 1); | ||
1289 | } else { | ||
1290 | iov_off = (cmd->iov_data_count - 1); | ||
1291 | } | ||
1318 | /* | 1292 | /* |
1319 | * Perform sendpage() for each page in the scatterlist | 1293 | * Perform sendpage() for each page in the scatterlist |
1320 | */ | 1294 | */ |
@@ -1343,8 +1317,7 @@ send_pg: | |||
1343 | 1317 | ||
1344 | send_padding: | 1318 | send_padding: |
1345 | if (cmd->padding) { | 1319 | if (cmd->padding) { |
1346 | struct kvec *iov_p = | 1320 | struct kvec *iov_p = &cmd->iov_data[iov_off++]; |
1347 | &cmd->iov_data[cmd->iov_data_count-1]; | ||
1348 | 1321 | ||
1349 | tx_sent = tx_data(conn, iov_p, 1, cmd->padding); | 1322 | tx_sent = tx_data(conn, iov_p, 1, cmd->padding); |
1350 | if (cmd->padding != tx_sent) { | 1323 | if (cmd->padding != tx_sent) { |
@@ -1358,8 +1331,7 @@ send_padding: | |||
1358 | 1331 | ||
1359 | send_datacrc: | 1332 | send_datacrc: |
1360 | if (conn->conn_ops->DataDigest) { | 1333 | if (conn->conn_ops->DataDigest) { |
1361 | struct kvec *iov_d = | 1334 | struct kvec *iov_d = &cmd->iov_data[iov_off]; |
1362 | &cmd->iov_data[cmd->iov_data_count]; | ||
1363 | 1335 | ||
1364 | tx_sent = tx_data(conn, iov_d, 1, ISCSI_CRC_LEN); | 1336 | tx_sent = tx_data(conn, iov_d, 1, ISCSI_CRC_LEN); |
1365 | if (ISCSI_CRC_LEN != tx_sent) { | 1337 | if (ISCSI_CRC_LEN != tx_sent) { |
@@ -1433,8 +1405,7 @@ static int iscsit_do_rx_data( | |||
1433 | struct iscsi_data_count *count) | 1405 | struct iscsi_data_count *count) |
1434 | { | 1406 | { |
1435 | int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; | 1407 | int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; |
1436 | u32 rx_marker_val[count->ss_marker_count], rx_marker_iov = 0; | 1408 | struct kvec *iov_p; |
1437 | struct kvec iov[count->ss_iov_count], *iov_p; | ||
1438 | struct msghdr msg; | 1409 | struct msghdr msg; |
1439 | 1410 | ||
1440 | if (!conn || !conn->sock || !conn->conn_ops) | 1411 | if (!conn || !conn->sock || !conn->conn_ops) |
@@ -1442,93 +1413,8 @@ static int iscsit_do_rx_data( | |||
1442 | 1413 | ||
1443 | memset(&msg, 0, sizeof(struct msghdr)); | 1414 | memset(&msg, 0, sizeof(struct msghdr)); |
1444 | 1415 | ||
1445 | if (count->sync_and_steering) { | 1416 | iov_p = count->iov; |
1446 | int size = 0; | 1417 | iov_len = count->iov_count; |
1447 | u32 i, orig_iov_count = 0; | ||
1448 | u32 orig_iov_len = 0, orig_iov_loc = 0; | ||
1449 | u32 iov_count = 0, per_iov_bytes = 0; | ||
1450 | u32 *rx_marker, old_rx_marker = 0; | ||
1451 | struct kvec *iov_record; | ||
1452 | |||
1453 | memset(&rx_marker_val, 0, | ||
1454 | count->ss_marker_count * sizeof(u32)); | ||
1455 | memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec)); | ||
1456 | |||
1457 | iov_record = count->iov; | ||
1458 | orig_iov_count = count->iov_count; | ||
1459 | rx_marker = &conn->of_marker; | ||
1460 | |||
1461 | i = 0; | ||
1462 | size = data; | ||
1463 | orig_iov_len = iov_record[orig_iov_loc].iov_len; | ||
1464 | while (size > 0) { | ||
1465 | pr_debug("rx_data: #1 orig_iov_len %u," | ||
1466 | " orig_iov_loc %u\n", orig_iov_len, orig_iov_loc); | ||
1467 | pr_debug("rx_data: #2 rx_marker %u, size" | ||
1468 | " %u\n", *rx_marker, size); | ||
1469 | |||
1470 | if (orig_iov_len >= *rx_marker) { | ||
1471 | iov[iov_count].iov_len = *rx_marker; | ||
1472 | iov[iov_count++].iov_base = | ||
1473 | (iov_record[orig_iov_loc].iov_base + | ||
1474 | per_iov_bytes); | ||
1475 | |||
1476 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1477 | iov[iov_count++].iov_base = | ||
1478 | &rx_marker_val[rx_marker_iov++]; | ||
1479 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1480 | iov[iov_count++].iov_base = | ||
1481 | &rx_marker_val[rx_marker_iov++]; | ||
1482 | old_rx_marker = *rx_marker; | ||
1483 | |||
1484 | /* | ||
1485 | * OFMarkInt is in 32-bit words. | ||
1486 | */ | ||
1487 | *rx_marker = (conn->conn_ops->OFMarkInt * 4); | ||
1488 | size -= old_rx_marker; | ||
1489 | orig_iov_len -= old_rx_marker; | ||
1490 | per_iov_bytes += old_rx_marker; | ||
1491 | |||
1492 | pr_debug("rx_data: #3 new_rx_marker" | ||
1493 | " %u, size %u\n", *rx_marker, size); | ||
1494 | } else { | ||
1495 | iov[iov_count].iov_len = orig_iov_len; | ||
1496 | iov[iov_count++].iov_base = | ||
1497 | (iov_record[orig_iov_loc].iov_base + | ||
1498 | per_iov_bytes); | ||
1499 | |||
1500 | per_iov_bytes = 0; | ||
1501 | *rx_marker -= orig_iov_len; | ||
1502 | size -= orig_iov_len; | ||
1503 | |||
1504 | if (size) | ||
1505 | orig_iov_len = | ||
1506 | iov_record[++orig_iov_loc].iov_len; | ||
1507 | |||
1508 | pr_debug("rx_data: #4 new_rx_marker" | ||
1509 | " %u, size %u\n", *rx_marker, size); | ||
1510 | } | ||
1511 | } | ||
1512 | data += (rx_marker_iov * (MARKER_SIZE / 2)); | ||
1513 | |||
1514 | iov_p = &iov[0]; | ||
1515 | iov_len = iov_count; | ||
1516 | |||
1517 | if (iov_count > count->ss_iov_count) { | ||
1518 | pr_err("iov_count: %d, count->ss_iov_count:" | ||
1519 | " %d\n", iov_count, count->ss_iov_count); | ||
1520 | return -1; | ||
1521 | } | ||
1522 | if (rx_marker_iov > count->ss_marker_count) { | ||
1523 | pr_err("rx_marker_iov: %d, count->ss_marker" | ||
1524 | "_count: %d\n", rx_marker_iov, | ||
1525 | count->ss_marker_count); | ||
1526 | return -1; | ||
1527 | } | ||
1528 | } else { | ||
1529 | iov_p = count->iov; | ||
1530 | iov_len = count->iov_count; | ||
1531 | } | ||
1532 | 1418 | ||
1533 | while (total_rx < data) { | 1419 | while (total_rx < data) { |
1534 | rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, | 1420 | rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, |
@@ -1543,16 +1429,6 @@ static int iscsit_do_rx_data( | |||
1543 | rx_loop, total_rx, data); | 1429 | rx_loop, total_rx, data); |
1544 | } | 1430 | } |
1545 | 1431 | ||
1546 | if (count->sync_and_steering) { | ||
1547 | int j; | ||
1548 | for (j = 0; j < rx_marker_iov; j++) { | ||
1549 | pr_debug("rx_data: #5 j: %d, offset: %d\n", | ||
1550 | j, rx_marker_val[j]); | ||
1551 | conn->of_marker_offset = rx_marker_val[j]; | ||
1552 | } | ||
1553 | total_rx -= (rx_marker_iov * (MARKER_SIZE / 2)); | ||
1554 | } | ||
1555 | |||
1556 | return total_rx; | 1432 | return total_rx; |
1557 | } | 1433 | } |
1558 | 1434 | ||
@@ -1561,8 +1437,7 @@ static int iscsit_do_tx_data( | |||
1561 | struct iscsi_data_count *count) | 1437 | struct iscsi_data_count *count) |
1562 | { | 1438 | { |
1563 | int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; | 1439 | int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; |
1564 | u32 tx_marker_val[count->ss_marker_count], tx_marker_iov = 0; | 1440 | struct kvec *iov_p; |
1565 | struct kvec iov[count->ss_iov_count], *iov_p; | ||
1566 | struct msghdr msg; | 1441 | struct msghdr msg; |
1567 | 1442 | ||
1568 | if (!conn || !conn->sock || !conn->conn_ops) | 1443 | if (!conn || !conn->sock || !conn->conn_ops) |
@@ -1575,98 +1450,8 @@ static int iscsit_do_tx_data( | |||
1575 | 1450 | ||
1576 | memset(&msg, 0, sizeof(struct msghdr)); | 1451 | memset(&msg, 0, sizeof(struct msghdr)); |
1577 | 1452 | ||
1578 | if (count->sync_and_steering) { | 1453 | iov_p = count->iov; |
1579 | int size = 0; | 1454 | iov_len = count->iov_count; |
1580 | u32 i, orig_iov_count = 0; | ||
1581 | u32 orig_iov_len = 0, orig_iov_loc = 0; | ||
1582 | u32 iov_count = 0, per_iov_bytes = 0; | ||
1583 | u32 *tx_marker, old_tx_marker = 0; | ||
1584 | struct kvec *iov_record; | ||
1585 | |||
1586 | memset(&tx_marker_val, 0, | ||
1587 | count->ss_marker_count * sizeof(u32)); | ||
1588 | memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec)); | ||
1589 | |||
1590 | iov_record = count->iov; | ||
1591 | orig_iov_count = count->iov_count; | ||
1592 | tx_marker = &conn->if_marker; | ||
1593 | |||
1594 | i = 0; | ||
1595 | size = data; | ||
1596 | orig_iov_len = iov_record[orig_iov_loc].iov_len; | ||
1597 | while (size > 0) { | ||
1598 | pr_debug("tx_data: #1 orig_iov_len %u," | ||
1599 | " orig_iov_loc %u\n", orig_iov_len, orig_iov_loc); | ||
1600 | pr_debug("tx_data: #2 tx_marker %u, size" | ||
1601 | " %u\n", *tx_marker, size); | ||
1602 | |||
1603 | if (orig_iov_len >= *tx_marker) { | ||
1604 | iov[iov_count].iov_len = *tx_marker; | ||
1605 | iov[iov_count++].iov_base = | ||
1606 | (iov_record[orig_iov_loc].iov_base + | ||
1607 | per_iov_bytes); | ||
1608 | |||
1609 | tx_marker_val[tx_marker_iov] = | ||
1610 | (size - *tx_marker); | ||
1611 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1612 | iov[iov_count++].iov_base = | ||
1613 | &tx_marker_val[tx_marker_iov++]; | ||
1614 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1615 | iov[iov_count++].iov_base = | ||
1616 | &tx_marker_val[tx_marker_iov++]; | ||
1617 | old_tx_marker = *tx_marker; | ||
1618 | |||
1619 | /* | ||
1620 | * IFMarkInt is in 32-bit words. | ||
1621 | */ | ||
1622 | *tx_marker = (conn->conn_ops->IFMarkInt * 4); | ||
1623 | size -= old_tx_marker; | ||
1624 | orig_iov_len -= old_tx_marker; | ||
1625 | per_iov_bytes += old_tx_marker; | ||
1626 | |||
1627 | pr_debug("tx_data: #3 new_tx_marker" | ||
1628 | " %u, size %u\n", *tx_marker, size); | ||
1629 | pr_debug("tx_data: #4 offset %u\n", | ||
1630 | tx_marker_val[tx_marker_iov-1]); | ||
1631 | } else { | ||
1632 | iov[iov_count].iov_len = orig_iov_len; | ||
1633 | iov[iov_count++].iov_base | ||
1634 | = (iov_record[orig_iov_loc].iov_base + | ||
1635 | per_iov_bytes); | ||
1636 | |||
1637 | per_iov_bytes = 0; | ||
1638 | *tx_marker -= orig_iov_len; | ||
1639 | size -= orig_iov_len; | ||
1640 | |||
1641 | if (size) | ||
1642 | orig_iov_len = | ||
1643 | iov_record[++orig_iov_loc].iov_len; | ||
1644 | |||
1645 | pr_debug("tx_data: #5 new_tx_marker" | ||
1646 | " %u, size %u\n", *tx_marker, size); | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | data += (tx_marker_iov * (MARKER_SIZE / 2)); | ||
1651 | |||
1652 | iov_p = &iov[0]; | ||
1653 | iov_len = iov_count; | ||
1654 | |||
1655 | if (iov_count > count->ss_iov_count) { | ||
1656 | pr_err("iov_count: %d, count->ss_iov_count:" | ||
1657 | " %d\n", iov_count, count->ss_iov_count); | ||
1658 | return -1; | ||
1659 | } | ||
1660 | if (tx_marker_iov > count->ss_marker_count) { | ||
1661 | pr_err("tx_marker_iov: %d, count->ss_marker" | ||
1662 | "_count: %d\n", tx_marker_iov, | ||
1663 | count->ss_marker_count); | ||
1664 | return -1; | ||
1665 | } | ||
1666 | } else { | ||
1667 | iov_p = count->iov; | ||
1668 | iov_len = count->iov_count; | ||
1669 | } | ||
1670 | 1455 | ||
1671 | while (total_tx < data) { | 1456 | while (total_tx < data) { |
1672 | tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, | 1457 | tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, |
@@ -1681,9 +1466,6 @@ static int iscsit_do_tx_data( | |||
1681 | tx_loop, total_tx, data); | 1466 | tx_loop, total_tx, data); |
1682 | } | 1467 | } |
1683 | 1468 | ||
1684 | if (count->sync_and_steering) | ||
1685 | total_tx -= (tx_marker_iov * (MARKER_SIZE / 2)); | ||
1686 | |||
1687 | return total_tx; | 1469 | return total_tx; |
1688 | } | 1470 | } |
1689 | 1471 | ||
@@ -1704,12 +1486,6 @@ int rx_data( | |||
1704 | c.data_length = data; | 1486 | c.data_length = data; |
1705 | c.type = ISCSI_RX_DATA; | 1487 | c.type = ISCSI_RX_DATA; |
1706 | 1488 | ||
1707 | if (conn->conn_ops->OFMarker && | ||
1708 | (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) { | ||
1709 | if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0) | ||
1710 | return -1; | ||
1711 | } | ||
1712 | |||
1713 | return iscsit_do_rx_data(conn, &c); | 1489 | return iscsit_do_rx_data(conn, &c); |
1714 | } | 1490 | } |
1715 | 1491 | ||
@@ -1730,12 +1506,6 @@ int tx_data( | |||
1730 | c.data_length = data; | 1506 | c.data_length = data; |
1731 | c.type = ISCSI_TX_DATA; | 1507 | c.type = ISCSI_TX_DATA; |
1732 | 1508 | ||
1733 | if (conn->conn_ops->IFMarker && | ||
1734 | (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) { | ||
1735 | if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0) | ||
1736 | return -1; | ||
1737 | } | ||
1738 | |||
1739 | return iscsit_do_tx_data(conn, &c); | 1509 | return iscsit_do_tx_data(conn, &c); |
1740 | } | 1510 | } |
1741 | 1511 | ||