diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 487 |
1 files changed, 380 insertions, 107 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index f1a4246f890c..633e09036357 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kfifo.h> | 25 | #include <linux/kfifo.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/log2.h> | 27 | #include <linux/log2.h> |
28 | #include <linux/slab.h> | ||
28 | #include <asm/unaligned.h> | 29 | #include <asm/unaligned.h> |
29 | #include <net/tcp.h> | 30 | #include <net/tcp.h> |
30 | #include <scsi/scsi_cmnd.h> | 31 | #include <scsi/scsi_cmnd.h> |
@@ -266,6 +267,88 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task) | |||
266 | } | 267 | } |
267 | 268 | ||
268 | /** | 269 | /** |
270 | * iscsi_check_tmf_restrictions - check if a task is affected by TMF | ||
271 | * @task: iscsi task | ||
272 | * @opcode: opcode to check for | ||
273 | * | ||
274 | * During TMF a task has to be checked if it's affected. | ||
275 | * All unrelated I/O can be passed through, but I/O to the | ||
276 | * affected LUN should be restricted. | ||
277 | * If 'fast_abort' is set we won't be sending any I/O to the | ||
278 | * affected LUN. | ||
279 | * Otherwise the target is waiting for all TTTs to be completed, | ||
280 | * so we have to send all outstanding Data-Out PDUs to the target. | ||
281 | */ | ||
282 | static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) | ||
283 | { | ||
284 | struct iscsi_conn *conn = task->conn; | ||
285 | struct iscsi_tm *tmf = &conn->tmhdr; | ||
286 | unsigned int hdr_lun; | ||
287 | |||
288 | if (conn->tmf_state == TMF_INITIAL) | ||
289 | return 0; | ||
290 | |||
291 | if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC) | ||
292 | return 0; | ||
293 | |||
294 | switch (ISCSI_TM_FUNC_VALUE(tmf)) { | ||
295 | case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: | ||
296 | /* | ||
297 | * Allow PDUs for unrelated LUNs | ||
298 | */ | ||
299 | hdr_lun = scsilun_to_int((struct scsi_lun *)tmf->lun); | ||
300 | if (hdr_lun != task->sc->device->lun) | ||
301 | return 0; | ||
302 | /* fall through */ | ||
303 | case ISCSI_TM_FUNC_TARGET_WARM_RESET: | ||
304 | /* | ||
305 | * Fail all SCSI cmd PDUs | ||
306 | */ | ||
307 | if (opcode != ISCSI_OP_SCSI_DATA_OUT) { | ||
308 | iscsi_conn_printk(KERN_INFO, conn, | ||
309 | "task [op %x/%x itt " | ||
310 | "0x%x/0x%x] " | ||
311 | "rejected.\n", | ||
312 | task->hdr->opcode, opcode, | ||
313 | task->itt, task->hdr_itt); | ||
314 | return -EACCES; | ||
315 | } | ||
316 | /* | ||
317 | * And also all data-out PDUs in response to R2T | ||
318 | * if fast_abort is set. | ||
319 | */ | ||
320 | if (conn->session->fast_abort) { | ||
321 | iscsi_conn_printk(KERN_INFO, conn, | ||
322 | "task [op %x/%x itt " | ||
323 | "0x%x/0x%x] fast abort.\n", | ||
324 | task->hdr->opcode, opcode, | ||
325 | task->itt, task->hdr_itt); | ||
326 | return -EACCES; | ||
327 | } | ||
328 | break; | ||
329 | case ISCSI_TM_FUNC_ABORT_TASK: | ||
330 | /* | ||
331 | * the caller has already checked if the task | ||
332 | * they want to abort was in the pending queue so if | ||
333 | * we are here the cmd pdu has gone out already, and | ||
334 | * we will only hit this for data-outs | ||
335 | */ | ||
336 | if (opcode == ISCSI_OP_SCSI_DATA_OUT && | ||
337 | task->hdr_itt == tmf->rtt) { | ||
338 | ISCSI_DBG_SESSION(conn->session, | ||
339 | "Preventing task %x/%x from sending " | ||
340 | "data-out due to abort task in " | ||
341 | "progress\n", task->itt, | ||
342 | task->hdr_itt); | ||
343 | return -EACCES; | ||
344 | } | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | /** | ||
269 | * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu | 352 | * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu |
270 | * @task: iscsi task | 353 | * @task: iscsi task |
271 | * | 354 | * |
@@ -282,6 +365,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
282 | itt_t itt; | 365 | itt_t itt; |
283 | int rc; | 366 | int rc; |
284 | 367 | ||
368 | rc = iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_CMD); | ||
369 | if (rc) | ||
370 | return rc; | ||
371 | |||
285 | if (conn->session->tt->alloc_pdu) { | 372 | if (conn->session->tt->alloc_pdu) { |
286 | rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); | 373 | rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); |
287 | if (rc) | 374 | if (rc) |
@@ -384,12 +471,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
384 | 471 | ||
385 | WARN_ON(hdrlength >= 256); | 472 | WARN_ON(hdrlength >= 256); |
386 | hdr->hlength = hdrlength & 0xFF; | 473 | hdr->hlength = hdrlength & 0xFF; |
474 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | ||
387 | 475 | ||
388 | if (session->tt->init_task && session->tt->init_task(task)) | 476 | if (session->tt->init_task && session->tt->init_task(task)) |
389 | return -EIO; | 477 | return -EIO; |
390 | 478 | ||
391 | task->state = ISCSI_TASK_RUNNING; | 479 | task->state = ISCSI_TASK_RUNNING; |
392 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | ||
393 | session->cmdsn++; | 480 | session->cmdsn++; |
394 | 481 | ||
395 | conn->scsicmd_pdus_cnt++; | 482 | conn->scsicmd_pdus_cnt++; |
@@ -431,7 +518,7 @@ static void iscsi_free_task(struct iscsi_task *task) | |||
431 | if (conn->login_task == task) | 518 | if (conn->login_task == task) |
432 | return; | 519 | return; |
433 | 520 | ||
434 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); | 521 | kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*)); |
435 | 522 | ||
436 | if (sc) { | 523 | if (sc) { |
437 | task->sc = NULL; | 524 | task->sc = NULL; |
@@ -577,12 +664,12 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
577 | struct iscsi_session *session = conn->session; | 664 | struct iscsi_session *session = conn->session; |
578 | struct iscsi_hdr *hdr = task->hdr; | 665 | struct iscsi_hdr *hdr = task->hdr; |
579 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; | 666 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; |
667 | uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK; | ||
580 | 668 | ||
581 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) | 669 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) |
582 | return -ENOTCONN; | 670 | return -ENOTCONN; |
583 | 671 | ||
584 | if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) && | 672 | if (opcode != ISCSI_OP_LOGIN && opcode != ISCSI_OP_TEXT) |
585 | hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) | ||
586 | nop->exp_statsn = cpu_to_be32(conn->exp_statsn); | 673 | nop->exp_statsn = cpu_to_be32(conn->exp_statsn); |
587 | /* | 674 | /* |
588 | * pre-format CmdSN for outgoing PDU. | 675 | * pre-format CmdSN for outgoing PDU. |
@@ -590,9 +677,12 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
590 | nop->cmdsn = cpu_to_be32(session->cmdsn); | 677 | nop->cmdsn = cpu_to_be32(session->cmdsn); |
591 | if (hdr->itt != RESERVED_ITT) { | 678 | if (hdr->itt != RESERVED_ITT) { |
592 | /* | 679 | /* |
593 | * TODO: We always use immediate, so we never hit this. | 680 | * TODO: We always use immediate for normal session pdus. |
594 | * If we start to send tmfs or nops as non-immediate then | 681 | * If we start to send tmfs or nops as non-immediate then |
595 | * we should start checking the cmdsn numbers for mgmt tasks. | 682 | * we should start checking the cmdsn numbers for mgmt tasks. |
683 | * | ||
684 | * During discovery sessions iscsid sends TEXT as non immediate, | ||
685 | * but we always only send one PDU at a time. | ||
596 | */ | 686 | */ |
597 | if (conn->c_stage == ISCSI_CONN_STARTED && | 687 | if (conn->c_stage == ISCSI_CONN_STARTED && |
598 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | 688 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { |
@@ -620,29 +710,35 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
620 | { | 710 | { |
621 | struct iscsi_session *session = conn->session; | 711 | struct iscsi_session *session = conn->session; |
622 | struct iscsi_host *ihost = shost_priv(session->host); | 712 | struct iscsi_host *ihost = shost_priv(session->host); |
713 | uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK; | ||
623 | struct iscsi_task *task; | 714 | struct iscsi_task *task; |
624 | itt_t itt; | 715 | itt_t itt; |
625 | 716 | ||
626 | if (session->state == ISCSI_STATE_TERMINATE) | 717 | if (session->state == ISCSI_STATE_TERMINATE) |
627 | return NULL; | 718 | return NULL; |
628 | 719 | ||
629 | if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || | 720 | if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) { |
630 | hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) | ||
631 | /* | 721 | /* |
632 | * Login and Text are sent serially, in | 722 | * Login and Text are sent serially, in |
633 | * request-followed-by-response sequence. | 723 | * request-followed-by-response sequence. |
634 | * Same task can be used. Same ITT must be used. | 724 | * Same task can be used. Same ITT must be used. |
635 | * Note that login_task is preallocated at conn_create(). | 725 | * Note that login_task is preallocated at conn_create(). |
636 | */ | 726 | */ |
727 | if (conn->login_task->state != ISCSI_TASK_FREE) { | ||
728 | iscsi_conn_printk(KERN_ERR, conn, "Login/Text in " | ||
729 | "progress. Cannot start new task.\n"); | ||
730 | return NULL; | ||
731 | } | ||
732 | |||
637 | task = conn->login_task; | 733 | task = conn->login_task; |
638 | else { | 734 | } else { |
639 | if (session->state != ISCSI_STATE_LOGGED_IN) | 735 | if (session->state != ISCSI_STATE_LOGGED_IN) |
640 | return NULL; | 736 | return NULL; |
641 | 737 | ||
642 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); | 738 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); |
643 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); | 739 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); |
644 | 740 | ||
645 | if (!__kfifo_get(session->cmdpool.queue, | 741 | if (!kfifo_out(&session->cmdpool.queue, |
646 | (void*)&task, sizeof(void*))) | 742 | (void*)&task, sizeof(void*))) |
647 | return NULL; | 743 | return NULL; |
648 | } | 744 | } |
@@ -1357,6 +1453,7 @@ EXPORT_SYMBOL_GPL(iscsi_requeue_task); | |||
1357 | **/ | 1453 | **/ |
1358 | static int iscsi_data_xmit(struct iscsi_conn *conn) | 1454 | static int iscsi_data_xmit(struct iscsi_conn *conn) |
1359 | { | 1455 | { |
1456 | struct iscsi_task *task; | ||
1360 | int rc = 0; | 1457 | int rc = 0; |
1361 | 1458 | ||
1362 | spin_lock_bh(&conn->session->lock); | 1459 | spin_lock_bh(&conn->session->lock); |
@@ -1394,11 +1491,8 @@ check_mgmt: | |||
1394 | 1491 | ||
1395 | /* process pending command queue */ | 1492 | /* process pending command queue */ |
1396 | while (!list_empty(&conn->cmdqueue)) { | 1493 | while (!list_empty(&conn->cmdqueue)) { |
1397 | if (conn->tmf_state == TMF_QUEUED) | 1494 | conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task, |
1398 | break; | 1495 | running); |
1399 | |||
1400 | conn->task = list_entry(conn->cmdqueue.next, | ||
1401 | struct iscsi_task, running); | ||
1402 | list_del_init(&conn->task->running); | 1496 | list_del_init(&conn->task->running); |
1403 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1497 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { |
1404 | fail_scsi_task(conn->task, DID_IMM_RETRY); | 1498 | fail_scsi_task(conn->task, DID_IMM_RETRY); |
@@ -1406,7 +1500,7 @@ check_mgmt: | |||
1406 | } | 1500 | } |
1407 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); | 1501 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); |
1408 | if (rc) { | 1502 | if (rc) { |
1409 | if (rc == -ENOMEM) { | 1503 | if (rc == -ENOMEM || rc == -EACCES) { |
1410 | list_add_tail(&conn->task->running, | 1504 | list_add_tail(&conn->task->running, |
1411 | &conn->cmdqueue); | 1505 | &conn->cmdqueue); |
1412 | conn->task = NULL; | 1506 | conn->task = NULL; |
@@ -1428,17 +1522,18 @@ check_mgmt: | |||
1428 | } | 1522 | } |
1429 | 1523 | ||
1430 | while (!list_empty(&conn->requeue)) { | 1524 | while (!list_empty(&conn->requeue)) { |
1431 | if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL) | ||
1432 | break; | ||
1433 | |||
1434 | /* | 1525 | /* |
1435 | * we always do fastlogout - conn stop code will clean up. | 1526 | * we always do fastlogout - conn stop code will clean up. |
1436 | */ | 1527 | */ |
1437 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) | 1528 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) |
1438 | break; | 1529 | break; |
1439 | 1530 | ||
1440 | conn->task = list_entry(conn->requeue.next, | 1531 | task = list_entry(conn->requeue.next, struct iscsi_task, |
1441 | struct iscsi_task, running); | 1532 | running); |
1533 | if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT)) | ||
1534 | break; | ||
1535 | |||
1536 | conn->task = task; | ||
1442 | list_del_init(&conn->task->running); | 1537 | list_del_init(&conn->task->running); |
1443 | conn->task->state = ISCSI_TASK_RUNNING; | 1538 | conn->task->state = ISCSI_TASK_RUNNING; |
1444 | rc = iscsi_xmit_task(conn); | 1539 | rc = iscsi_xmit_task(conn); |
@@ -1473,7 +1568,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, | |||
1473 | { | 1568 | { |
1474 | struct iscsi_task *task; | 1569 | struct iscsi_task *task; |
1475 | 1570 | ||
1476 | if (!__kfifo_get(conn->session->cmdpool.queue, | 1571 | if (!kfifo_out(&conn->session->cmdpool.queue, |
1477 | (void *) &task, sizeof(void *))) | 1572 | (void *) &task, sizeof(void *))) |
1478 | return NULL; | 1573 | return NULL; |
1479 | 1574 | ||
@@ -1591,7 +1686,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1591 | if (!ihost->workq) { | 1686 | if (!ihost->workq) { |
1592 | reason = iscsi_prep_scsi_cmd_pdu(task); | 1687 | reason = iscsi_prep_scsi_cmd_pdu(task); |
1593 | if (reason) { | 1688 | if (reason) { |
1594 | if (reason == -ENOMEM) { | 1689 | if (reason == -ENOMEM || reason == -EACCES) { |
1595 | reason = FAILURE_OOM; | 1690 | reason = FAILURE_OOM; |
1596 | goto prepd_reject; | 1691 | goto prepd_reject; |
1597 | } else { | 1692 | } else { |
@@ -1643,9 +1738,21 @@ fault: | |||
1643 | } | 1738 | } |
1644 | EXPORT_SYMBOL_GPL(iscsi_queuecommand); | 1739 | EXPORT_SYMBOL_GPL(iscsi_queuecommand); |
1645 | 1740 | ||
1646 | int iscsi_change_queue_depth(struct scsi_device *sdev, int depth) | 1741 | int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) |
1647 | { | 1742 | { |
1648 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); | 1743 | switch (reason) { |
1744 | case SCSI_QDEPTH_DEFAULT: | ||
1745 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); | ||
1746 | break; | ||
1747 | case SCSI_QDEPTH_QFULL: | ||
1748 | scsi_track_queue_full(sdev, depth); | ||
1749 | break; | ||
1750 | case SCSI_QDEPTH_RAMP_UP: | ||
1751 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); | ||
1752 | break; | ||
1753 | default: | ||
1754 | return -EOPNOTSUPP; | ||
1755 | } | ||
1649 | return sdev->queue_depth; | 1756 | return sdev->queue_depth; |
1650 | } | 1757 | } |
1651 | EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); | 1758 | EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); |
@@ -1660,72 +1767,6 @@ int iscsi_target_alloc(struct scsi_target *starget) | |||
1660 | } | 1767 | } |
1661 | EXPORT_SYMBOL_GPL(iscsi_target_alloc); | 1768 | EXPORT_SYMBOL_GPL(iscsi_target_alloc); |
1662 | 1769 | ||
1663 | void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) | ||
1664 | { | ||
1665 | struct iscsi_session *session = cls_session->dd_data; | ||
1666 | |||
1667 | spin_lock_bh(&session->lock); | ||
1668 | if (session->state != ISCSI_STATE_LOGGED_IN) { | ||
1669 | session->state = ISCSI_STATE_RECOVERY_FAILED; | ||
1670 | if (session->leadconn) | ||
1671 | wake_up(&session->leadconn->ehwait); | ||
1672 | } | ||
1673 | spin_unlock_bh(&session->lock); | ||
1674 | } | ||
1675 | EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); | ||
1676 | |||
1677 | int iscsi_eh_target_reset(struct scsi_cmnd *sc) | ||
1678 | { | ||
1679 | struct iscsi_cls_session *cls_session; | ||
1680 | struct iscsi_session *session; | ||
1681 | struct iscsi_conn *conn; | ||
1682 | |||
1683 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
1684 | session = cls_session->dd_data; | ||
1685 | conn = session->leadconn; | ||
1686 | |||
1687 | mutex_lock(&session->eh_mutex); | ||
1688 | spin_lock_bh(&session->lock); | ||
1689 | if (session->state == ISCSI_STATE_TERMINATE) { | ||
1690 | failed: | ||
1691 | ISCSI_DBG_EH(session, | ||
1692 | "failing target reset: Could not log back into " | ||
1693 | "target [age %d]\n", | ||
1694 | session->age); | ||
1695 | spin_unlock_bh(&session->lock); | ||
1696 | mutex_unlock(&session->eh_mutex); | ||
1697 | return FAILED; | ||
1698 | } | ||
1699 | |||
1700 | spin_unlock_bh(&session->lock); | ||
1701 | mutex_unlock(&session->eh_mutex); | ||
1702 | /* | ||
1703 | * we drop the lock here but the leadconn cannot be destoyed while | ||
1704 | * we are in the scsi eh | ||
1705 | */ | ||
1706 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
1707 | |||
1708 | ISCSI_DBG_EH(session, "wait for relogin\n"); | ||
1709 | wait_event_interruptible(conn->ehwait, | ||
1710 | session->state == ISCSI_STATE_TERMINATE || | ||
1711 | session->state == ISCSI_STATE_LOGGED_IN || | ||
1712 | session->state == ISCSI_STATE_RECOVERY_FAILED); | ||
1713 | if (signal_pending(current)) | ||
1714 | flush_signals(current); | ||
1715 | |||
1716 | mutex_lock(&session->eh_mutex); | ||
1717 | spin_lock_bh(&session->lock); | ||
1718 | if (session->state == ISCSI_STATE_LOGGED_IN) { | ||
1719 | ISCSI_DBG_EH(session, | ||
1720 | "target reset succeeded\n"); | ||
1721 | } else | ||
1722 | goto failed; | ||
1723 | spin_unlock_bh(&session->lock); | ||
1724 | mutex_unlock(&session->eh_mutex); | ||
1725 | return SUCCESS; | ||
1726 | } | ||
1727 | EXPORT_SYMBOL_GPL(iscsi_eh_target_reset); | ||
1728 | |||
1729 | static void iscsi_tmf_timedout(unsigned long data) | 1770 | static void iscsi_tmf_timedout(unsigned long data) |
1730 | { | 1771 | { |
1731 | struct iscsi_conn *conn = (struct iscsi_conn *)data; | 1772 | struct iscsi_conn *conn = (struct iscsi_conn *)data; |
@@ -1879,10 +1920,11 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) | |||
1879 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | 1920 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) |
1880 | { | 1921 | { |
1881 | enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; | 1922 | enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; |
1882 | struct iscsi_task *task = NULL; | 1923 | struct iscsi_task *task = NULL, *running_task; |
1883 | struct iscsi_cls_session *cls_session; | 1924 | struct iscsi_cls_session *cls_session; |
1884 | struct iscsi_session *session; | 1925 | struct iscsi_session *session; |
1885 | struct iscsi_conn *conn; | 1926 | struct iscsi_conn *conn; |
1927 | int i; | ||
1886 | 1928 | ||
1887 | cls_session = starget_to_session(scsi_target(sc->device)); | 1929 | cls_session = starget_to_session(scsi_target(sc->device)); |
1888 | session = cls_session->dd_data; | 1930 | session = cls_session->dd_data; |
@@ -1907,8 +1949,15 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | |||
1907 | } | 1949 | } |
1908 | 1950 | ||
1909 | task = (struct iscsi_task *)sc->SCp.ptr; | 1951 | task = (struct iscsi_task *)sc->SCp.ptr; |
1910 | if (!task) | 1952 | if (!task) { |
1953 | /* | ||
1954 | * Raced with completion. Just reset timer, and let it | ||
1955 | * complete normally | ||
1956 | */ | ||
1957 | rc = BLK_EH_RESET_TIMER; | ||
1911 | goto done; | 1958 | goto done; |
1959 | } | ||
1960 | |||
1912 | /* | 1961 | /* |
1913 | * If we have sent (at least queued to the network layer) a pdu or | 1962 | * If we have sent (at least queued to the network layer) a pdu or |
1914 | * recvd one for the task since the last timeout ask for | 1963 | * recvd one for the task since the last timeout ask for |
@@ -1916,10 +1965,10 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | |||
1916 | * we can check if it is the task or connection when we send the | 1965 | * we can check if it is the task or connection when we send the |
1917 | * nop as a ping. | 1966 | * nop as a ping. |
1918 | */ | 1967 | */ |
1919 | if (time_after_eq(task->last_xfer, task->last_timeout)) { | 1968 | if (time_after(task->last_xfer, task->last_timeout)) { |
1920 | ISCSI_DBG_EH(session, "Command making progress. Asking " | 1969 | ISCSI_DBG_EH(session, "Command making progress. Asking " |
1921 | "scsi-ml for more time to complete. " | 1970 | "scsi-ml for more time to complete. " |
1922 | "Last data recv at %lu. Last timeout was at " | 1971 | "Last data xfer at %lu. Last timeout was at " |
1923 | "%lu\n.", task->last_xfer, task->last_timeout); | 1972 | "%lu\n.", task->last_xfer, task->last_timeout); |
1924 | task->have_checked_conn = false; | 1973 | task->have_checked_conn = false; |
1925 | rc = BLK_EH_RESET_TIMER; | 1974 | rc = BLK_EH_RESET_TIMER; |
@@ -1937,6 +1986,43 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | |||
1937 | goto done; | 1986 | goto done; |
1938 | } | 1987 | } |
1939 | 1988 | ||
1989 | for (i = 0; i < conn->session->cmds_max; i++) { | ||
1990 | running_task = conn->session->cmds[i]; | ||
1991 | if (!running_task->sc || running_task == task || | ||
1992 | running_task->state != ISCSI_TASK_RUNNING) | ||
1993 | continue; | ||
1994 | |||
1995 | /* | ||
1996 | * Only check if cmds started before this one have made | ||
1997 | * progress, or this could never fail | ||
1998 | */ | ||
1999 | if (time_after(running_task->sc->jiffies_at_alloc, | ||
2000 | task->sc->jiffies_at_alloc)) | ||
2001 | continue; | ||
2002 | |||
2003 | if (time_after(running_task->last_xfer, task->last_timeout)) { | ||
2004 | /* | ||
2005 | * This task has not made progress, but a task | ||
2006 | * started before us has transferred data since | ||
2007 | * we started/last-checked. We could be queueing | ||
2008 | * too many tasks or the LU is bad. | ||
2009 | * | ||
2010 | * If the device is bad the cmds ahead of us on | ||
2011 | * other devs will complete, and this loop will | ||
2012 | * eventually fail starting the scsi eh. | ||
2013 | */ | ||
2014 | ISCSI_DBG_EH(session, "Command has not made progress " | ||
2015 | "but commands ahead of it have. " | ||
2016 | "Asking scsi-ml for more time to " | ||
2017 | "complete. Our last xfer vs running task " | ||
2018 | "last xfer %lu/%lu. Last check %lu.\n", | ||
2019 | task->last_xfer, running_task->last_xfer, | ||
2020 | task->last_timeout); | ||
2021 | rc = BLK_EH_RESET_TIMER; | ||
2022 | goto done; | ||
2023 | } | ||
2024 | } | ||
2025 | |||
1940 | /* Assumes nop timeout is shorter than scsi cmd timeout */ | 2026 | /* Assumes nop timeout is shorter than scsi cmd timeout */ |
1941 | if (task->have_checked_conn) | 2027 | if (task->have_checked_conn) |
1942 | goto done; | 2028 | goto done; |
@@ -2108,6 +2194,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
2108 | spin_lock_bh(&session->lock); | 2194 | spin_lock_bh(&session->lock); |
2109 | fail_scsi_task(task, DID_ABORT); | 2195 | fail_scsi_task(task, DID_ABORT); |
2110 | conn->tmf_state = TMF_INITIAL; | 2196 | conn->tmf_state = TMF_INITIAL; |
2197 | memset(hdr, 0, sizeof(*hdr)); | ||
2111 | spin_unlock_bh(&session->lock); | 2198 | spin_unlock_bh(&session->lock); |
2112 | iscsi_start_tx(conn); | 2199 | iscsi_start_tx(conn); |
2113 | goto success_unlocked; | 2200 | goto success_unlocked; |
@@ -2118,6 +2205,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
2118 | case TMF_NOT_FOUND: | 2205 | case TMF_NOT_FOUND: |
2119 | if (!sc->SCp.ptr) { | 2206 | if (!sc->SCp.ptr) { |
2120 | conn->tmf_state = TMF_INITIAL; | 2207 | conn->tmf_state = TMF_INITIAL; |
2208 | memset(hdr, 0, sizeof(*hdr)); | ||
2121 | /* task completed before tmf abort response */ | 2209 | /* task completed before tmf abort response */ |
2122 | ISCSI_DBG_EH(session, "sc completed while abort in " | 2210 | ISCSI_DBG_EH(session, "sc completed while abort in " |
2123 | "progress\n"); | 2211 | "progress\n"); |
@@ -2212,6 +2300,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
2212 | iscsi_suspend_tx(conn); | 2300 | iscsi_suspend_tx(conn); |
2213 | 2301 | ||
2214 | spin_lock_bh(&session->lock); | 2302 | spin_lock_bh(&session->lock); |
2303 | memset(hdr, 0, sizeof(*hdr)); | ||
2215 | fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); | 2304 | fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); |
2216 | conn->tmf_state = TMF_INITIAL; | 2305 | conn->tmf_state = TMF_INITIAL; |
2217 | spin_unlock_bh(&session->lock); | 2306 | spin_unlock_bh(&session->lock); |
@@ -2229,6 +2318,187 @@ done: | |||
2229 | } | 2318 | } |
2230 | EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); | 2319 | EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); |
2231 | 2320 | ||
2321 | void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) | ||
2322 | { | ||
2323 | struct iscsi_session *session = cls_session->dd_data; | ||
2324 | |||
2325 | spin_lock_bh(&session->lock); | ||
2326 | if (session->state != ISCSI_STATE_LOGGED_IN) { | ||
2327 | session->state = ISCSI_STATE_RECOVERY_FAILED; | ||
2328 | if (session->leadconn) | ||
2329 | wake_up(&session->leadconn->ehwait); | ||
2330 | } | ||
2331 | spin_unlock_bh(&session->lock); | ||
2332 | } | ||
2333 | EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); | ||
2334 | |||
2335 | /** | ||
2336 | * iscsi_eh_session_reset - drop session and attempt relogin | ||
2337 | * @sc: scsi command | ||
2338 | * | ||
2339 | * This function will wait for a relogin, session termination from | ||
2340 | * userspace, or a recovery/replacement timeout. | ||
2341 | */ | ||
2342 | int iscsi_eh_session_reset(struct scsi_cmnd *sc) | ||
2343 | { | ||
2344 | struct iscsi_cls_session *cls_session; | ||
2345 | struct iscsi_session *session; | ||
2346 | struct iscsi_conn *conn; | ||
2347 | |||
2348 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
2349 | session = cls_session->dd_data; | ||
2350 | conn = session->leadconn; | ||
2351 | |||
2352 | mutex_lock(&session->eh_mutex); | ||
2353 | spin_lock_bh(&session->lock); | ||
2354 | if (session->state == ISCSI_STATE_TERMINATE) { | ||
2355 | failed: | ||
2356 | ISCSI_DBG_EH(session, | ||
2357 | "failing session reset: Could not log back into " | ||
2358 | "%s, %s [age %d]\n", session->targetname, | ||
2359 | conn->persistent_address, session->age); | ||
2360 | spin_unlock_bh(&session->lock); | ||
2361 | mutex_unlock(&session->eh_mutex); | ||
2362 | return FAILED; | ||
2363 | } | ||
2364 | |||
2365 | spin_unlock_bh(&session->lock); | ||
2366 | mutex_unlock(&session->eh_mutex); | ||
2367 | /* | ||
2368 | * we drop the lock here but the leadconn cannot be destoyed while | ||
2369 | * we are in the scsi eh | ||
2370 | */ | ||
2371 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
2372 | |||
2373 | ISCSI_DBG_EH(session, "wait for relogin\n"); | ||
2374 | wait_event_interruptible(conn->ehwait, | ||
2375 | session->state == ISCSI_STATE_TERMINATE || | ||
2376 | session->state == ISCSI_STATE_LOGGED_IN || | ||
2377 | session->state == ISCSI_STATE_RECOVERY_FAILED); | ||
2378 | if (signal_pending(current)) | ||
2379 | flush_signals(current); | ||
2380 | |||
2381 | mutex_lock(&session->eh_mutex); | ||
2382 | spin_lock_bh(&session->lock); | ||
2383 | if (session->state == ISCSI_STATE_LOGGED_IN) { | ||
2384 | ISCSI_DBG_EH(session, | ||
2385 | "session reset succeeded for %s,%s\n", | ||
2386 | session->targetname, conn->persistent_address); | ||
2387 | } else | ||
2388 | goto failed; | ||
2389 | spin_unlock_bh(&session->lock); | ||
2390 | mutex_unlock(&session->eh_mutex); | ||
2391 | return SUCCESS; | ||
2392 | } | ||
2393 | EXPORT_SYMBOL_GPL(iscsi_eh_session_reset); | ||
2394 | |||
2395 | static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) | ||
2396 | { | ||
2397 | memset(hdr, 0, sizeof(*hdr)); | ||
2398 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; | ||
2399 | hdr->flags = ISCSI_TM_FUNC_TARGET_WARM_RESET & ISCSI_FLAG_TM_FUNC_MASK; | ||
2400 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
2401 | hdr->rtt = RESERVED_ITT; | ||
2402 | } | ||
2403 | |||
2404 | /** | ||
2405 | * iscsi_eh_target_reset - reset target | ||
2406 | * @sc: scsi command | ||
2407 | * | ||
2408 | * This will attempt to send a warm target reset. | ||
2409 | */ | ||
2410 | int iscsi_eh_target_reset(struct scsi_cmnd *sc) | ||
2411 | { | ||
2412 | struct iscsi_cls_session *cls_session; | ||
2413 | struct iscsi_session *session; | ||
2414 | struct iscsi_conn *conn; | ||
2415 | struct iscsi_tm *hdr; | ||
2416 | int rc = FAILED; | ||
2417 | |||
2418 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
2419 | session = cls_session->dd_data; | ||
2420 | |||
2421 | ISCSI_DBG_EH(session, "tgt Reset [sc %p tgt %s]\n", sc, | ||
2422 | session->targetname); | ||
2423 | |||
2424 | mutex_lock(&session->eh_mutex); | ||
2425 | spin_lock_bh(&session->lock); | ||
2426 | /* | ||
2427 | * Just check if we are not logged in. We cannot check for | ||
2428 | * the phase because the reset could come from a ioctl. | ||
2429 | */ | ||
2430 | if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) | ||
2431 | goto unlock; | ||
2432 | conn = session->leadconn; | ||
2433 | |||
2434 | /* only have one tmf outstanding at a time */ | ||
2435 | if (conn->tmf_state != TMF_INITIAL) | ||
2436 | goto unlock; | ||
2437 | conn->tmf_state = TMF_QUEUED; | ||
2438 | |||
2439 | hdr = &conn->tmhdr; | ||
2440 | iscsi_prep_tgt_reset_pdu(sc, hdr); | ||
2441 | |||
2442 | if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, | ||
2443 | session->tgt_reset_timeout)) { | ||
2444 | rc = FAILED; | ||
2445 | goto unlock; | ||
2446 | } | ||
2447 | |||
2448 | switch (conn->tmf_state) { | ||
2449 | case TMF_SUCCESS: | ||
2450 | break; | ||
2451 | case TMF_TIMEDOUT: | ||
2452 | spin_unlock_bh(&session->lock); | ||
2453 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
2454 | goto done; | ||
2455 | default: | ||
2456 | conn->tmf_state = TMF_INITIAL; | ||
2457 | goto unlock; | ||
2458 | } | ||
2459 | |||
2460 | rc = SUCCESS; | ||
2461 | spin_unlock_bh(&session->lock); | ||
2462 | |||
2463 | iscsi_suspend_tx(conn); | ||
2464 | |||
2465 | spin_lock_bh(&session->lock); | ||
2466 | memset(hdr, 0, sizeof(*hdr)); | ||
2467 | fail_scsi_tasks(conn, -1, DID_ERROR); | ||
2468 | conn->tmf_state = TMF_INITIAL; | ||
2469 | spin_unlock_bh(&session->lock); | ||
2470 | |||
2471 | iscsi_start_tx(conn); | ||
2472 | goto done; | ||
2473 | |||
2474 | unlock: | ||
2475 | spin_unlock_bh(&session->lock); | ||
2476 | done: | ||
2477 | ISCSI_DBG_EH(session, "tgt %s reset result = %s\n", session->targetname, | ||
2478 | rc == SUCCESS ? "SUCCESS" : "FAILED"); | ||
2479 | mutex_unlock(&session->eh_mutex); | ||
2480 | return rc; | ||
2481 | } | ||
2482 | EXPORT_SYMBOL_GPL(iscsi_eh_target_reset); | ||
2483 | |||
2484 | /** | ||
2485 | * iscsi_eh_recover_target - reset target and possibly the session | ||
2486 | * @sc: scsi command | ||
2487 | * | ||
2488 | * This will attempt to send a warm target reset. If that fails, | ||
2489 | * we will escalate to ERL0 session recovery. | ||
2490 | */ | ||
2491 | int iscsi_eh_recover_target(struct scsi_cmnd *sc) | ||
2492 | { | ||
2493 | int rc; | ||
2494 | |||
2495 | rc = iscsi_eh_target_reset(sc); | ||
2496 | if (rc == FAILED) | ||
2497 | rc = iscsi_eh_session_reset(sc); | ||
2498 | return rc; | ||
2499 | } | ||
2500 | EXPORT_SYMBOL_GPL(iscsi_eh_recover_target); | ||
2501 | |||
2232 | /* | 2502 | /* |
2233 | * Pre-allocate a pool of @max items of @item_size. By default, the pool | 2503 | * Pre-allocate a pool of @max items of @item_size. By default, the pool |
2234 | * should be accessed via kfifo_{get,put} on q->queue. | 2504 | * should be accessed via kfifo_{get,put} on q->queue. |
@@ -2252,12 +2522,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) | |||
2252 | if (q->pool == NULL) | 2522 | if (q->pool == NULL) |
2253 | return -ENOMEM; | 2523 | return -ENOMEM; |
2254 | 2524 | ||
2255 | q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), | 2525 | kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*)); |
2256 | GFP_KERNEL, NULL); | ||
2257 | if (IS_ERR(q->queue)) { | ||
2258 | q->queue = NULL; | ||
2259 | goto enomem; | ||
2260 | } | ||
2261 | 2526 | ||
2262 | for (i = 0; i < max; i++) { | 2527 | for (i = 0; i < max; i++) { |
2263 | q->pool[i] = kzalloc(item_size, GFP_KERNEL); | 2528 | q->pool[i] = kzalloc(item_size, GFP_KERNEL); |
@@ -2265,7 +2530,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) | |||
2265 | q->max = i; | 2530 | q->max = i; |
2266 | goto enomem; | 2531 | goto enomem; |
2267 | } | 2532 | } |
2268 | __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); | 2533 | kfifo_in(&q->queue, (void*)&q->pool[i], sizeof(void*)); |
2269 | } | 2534 | } |
2270 | 2535 | ||
2271 | if (items) { | 2536 | if (items) { |
@@ -2288,7 +2553,6 @@ void iscsi_pool_free(struct iscsi_pool *q) | |||
2288 | for (i = 0; i < q->max; i++) | 2553 | for (i = 0; i < q->max; i++) |
2289 | kfree(q->pool[i]); | 2554 | kfree(q->pool[i]); |
2290 | kfree(q->pool); | 2555 | kfree(q->pool); |
2291 | kfree(q->queue); | ||
2292 | } | 2556 | } |
2293 | EXPORT_SYMBOL_GPL(iscsi_pool_free); | 2557 | EXPORT_SYMBOL_GPL(iscsi_pool_free); |
2294 | 2558 | ||
@@ -2495,6 +2759,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
2495 | session->host = shost; | 2759 | session->host = shost; |
2496 | session->state = ISCSI_STATE_FREE; | 2760 | session->state = ISCSI_STATE_FREE; |
2497 | session->fast_abort = 1; | 2761 | session->fast_abort = 1; |
2762 | session->tgt_reset_timeout = 30; | ||
2498 | session->lu_reset_timeout = 15; | 2763 | session->lu_reset_timeout = 15; |
2499 | session->abort_timeout = 10; | 2764 | session->abort_timeout = 10; |
2500 | session->scsi_cmds_max = scsi_cmds; | 2765 | session->scsi_cmds_max = scsi_cmds; |
@@ -2615,7 +2880,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2615 | 2880 | ||
2616 | /* allocate login_task used for the login/text sequences */ | 2881 | /* allocate login_task used for the login/text sequences */ |
2617 | spin_lock_bh(&session->lock); | 2882 | spin_lock_bh(&session->lock); |
2618 | if (!__kfifo_get(session->cmdpool.queue, | 2883 | if (!kfifo_out(&session->cmdpool.queue, |
2619 | (void*)&conn->login_task, | 2884 | (void*)&conn->login_task, |
2620 | sizeof(void*))) { | 2885 | sizeof(void*))) { |
2621 | spin_unlock_bh(&session->lock); | 2886 | spin_unlock_bh(&session->lock); |
@@ -2635,7 +2900,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2635 | return cls_conn; | 2900 | return cls_conn; |
2636 | 2901 | ||
2637 | login_task_data_alloc_fail: | 2902 | login_task_data_alloc_fail: |
2638 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, | 2903 | kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, |
2639 | sizeof(void*)); | 2904 | sizeof(void*)); |
2640 | login_task_alloc_fail: | 2905 | login_task_alloc_fail: |
2641 | iscsi_destroy_conn(cls_conn); | 2906 | iscsi_destroy_conn(cls_conn); |
@@ -2698,7 +2963,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
2698 | free_pages((unsigned long) conn->data, | 2963 | free_pages((unsigned long) conn->data, |
2699 | get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); | 2964 | get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); |
2700 | kfree(conn->persistent_address); | 2965 | kfree(conn->persistent_address); |
2701 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, | 2966 | kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, |
2702 | sizeof(void*)); | 2967 | sizeof(void*)); |
2703 | if (session->leadconn == conn) | 2968 | if (session->leadconn == conn) |
2704 | session->leadconn = NULL; | 2969 | session->leadconn = NULL; |
@@ -2823,14 +3088,15 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2823 | session->state = ISCSI_STATE_TERMINATE; | 3088 | session->state = ISCSI_STATE_TERMINATE; |
2824 | else if (conn->stop_stage != STOP_CONN_RECOVER) | 3089 | else if (conn->stop_stage != STOP_CONN_RECOVER) |
2825 | session->state = ISCSI_STATE_IN_RECOVERY; | 3090 | session->state = ISCSI_STATE_IN_RECOVERY; |
3091 | |||
3092 | old_stop_stage = conn->stop_stage; | ||
3093 | conn->stop_stage = flag; | ||
2826 | spin_unlock_bh(&session->lock); | 3094 | spin_unlock_bh(&session->lock); |
2827 | 3095 | ||
2828 | del_timer_sync(&conn->transport_timer); | 3096 | del_timer_sync(&conn->transport_timer); |
2829 | iscsi_suspend_tx(conn); | 3097 | iscsi_suspend_tx(conn); |
2830 | 3098 | ||
2831 | spin_lock_bh(&session->lock); | 3099 | spin_lock_bh(&session->lock); |
2832 | old_stop_stage = conn->stop_stage; | ||
2833 | conn->stop_stage = flag; | ||
2834 | conn->c_stage = ISCSI_CONN_STOPPED; | 3100 | conn->c_stage = ISCSI_CONN_STOPPED; |
2835 | spin_unlock_bh(&session->lock); | 3101 | spin_unlock_bh(&session->lock); |
2836 | 3102 | ||
@@ -2856,6 +3122,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2856 | spin_lock_bh(&session->lock); | 3122 | spin_lock_bh(&session->lock); |
2857 | fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); | 3123 | fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); |
2858 | fail_mgmt_tasks(session, conn); | 3124 | fail_mgmt_tasks(session, conn); |
3125 | memset(&conn->tmhdr, 0, sizeof(conn->tmhdr)); | ||
2859 | spin_unlock_bh(&session->lock); | 3126 | spin_unlock_bh(&session->lock); |
2860 | mutex_unlock(&session->eh_mutex); | 3127 | mutex_unlock(&session->eh_mutex); |
2861 | } | 3128 | } |
@@ -2932,6 +3199,9 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
2932 | case ISCSI_PARAM_LU_RESET_TMO: | 3199 | case ISCSI_PARAM_LU_RESET_TMO: |
2933 | sscanf(buf, "%d", &session->lu_reset_timeout); | 3200 | sscanf(buf, "%d", &session->lu_reset_timeout); |
2934 | break; | 3201 | break; |
3202 | case ISCSI_PARAM_TGT_RESET_TMO: | ||
3203 | sscanf(buf, "%d", &session->tgt_reset_timeout); | ||
3204 | break; | ||
2935 | case ISCSI_PARAM_PING_TMO: | 3205 | case ISCSI_PARAM_PING_TMO: |
2936 | sscanf(buf, "%d", &conn->ping_timeout); | 3206 | sscanf(buf, "%d", &conn->ping_timeout); |
2937 | break; | 3207 | break; |
@@ -3031,6 +3301,9 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session, | |||
3031 | case ISCSI_PARAM_LU_RESET_TMO: | 3301 | case ISCSI_PARAM_LU_RESET_TMO: |
3032 | len = sprintf(buf, "%d\n", session->lu_reset_timeout); | 3302 | len = sprintf(buf, "%d\n", session->lu_reset_timeout); |
3033 | break; | 3303 | break; |
3304 | case ISCSI_PARAM_TGT_RESET_TMO: | ||
3305 | len = sprintf(buf, "%d\n", session->tgt_reset_timeout); | ||
3306 | break; | ||
3034 | case ISCSI_PARAM_INITIAL_R2T_EN: | 3307 | case ISCSI_PARAM_INITIAL_R2T_EN: |
3035 | len = sprintf(buf, "%d\n", session->initial_r2t_en); | 3308 | len = sprintf(buf, "%d\n", session->initial_r2t_en); |
3036 | break; | 3309 | break; |