aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2007-12-13 13:43:30 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-11 19:28:35 -0500
commitf6d5180c78780d63b0577edeb3ce41eeb3e93eea (patch)
tree95eb44fb84dd7659f816c5f1166c1ae7e2301f5f
parent2697478903d0ad8bdbf868b1346ae4b891662bb1 (diff)
[SCSI] libiscsi: fix nop handling
During root boot and shutdown the target could send us nops. At this time iscsid cannot be running, so the target will drop the session and the boot or shutdown will hang. To handle this and allow us to better control when to check the network this patch moves the nop handling to the kernel. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c4
-rw-r--r--drivers/scsi/iscsi_tcp.c4
-rw-r--r--drivers/scsi/libiscsi.c331
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c4
-rw-r--r--include/scsi/iscsi_if.h11
-rw-r--r--include/scsi/libiscsi.h8
6 files changed, 294 insertions, 68 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index a2622f4bd858..265606422278 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -577,7 +577,9 @@ static struct iscsi_transport iscsi_iser_transport = {
577 ISCSI_PERSISTENT_ADDRESS | 577 ISCSI_PERSISTENT_ADDRESS |
578 ISCSI_TARGET_NAME | ISCSI_TPGT | 578 ISCSI_TARGET_NAME | ISCSI_TPGT |
579 ISCSI_USERNAME | ISCSI_PASSWORD | 579 ISCSI_USERNAME | ISCSI_PASSWORD |
580 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN, 580 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
581 ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
582 ISCSI_PING_TMO | ISCSI_RECV_TMO,
581 .host_param_mask = ISCSI_HOST_HWADDRESS | 583 .host_param_mask = ISCSI_HOST_HWADDRESS |
582 ISCSI_HOST_NETDEV_NAME | 584 ISCSI_HOST_NETDEV_NAME |
583 ISCSI_HOST_INITIATOR_NAME, 585 ISCSI_HOST_INITIATOR_NAME,
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 90eae8e0d978..9b418522c9bf 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -2246,7 +2246,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
2246 ISCSI_TARGET_NAME | ISCSI_TPGT | 2246 ISCSI_TARGET_NAME | ISCSI_TPGT |
2247 ISCSI_USERNAME | ISCSI_PASSWORD | 2247 ISCSI_USERNAME | ISCSI_PASSWORD |
2248 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | 2248 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
2249 ISCSI_FAST_ABORT, 2249 ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
2250 ISCSI_LU_RESET_TMO |
2251 ISCSI_PING_TMO | ISCSI_RECV_TMO,
2250 .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | 2252 .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
2251 ISCSI_HOST_INITIATOR_NAME | 2253 ISCSI_HOST_INITIATOR_NAME |
2252 ISCSI_HOST_NETDEV_NAME, 2254 ISCSI_HOST_NETDEV_NAME,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 5205ef2c29b2..96883614ba08 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -313,11 +313,70 @@ void iscsi_free_mgmt_task(struct iscsi_conn *conn,
313 list_del_init(&mtask->running); 313 list_del_init(&mtask->running);
314 if (conn->login_mtask == mtask) 314 if (conn->login_mtask == mtask)
315 return; 315 return;
316
317 if (conn->ping_mtask == mtask)
318 conn->ping_mtask = NULL;
316 __kfifo_put(conn->session->mgmtpool.queue, 319 __kfifo_put(conn->session->mgmtpool.queue,
317 (void*)&mtask, sizeof(void*)); 320 (void*)&mtask, sizeof(void*));
318} 321}
319EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); 322EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
320 323
324static struct iscsi_mgmt_task *
325__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
326 char *data, uint32_t data_size)
327{
328 struct iscsi_session *session = conn->session;
329 struct iscsi_mgmt_task *mtask;
330
331 if (session->state == ISCSI_STATE_TERMINATE)
332 return NULL;
333
334 if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
335 hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
336 /*
337 * Login and Text are sent serially, in
338 * request-followed-by-response sequence.
339 * Same mtask can be used. Same ITT must be used.
340 * Note that login_mtask is preallocated at conn_create().
341 */
342 mtask = conn->login_mtask;
343 else {
344 BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
345 BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
346
347 if (!__kfifo_get(session->mgmtpool.queue,
348 (void*)&mtask, sizeof(void*)))
349 return NULL;
350 }
351
352 if (data_size) {
353 memcpy(mtask->data, data, data_size);
354 mtask->data_count = data_size;
355 } else
356 mtask->data_count = 0;
357
358 memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
359 INIT_LIST_HEAD(&mtask->running);
360 list_add_tail(&mtask->running, &conn->mgmtqueue);
361 return mtask;
362}
363
364int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
365 char *data, uint32_t data_size)
366{
367 struct iscsi_conn *conn = cls_conn->dd_data;
368 struct iscsi_session *session = conn->session;
369 int err = 0;
370
371 spin_lock_bh(&session->lock);
372 if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
373 err = -EPERM;
374 spin_unlock_bh(&session->lock);
375 scsi_queue_work(session->host, &conn->xmitwork);
376 return err;
377}
378EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
379
321/** 380/**
322 * iscsi_cmd_rsp - SCSI Command Response processing 381 * iscsi_cmd_rsp - SCSI Command Response processing
323 * @conn: iscsi connection 382 * @conn: iscsi connection
@@ -409,6 +468,39 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
409 wake_up(&conn->ehwait); 468 wake_up(&conn->ehwait);
410} 469}
411 470
471static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
472{
473 struct iscsi_nopout hdr;
474 struct iscsi_mgmt_task *mtask;
475
476 if (!rhdr && conn->ping_mtask)
477 return;
478
479 memset(&hdr, 0, sizeof(struct iscsi_nopout));
480 hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
481 hdr.flags = ISCSI_FLAG_CMD_FINAL;
482
483 if (rhdr) {
484 memcpy(hdr.lun, rhdr->lun, 8);
485 hdr.ttt = rhdr->ttt;
486 hdr.itt = RESERVED_ITT;
487 } else
488 hdr.ttt = RESERVED_ITT;
489
490 mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
491 if (!mtask) {
492 printk(KERN_ERR "Could not send nopout\n");
493 return;
494 }
495
496 /* only track our nops */
497 if (!rhdr) {
498 conn->ping_mtask = mtask;
499 conn->last_ping = jiffies;
500 }
501 scsi_queue_work(conn->session->host, &conn->xmitwork);
502}
503
412static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, 504static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
413 char *data, int datalen) 505 char *data, int datalen)
414{ 506{
@@ -453,6 +545,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
453 struct iscsi_mgmt_task *mtask; 545 struct iscsi_mgmt_task *mtask;
454 uint32_t itt; 546 uint32_t itt;
455 547
548 conn->last_recv = jiffies;
456 if (hdr->itt != RESERVED_ITT) 549 if (hdr->itt != RESERVED_ITT)
457 itt = get_itt(hdr->itt); 550 itt = get_itt(hdr->itt);
458 else 551 else
@@ -520,14 +613,22 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
520 iscsi_free_mgmt_task(conn, mtask); 613 iscsi_free_mgmt_task(conn, mtask);
521 break; 614 break;
522 case ISCSI_OP_NOOP_IN: 615 case ISCSI_OP_NOOP_IN:
523 if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) { 616 if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) ||
617 datalen) {
524 rc = ISCSI_ERR_PROTO; 618 rc = ISCSI_ERR_PROTO;
525 break; 619 break;
526 } 620 }
527 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; 621 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
528 622
529 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) 623 if (conn->ping_mtask != mtask) {
530 rc = ISCSI_ERR_CONN_FAILED; 624 /*
625 * If this is not in response to one of our
626 * nops then it must be from userspace.
627 */
628 if (iscsi_recv_pdu(conn->cls_conn, hdr, data,
629 datalen))
630 rc = ISCSI_ERR_CONN_FAILED;
631 }
531 iscsi_free_mgmt_task(conn, mtask); 632 iscsi_free_mgmt_task(conn, mtask);
532 break; 633 break;
533 default: 634 default:
@@ -547,8 +648,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
547 if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) 648 if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG))
548 break; 649 break;
549 650
550 if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0)) 651 iscsi_send_nopout(conn, (struct iscsi_nopin*)hdr);
551 rc = ISCSI_ERR_CONN_FAILED;
552 break; 652 break;
553 case ISCSI_OP_REJECT: 653 case ISCSI_OP_REJECT:
554 rc = iscsi_handle_reject(conn, hdr, data, datalen); 654 rc = iscsi_handle_reject(conn, hdr, data, datalen);
@@ -1003,62 +1103,6 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
1003} 1103}
1004EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); 1104EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
1005 1105
1006static struct iscsi_mgmt_task *
1007__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
1008 char *data, uint32_t data_size)
1009{
1010 struct iscsi_session *session = conn->session;
1011 struct iscsi_mgmt_task *mtask;
1012
1013 if (session->state == ISCSI_STATE_TERMINATE)
1014 return NULL;
1015
1016 if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
1017 hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
1018 /*
1019 * Login and Text are sent serially, in
1020 * request-followed-by-response sequence.
1021 * Same mtask can be used. Same ITT must be used.
1022 * Note that login_mtask is preallocated at conn_create().
1023 */
1024 mtask = conn->login_mtask;
1025 else {
1026 BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
1027 BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
1028
1029 if (!__kfifo_get(session->mgmtpool.queue,
1030 (void*)&mtask, sizeof(void*)))
1031 return NULL;
1032 }
1033
1034 if (data_size) {
1035 memcpy(mtask->data, data, data_size);
1036 mtask->data_count = data_size;
1037 } else
1038 mtask->data_count = 0;
1039
1040 memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
1041 INIT_LIST_HEAD(&mtask->running);
1042 list_add_tail(&mtask->running, &conn->mgmtqueue);
1043 return mtask;
1044}
1045
1046int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
1047 char *data, uint32_t data_size)
1048{
1049 struct iscsi_conn *conn = cls_conn->dd_data;
1050 struct iscsi_session *session = conn->session;
1051 int err = 0;
1052
1053 spin_lock_bh(&session->lock);
1054 if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
1055 err = -EPERM;
1056 spin_unlock_bh(&session->lock);
1057 scsi_queue_work(session->host, &conn->xmitwork);
1058 return err;
1059}
1060EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
1061
1062void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) 1106void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
1063{ 1107{
1064 struct iscsi_session *session = class_to_transport_session(cls_session); 1108 struct iscsi_session *session = class_to_transport_session(cls_session);
@@ -1134,7 +1178,8 @@ static void iscsi_tmf_timedout(unsigned long data)
1134} 1178}
1135 1179
1136static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, 1180static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
1137 struct iscsi_tm *hdr, int age) 1181 struct iscsi_tm *hdr, int age,
1182 int timeout)
1138{ 1183{
1139 struct iscsi_session *session = conn->session; 1184 struct iscsi_session *session = conn->session;
1140 struct iscsi_mgmt_task *mtask; 1185 struct iscsi_mgmt_task *mtask;
@@ -1149,7 +1194,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
1149 return -EPERM; 1194 return -EPERM;
1150 } 1195 }
1151 conn->tmfcmd_pdus_cnt++; 1196 conn->tmfcmd_pdus_cnt++;
1152 conn->tmf_timer.expires = 30 * HZ + jiffies; 1197 conn->tmf_timer.expires = timeout * HZ + jiffies;
1153 conn->tmf_timer.function = iscsi_tmf_timedout; 1198 conn->tmf_timer.function = iscsi_tmf_timedout;
1154 conn->tmf_timer.data = (unsigned long)conn; 1199 conn->tmf_timer.data = (unsigned long)conn;
1155 add_timer(&conn->tmf_timer); 1200 add_timer(&conn->tmf_timer);
@@ -1233,6 +1278,106 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
1233 scsi_queue_work(conn->session->host, &conn->xmitwork); 1278 scsi_queue_work(conn->session->host, &conn->xmitwork);
1234} 1279}
1235 1280
1281static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
1282{
1283 struct iscsi_cls_session *cls_session;
1284 struct iscsi_session *session;
1285 struct iscsi_conn *conn;
1286 enum scsi_eh_timer_return rc = EH_NOT_HANDLED;
1287
1288 cls_session = starget_to_session(scsi_target(scmd->device));
1289 session = class_to_transport_session(cls_session);
1290
1291 debug_scsi("scsi cmd %p timedout\n", scmd);
1292
1293 spin_lock(&session->lock);
1294 if (session->state != ISCSI_STATE_LOGGED_IN) {
1295 /*
1296 * We are probably in the middle of iscsi recovery so let
1297 * that complete and handle the error.
1298 */
1299 rc = EH_RESET_TIMER;
1300 goto done;
1301 }
1302
1303 conn = session->leadconn;
1304 if (!conn) {
1305 /* In the middle of shuting down */
1306 rc = EH_RESET_TIMER;
1307 goto done;
1308 }
1309
1310 if (!conn->recv_timeout && !conn->ping_timeout)
1311 goto done;
1312 /*
1313 * if the ping timedout then we are in the middle of cleaning up
1314 * and can let the iscsi eh handle it
1315 */
1316 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
1317 (conn->ping_timeout * HZ), jiffies))
1318 rc = EH_RESET_TIMER;
1319 /*
1320 * if we are about to check the transport then give the command
1321 * more time
1322 */
1323 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
1324 jiffies))
1325 rc = EH_RESET_TIMER;
1326 /* if in the middle of checking the transport then give us more time */
1327 if (conn->ping_mtask)
1328 rc = EH_RESET_TIMER;
1329done:
1330 spin_unlock(&session->lock);
1331 debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh");
1332 return rc;
1333}
1334
1335static void iscsi_check_transport_timeouts(unsigned long data)
1336{
1337 struct iscsi_conn *conn = (struct iscsi_conn *)data;
1338 struct iscsi_session *session = conn->session;
1339 unsigned long timeout, next_timeout = 0, last_recv;
1340
1341 spin_lock(&session->lock);
1342 if (session->state != ISCSI_STATE_LOGGED_IN)
1343 goto done;
1344
1345 timeout = conn->recv_timeout;
1346 if (!timeout)
1347 goto done;
1348
1349 timeout *= HZ;
1350 last_recv = conn->last_recv;
1351 if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ),
1352 jiffies)) {
1353 printk(KERN_ERR "ping timeout of %d secs expired, "
1354 "last rx %lu, last ping %lu, now %lu\n",
1355 conn->ping_timeout, last_recv,
1356 conn->last_ping, jiffies);
1357 spin_unlock(&session->lock);
1358 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1359 return;
1360 }
1361
1362 if (time_before_eq(last_recv + timeout, jiffies)) {
1363 if (time_before_eq(conn->last_ping, last_recv)) {
1364 /* send a ping to try to provoke some traffic */
1365 debug_scsi("Sending nopout as ping on conn %p\n", conn);
1366 iscsi_send_nopout(conn, NULL);
1367 }
1368 next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
1369 } else {
1370 next_timeout = last_recv + timeout;
1371 }
1372
1373 if (next_timeout) {
1374 debug_scsi("Setting next tmo %lu\n", next_timeout);
1375 mod_timer(&conn->transport_timer, next_timeout);
1376 }
1377done:
1378 spin_unlock(&session->lock);
1379}
1380
1236static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask, 1381static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask,
1237 struct iscsi_tm *hdr) 1382 struct iscsi_tm *hdr)
1238{ 1383{
@@ -1304,7 +1449,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1304 hdr = &conn->tmhdr; 1449 hdr = &conn->tmhdr;
1305 iscsi_prep_abort_task_pdu(ctask, hdr); 1450 iscsi_prep_abort_task_pdu(ctask, hdr);
1306 1451
1307 if (iscsi_exec_task_mgmt_fn(conn, hdr, age)) { 1452 if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
1308 rc = FAILED; 1453 rc = FAILED;
1309 goto failed; 1454 goto failed;
1310 } 1455 }
@@ -1365,7 +1510,7 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
1365 hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK; 1510 hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK;
1366 hdr->flags |= ISCSI_FLAG_CMD_FINAL; 1511 hdr->flags |= ISCSI_FLAG_CMD_FINAL;
1367 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); 1512 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
1368 hdr->rtt = ISCSI_RESERVED_TAG; 1513 hdr->rtt = RESERVED_ITT;
1369} 1514}
1370 1515
1371int iscsi_eh_device_reset(struct scsi_cmnd *sc) 1516int iscsi_eh_device_reset(struct scsi_cmnd *sc)
@@ -1396,7 +1541,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
1396 hdr = &conn->tmhdr; 1541 hdr = &conn->tmhdr;
1397 iscsi_prep_lun_reset_pdu(sc, hdr); 1542 iscsi_prep_lun_reset_pdu(sc, hdr);
1398 1543
1399 if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age)) { 1544 if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
1545 session->lu_reset_timeout)) {
1400 rc = FAILED; 1546 rc = FAILED;
1401 goto unlock; 1547 goto unlock;
1402 } 1548 }
@@ -1572,12 +1718,14 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
1572 shost->max_cmd_len = iscsit->max_cmd_len; 1718 shost->max_cmd_len = iscsit->max_cmd_len;
1573 shost->transportt = scsit; 1719 shost->transportt = scsit;
1574 shost->transportt->create_work_queue = 1; 1720 shost->transportt->create_work_queue = 1;
1721 shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
1575 *hostno = shost->host_no; 1722 *hostno = shost->host_no;
1576 1723
1577 session = iscsi_hostdata(shost->hostdata); 1724 session = iscsi_hostdata(shost->hostdata);
1578 memset(session, 0, sizeof(struct iscsi_session)); 1725 memset(session, 0, sizeof(struct iscsi_session));
1579 session->host = shost; 1726 session->host = shost;
1580 session->state = ISCSI_STATE_FREE; 1727 session->state = ISCSI_STATE_FREE;
1728 session->fast_abort = 1;
1581 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; 1729 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
1582 session->cmds_max = cmds_max; 1730 session->cmds_max = cmds_max;
1583 session->queued_cmdsn = session->cmdsn = initial_cmdsn; 1731 session->queued_cmdsn = session->cmdsn = initial_cmdsn;
@@ -1708,6 +1856,11 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
1708 conn->id = conn_idx; 1856 conn->id = conn_idx;
1709 conn->exp_statsn = 0; 1857 conn->exp_statsn = 0;
1710 conn->tmf_state = TMF_INITIAL; 1858 conn->tmf_state = TMF_INITIAL;
1859
1860 init_timer(&conn->transport_timer);
1861 conn->transport_timer.data = (unsigned long)conn;
1862 conn->transport_timer.function = iscsi_check_transport_timeouts;
1863
1711 INIT_LIST_HEAD(&conn->run_list); 1864 INIT_LIST_HEAD(&conn->run_list);
1712 INIT_LIST_HEAD(&conn->mgmt_run_list); 1865 INIT_LIST_HEAD(&conn->mgmt_run_list);
1713 INIT_LIST_HEAD(&conn->mgmtqueue); 1866 INIT_LIST_HEAD(&conn->mgmtqueue);
@@ -1757,6 +1910,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
1757 struct iscsi_session *session = conn->session; 1910 struct iscsi_session *session = conn->session;
1758 unsigned long flags; 1911 unsigned long flags;
1759 1912
1913 del_timer_sync(&conn->transport_timer);
1914
1760 spin_lock_bh(&session->lock); 1915 spin_lock_bh(&session->lock);
1761 conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; 1916 conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
1762 if (session->leadconn == conn) { 1917 if (session->leadconn == conn) {
@@ -1823,11 +1978,29 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
1823 return -EINVAL; 1978 return -EINVAL;
1824 } 1979 }
1825 1980
1981 if (conn->ping_timeout && !conn->recv_timeout) {
1982 printk(KERN_ERR "iscsi: invalid recv timeout of zero "
1983 "Using 5 seconds\n.");
1984 conn->recv_timeout = 5;
1985 }
1986
1987 if (conn->recv_timeout && !conn->ping_timeout) {
1988 printk(KERN_ERR "iscsi: invalid ping timeout of zero "
1989 "Using 5 seconds.\n");
1990 conn->ping_timeout = 5;
1991 }
1992
1826 spin_lock_bh(&session->lock); 1993 spin_lock_bh(&session->lock);
1827 conn->c_stage = ISCSI_CONN_STARTED; 1994 conn->c_stage = ISCSI_CONN_STARTED;
1828 session->state = ISCSI_STATE_LOGGED_IN; 1995 session->state = ISCSI_STATE_LOGGED_IN;
1829 session->queued_cmdsn = session->cmdsn; 1996 session->queued_cmdsn = session->cmdsn;
1830 1997
1998 conn->last_recv = jiffies;
1999 conn->last_ping = jiffies;
2000 if (conn->recv_timeout && conn->ping_timeout)
2001 mod_timer(&conn->transport_timer,
2002 jiffies + (conn->recv_timeout * HZ));
2003
1831 switch(conn->stop_stage) { 2004 switch(conn->stop_stage) {
1832 case STOP_CONN_RECOVER: 2005 case STOP_CONN_RECOVER:
1833 /* 2006 /*
@@ -1879,6 +2052,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
1879{ 2052{
1880 int old_stop_stage; 2053 int old_stop_stage;
1881 2054
2055 del_timer_sync(&conn->transport_timer);
2056
1882 mutex_lock(&session->eh_mutex); 2057 mutex_lock(&session->eh_mutex);
1883 spin_lock_bh(&session->lock); 2058 spin_lock_bh(&session->lock);
1884 if (conn->stop_stage == STOP_CONN_TERM) { 2059 if (conn->stop_stage == STOP_CONN_TERM) {
@@ -1993,6 +2168,18 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
1993 case ISCSI_PARAM_FAST_ABORT: 2168 case ISCSI_PARAM_FAST_ABORT:
1994 sscanf(buf, "%d", &session->fast_abort); 2169 sscanf(buf, "%d", &session->fast_abort);
1995 break; 2170 break;
2171 case ISCSI_PARAM_ABORT_TMO:
2172 sscanf(buf, "%d", &session->abort_timeout);
2173 break;
2174 case ISCSI_PARAM_LU_RESET_TMO:
2175 sscanf(buf, "%d", &session->lu_reset_timeout);
2176 break;
2177 case ISCSI_PARAM_PING_TMO:
2178 sscanf(buf, "%d", &conn->ping_timeout);
2179 break;
2180 case ISCSI_PARAM_RECV_TMO:
2181 sscanf(buf, "%d", &conn->recv_timeout);
2182 break;
1996 case ISCSI_PARAM_MAX_RECV_DLENGTH: 2183 case ISCSI_PARAM_MAX_RECV_DLENGTH:
1997 sscanf(buf, "%d", &conn->max_recv_dlength); 2184 sscanf(buf, "%d", &conn->max_recv_dlength);
1998 break; 2185 break;
@@ -2110,6 +2297,12 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
2110 case ISCSI_PARAM_FAST_ABORT: 2297 case ISCSI_PARAM_FAST_ABORT:
2111 len = sprintf(buf, "%d\n", session->fast_abort); 2298 len = sprintf(buf, "%d\n", session->fast_abort);
2112 break; 2299 break;
2300 case ISCSI_PARAM_ABORT_TMO:
2301 len = sprintf(buf, "%d\n", session->abort_timeout);
2302 break;
2303 case ISCSI_PARAM_LU_RESET_TMO:
2304 len = sprintf(buf, "%d\n", session->lu_reset_timeout);
2305 break;
2113 case ISCSI_PARAM_INITIAL_R2T_EN: 2306 case ISCSI_PARAM_INITIAL_R2T_EN:
2114 len = sprintf(buf, "%d\n", session->initial_r2t_en); 2307 len = sprintf(buf, "%d\n", session->initial_r2t_en);
2115 break; 2308 break;
@@ -2167,6 +2360,12 @@ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
2167 int len; 2360 int len;
2168 2361
2169 switch(param) { 2362 switch(param) {
2363 case ISCSI_PARAM_PING_TMO:
2364 len = sprintf(buf, "%u\n", conn->ping_timeout);
2365 break;
2366 case ISCSI_PARAM_RECV_TMO:
2367 len = sprintf(buf, "%u\n", conn->recv_timeout);
2368 break;
2170 case ISCSI_PARAM_MAX_RECV_DLENGTH: 2369 case ISCSI_PARAM_MAX_RECV_DLENGTH:
2171 len = sprintf(buf, "%u\n", conn->max_recv_dlength); 2370 len = sprintf(buf, "%u\n", conn->max_recv_dlength);
2172 break; 2371 break;
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index b82139dc4830..36aa50e45ec7 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1202,6 +1202,8 @@ iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
1202iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN); 1202iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
1203iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); 1203iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
1204iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS); 1204iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
1205iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
1206iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
1205 1207
1206#define iscsi_cdev_to_session(_cdev) \ 1208#define iscsi_cdev_to_session(_cdev) \
1207 iscsi_dev_to_session(_cdev->dev) 1209 iscsi_dev_to_session(_cdev->dev)
@@ -1437,6 +1439,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
1437 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); 1439 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
1438 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); 1440 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
1439 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); 1441 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
1442 SETUP_CONN_RD_ATTR(ping_tmo, ISCSI_PING_TMO);
1443 SETUP_CONN_RD_ATTR(recv_tmo, ISCSI_RECV_TMO);
1440 1444
1441 BUG_ON(count > ISCSI_CONN_ATTRS); 1445 BUG_ON(count > ISCSI_CONN_ATTRS);
1442 priv->conn_attrs[count] = NULL; 1446 priv->conn_attrs[count] = NULL;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 8a4426df6c3a..e19e58423166 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -244,6 +244,12 @@ enum iscsi_param {
244 ISCSI_PARAM_PASSWORD_IN, 244 ISCSI_PARAM_PASSWORD_IN,
245 245
246 ISCSI_PARAM_FAST_ABORT, 246 ISCSI_PARAM_FAST_ABORT,
247 ISCSI_PARAM_ABORT_TMO,
248 ISCSI_PARAM_LU_RESET_TMO,
249 ISCSI_PARAM_HOST_RESET_TMO,
250
251 ISCSI_PARAM_PING_TMO,
252 ISCSI_PARAM_RECV_TMO,
247 /* must always be last */ 253 /* must always be last */
248 ISCSI_PARAM_MAX, 254 ISCSI_PARAM_MAX,
249}; 255};
@@ -275,6 +281,11 @@ enum iscsi_param {
275#define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD) 281#define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD)
276#define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN) 282#define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN)
277#define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT) 283#define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT)
284#define ISCSI_ABORT_TMO (1 << ISCSI_PARAM_ABORT_TMO)
285#define ISCSI_LU_RESET_TMO (1 << ISCSI_PARAM_LU_RESET_TMO)
286#define ISCSI_HOST_RESET_TMO (1 << ISCSI_PARAM_HOST_RESET_TMO)
287#define ISCSI_PING_TMO (1 << ISCSI_PARAM_PING_TMO)
288#define ISCSI_RECV_TMO (1 << ISCSI_PARAM_RECV_TMO)
278 289
279/* iSCSI HBA params */ 290/* iSCSI HBA params */
280enum iscsi_host_param { 291enum iscsi_host_param {
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index d68f74523f2e..889f51fabab9 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -148,6 +148,12 @@ struct iscsi_conn {
148 * conn_stop() flag: stop to recover, stop to terminate 148 * conn_stop() flag: stop to recover, stop to terminate
149 */ 149 */
150 int stop_stage; 150 int stop_stage;
151 struct timer_list transport_timer;
152 unsigned long last_recv;
153 unsigned long last_ping;
154 int ping_timeout;
155 int recv_timeout;
156 struct iscsi_mgmt_task *ping_mtask;
151 157
152 /* iSCSI connection-wide sequencing */ 158 /* iSCSI connection-wide sequencing */
153 uint32_t exp_statsn; 159 uint32_t exp_statsn;
@@ -238,6 +244,8 @@ struct iscsi_session {
238 uint32_t queued_cmdsn; 244 uint32_t queued_cmdsn;
239 245
240 /* configuration */ 246 /* configuration */
247 int abort_timeout;
248 int lu_reset_timeout;
241 int initial_r2t_en; 249 int initial_r2t_en;
242 unsigned max_r2t; 250 unsigned max_r2t;
243 int imm_data_en; 251 int imm_data_en;