diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 703eb6a88790..6d5ae4474bb3 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> |
@@ -2338,7 +2339,7 @@ EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); | |||
2338 | * This function will wait for a relogin, session termination from | 2339 | * This function will wait for a relogin, session termination from |
2339 | * userspace, or a recovery/replacement timeout. | 2340 | * userspace, or a recovery/replacement timeout. |
2340 | */ | 2341 | */ |
2341 | static int iscsi_eh_session_reset(struct scsi_cmnd *sc) | 2342 | int iscsi_eh_session_reset(struct scsi_cmnd *sc) |
2342 | { | 2343 | { |
2343 | struct iscsi_cls_session *cls_session; | 2344 | struct iscsi_cls_session *cls_session; |
2344 | struct iscsi_session *session; | 2345 | struct iscsi_session *session; |
@@ -2389,6 +2390,7 @@ failed: | |||
2389 | mutex_unlock(&session->eh_mutex); | 2390 | mutex_unlock(&session->eh_mutex); |
2390 | return SUCCESS; | 2391 | return SUCCESS; |
2391 | } | 2392 | } |
2393 | EXPORT_SYMBOL_GPL(iscsi_eh_session_reset); | ||
2392 | 2394 | ||
2393 | static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) | 2395 | static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) |
2394 | { | 2396 | { |
@@ -2403,8 +2405,7 @@ static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) | |||
2403 | * iscsi_eh_target_reset - reset target | 2405 | * iscsi_eh_target_reset - reset target |
2404 | * @sc: scsi command | 2406 | * @sc: scsi command |
2405 | * | 2407 | * |
2406 | * This will attempt to send a warm target reset. If that fails | 2408 | * This will attempt to send a warm target reset. |
2407 | * then we will drop the session and attempt ERL0 recovery. | ||
2408 | */ | 2409 | */ |
2409 | int iscsi_eh_target_reset(struct scsi_cmnd *sc) | 2410 | int iscsi_eh_target_reset(struct scsi_cmnd *sc) |
2410 | { | 2411 | { |
@@ -2476,12 +2477,27 @@ done: | |||
2476 | ISCSI_DBG_EH(session, "tgt %s reset result = %s\n", session->targetname, | 2477 | ISCSI_DBG_EH(session, "tgt %s reset result = %s\n", session->targetname, |
2477 | rc == SUCCESS ? "SUCCESS" : "FAILED"); | 2478 | rc == SUCCESS ? "SUCCESS" : "FAILED"); |
2478 | mutex_unlock(&session->eh_mutex); | 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; | ||
2479 | 2494 | ||
2495 | rc = iscsi_eh_target_reset(sc); | ||
2480 | if (rc == FAILED) | 2496 | if (rc == FAILED) |
2481 | rc = iscsi_eh_session_reset(sc); | 2497 | rc = iscsi_eh_session_reset(sc); |
2482 | return rc; | 2498 | return rc; |
2483 | } | 2499 | } |
2484 | EXPORT_SYMBOL_GPL(iscsi_eh_target_reset); | 2500 | EXPORT_SYMBOL_GPL(iscsi_eh_recover_target); |
2485 | 2501 | ||
2486 | /* | 2502 | /* |
2487 | * 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 |
@@ -3072,14 +3088,15 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
3072 | session->state = ISCSI_STATE_TERMINATE; | 3088 | session->state = ISCSI_STATE_TERMINATE; |
3073 | else if (conn->stop_stage != STOP_CONN_RECOVER) | 3089 | else if (conn->stop_stage != STOP_CONN_RECOVER) |
3074 | 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; | ||
3075 | spin_unlock_bh(&session->lock); | 3094 | spin_unlock_bh(&session->lock); |
3076 | 3095 | ||
3077 | del_timer_sync(&conn->transport_timer); | 3096 | del_timer_sync(&conn->transport_timer); |
3078 | iscsi_suspend_tx(conn); | 3097 | iscsi_suspend_tx(conn); |
3079 | 3098 | ||
3080 | spin_lock_bh(&session->lock); | 3099 | spin_lock_bh(&session->lock); |
3081 | old_stop_stage = conn->stop_stage; | ||
3082 | conn->stop_stage = flag; | ||
3083 | conn->c_stage = ISCSI_CONN_STOPPED; | 3100 | conn->c_stage = ISCSI_CONN_STOPPED; |
3084 | spin_unlock_bh(&session->lock); | 3101 | spin_unlock_bh(&session->lock); |
3085 | 3102 | ||