diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-01-31 14:36:43 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-07 19:02:34 -0500 |
commit | 6eabafbe6616266e8de61980a7dac5ecc1ba1113 (patch) | |
tree | f5533027fac576acf4db08210ea5815db3a15e50 | |
parent | 84ac86ca8c6787f9efff28bc04b1b65fe0a5c310 (diff) |
[SCSI] iscsi class, libiscsi: add iscsi sysfs session state file
This adds a iscsi session state file which exports the session
state for both software and hardware iscsi. It also hooks libiscsi
in.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/libiscsi.c | 41 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 107 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 19 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 27 |
4 files changed, 161 insertions, 33 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index e7942628ac4a..c8c00e173414 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -996,6 +996,7 @@ enum { | |||
996 | FAILURE_SESSION_IN_RECOVERY, | 996 | FAILURE_SESSION_IN_RECOVERY, |
997 | FAILURE_SESSION_RECOVERY_TIMEOUT, | 997 | FAILURE_SESSION_RECOVERY_TIMEOUT, |
998 | FAILURE_SESSION_LOGGING_OUT, | 998 | FAILURE_SESSION_LOGGING_OUT, |
999 | FAILURE_SESSION_NOT_READY, | ||
999 | }; | 1000 | }; |
1000 | 1001 | ||
1001 | int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | 1002 | int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) |
@@ -1016,6 +1017,12 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1016 | session = iscsi_hostdata(host->hostdata); | 1017 | session = iscsi_hostdata(host->hostdata); |
1017 | spin_lock(&session->lock); | 1018 | spin_lock(&session->lock); |
1018 | 1019 | ||
1020 | reason = iscsi_session_chkready(session_to_cls(session)); | ||
1021 | if (reason) { | ||
1022 | sc->result = reason; | ||
1023 | goto fault; | ||
1024 | } | ||
1025 | |||
1019 | /* | 1026 | /* |
1020 | * ISCSI_STATE_FAILED is a temp. state. The recovery | 1027 | * ISCSI_STATE_FAILED is a temp. state. The recovery |
1021 | * code will decide what is best to do with command queued | 1028 | * code will decide what is best to do with command queued |
@@ -1032,18 +1039,23 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1032 | switch (session->state) { | 1039 | switch (session->state) { |
1033 | case ISCSI_STATE_IN_RECOVERY: | 1040 | case ISCSI_STATE_IN_RECOVERY: |
1034 | reason = FAILURE_SESSION_IN_RECOVERY; | 1041 | reason = FAILURE_SESSION_IN_RECOVERY; |
1035 | goto reject; | 1042 | sc->result = DID_IMM_RETRY << 16; |
1043 | break; | ||
1036 | case ISCSI_STATE_LOGGING_OUT: | 1044 | case ISCSI_STATE_LOGGING_OUT: |
1037 | reason = FAILURE_SESSION_LOGGING_OUT; | 1045 | reason = FAILURE_SESSION_LOGGING_OUT; |
1038 | goto reject; | 1046 | sc->result = DID_IMM_RETRY << 16; |
1047 | break; | ||
1039 | case ISCSI_STATE_RECOVERY_FAILED: | 1048 | case ISCSI_STATE_RECOVERY_FAILED: |
1040 | reason = FAILURE_SESSION_RECOVERY_TIMEOUT; | 1049 | reason = FAILURE_SESSION_RECOVERY_TIMEOUT; |
1050 | sc->result = DID_NO_CONNECT << 16; | ||
1041 | break; | 1051 | break; |
1042 | case ISCSI_STATE_TERMINATE: | 1052 | case ISCSI_STATE_TERMINATE: |
1043 | reason = FAILURE_SESSION_TERMINATE; | 1053 | reason = FAILURE_SESSION_TERMINATE; |
1054 | sc->result = DID_NO_CONNECT << 16; | ||
1044 | break; | 1055 | break; |
1045 | default: | 1056 | default: |
1046 | reason = FAILURE_SESSION_FREED; | 1057 | reason = FAILURE_SESSION_FREED; |
1058 | sc->result = DID_NO_CONNECT << 16; | ||
1047 | } | 1059 | } |
1048 | goto fault; | 1060 | goto fault; |
1049 | } | 1061 | } |
@@ -1051,6 +1063,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1051 | conn = session->leadconn; | 1063 | conn = session->leadconn; |
1052 | if (!conn) { | 1064 | if (!conn) { |
1053 | reason = FAILURE_SESSION_FREED; | 1065 | reason = FAILURE_SESSION_FREED; |
1066 | sc->result = DID_NO_CONNECT << 16; | ||
1054 | goto fault; | 1067 | goto fault; |
1055 | } | 1068 | } |
1056 | 1069 | ||
@@ -1090,9 +1103,7 @@ reject: | |||
1090 | 1103 | ||
1091 | fault: | 1104 | fault: |
1092 | spin_unlock(&session->lock); | 1105 | spin_unlock(&session->lock); |
1093 | printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n", | 1106 | debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); |
1094 | sc->cmnd[0], reason); | ||
1095 | sc->result = (DID_NO_CONNECT << 16); | ||
1096 | scsi_set_resid(sc, scsi_bufflen(sc)); | 1107 | scsi_set_resid(sc, scsi_bufflen(sc)); |
1097 | sc->scsi_done(sc); | 1108 | sc->scsi_done(sc); |
1098 | spin_lock(host->host_lock); | 1109 | spin_lock(host->host_lock); |
@@ -1238,7 +1249,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1238 | * Fail commands. session lock held and recv side suspended and xmit | 1249 | * Fail commands. session lock held and recv side suspended and xmit |
1239 | * thread flushed | 1250 | * thread flushed |
1240 | */ | 1251 | */ |
1241 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) | 1252 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, |
1253 | int error) | ||
1242 | { | 1254 | { |
1243 | struct iscsi_cmd_task *ctask, *tmp; | 1255 | struct iscsi_cmd_task *ctask, *tmp; |
1244 | 1256 | ||
@@ -1250,7 +1262,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) | |||
1250 | if (lun == ctask->sc->device->lun || lun == -1) { | 1262 | if (lun == ctask->sc->device->lun || lun == -1) { |
1251 | debug_scsi("failing pending sc %p itt 0x%x\n", | 1263 | debug_scsi("failing pending sc %p itt 0x%x\n", |
1252 | ctask->sc, ctask->itt); | 1264 | ctask->sc, ctask->itt); |
1253 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | 1265 | fail_command(conn, ctask, error << 16); |
1254 | } | 1266 | } |
1255 | } | 1267 | } |
1256 | 1268 | ||
@@ -1258,7 +1270,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) | |||
1258 | if (lun == ctask->sc->device->lun || lun == -1) { | 1270 | if (lun == ctask->sc->device->lun || lun == -1) { |
1259 | debug_scsi("failing requeued sc %p itt 0x%x\n", | 1271 | debug_scsi("failing requeued sc %p itt 0x%x\n", |
1260 | ctask->sc, ctask->itt); | 1272 | ctask->sc, ctask->itt); |
1261 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | 1273 | fail_command(conn, ctask, error << 16); |
1262 | } | 1274 | } |
1263 | } | 1275 | } |
1264 | 1276 | ||
@@ -1572,7 +1584,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1572 | /* need to grab the recv lock then session lock */ | 1584 | /* need to grab the recv lock then session lock */ |
1573 | write_lock_bh(conn->recv_lock); | 1585 | write_lock_bh(conn->recv_lock); |
1574 | spin_lock(&session->lock); | 1586 | spin_lock(&session->lock); |
1575 | fail_all_commands(conn, sc->device->lun); | 1587 | fail_all_commands(conn, sc->device->lun, DID_ERROR); |
1576 | conn->tmf_state = TMF_INITIAL; | 1588 | conn->tmf_state = TMF_INITIAL; |
1577 | spin_unlock(&session->lock); | 1589 | spin_unlock(&session->lock); |
1578 | write_unlock_bh(conn->recv_lock); | 1590 | write_unlock_bh(conn->recv_lock); |
@@ -2018,11 +2030,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
2018 | conn->stop_stage = 0; | 2030 | conn->stop_stage = 0; |
2019 | conn->tmf_state = TMF_INITIAL; | 2031 | conn->tmf_state = TMF_INITIAL; |
2020 | session->age++; | 2032 | session->age++; |
2021 | spin_unlock_bh(&session->lock); | 2033 | break; |
2022 | |||
2023 | iscsi_unblock_session(session_to_cls(session)); | ||
2024 | wake_up(&conn->ehwait); | ||
2025 | return 0; | ||
2026 | case STOP_CONN_TERM: | 2034 | case STOP_CONN_TERM: |
2027 | conn->stop_stage = 0; | 2035 | conn->stop_stage = 0; |
2028 | break; | 2036 | break; |
@@ -2031,6 +2039,8 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
2031 | } | 2039 | } |
2032 | spin_unlock_bh(&session->lock); | 2040 | spin_unlock_bh(&session->lock); |
2033 | 2041 | ||
2042 | iscsi_unblock_session(session_to_cls(session)); | ||
2043 | wake_up(&conn->ehwait); | ||
2034 | return 0; | 2044 | return 0; |
2035 | } | 2045 | } |
2036 | EXPORT_SYMBOL_GPL(iscsi_conn_start); | 2046 | EXPORT_SYMBOL_GPL(iscsi_conn_start); |
@@ -2122,7 +2132,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2122 | * flush queues. | 2132 | * flush queues. |
2123 | */ | 2133 | */ |
2124 | spin_lock_bh(&session->lock); | 2134 | spin_lock_bh(&session->lock); |
2125 | fail_all_commands(conn, -1); | 2135 | fail_all_commands(conn, -1, |
2136 | STOP_CONN_RECOVER ? DID_BUS_BUSY : DID_ERROR); | ||
2126 | flush_control_queues(session, conn); | 2137 | flush_control_queues(session, conn); |
2127 | spin_unlock_bh(&session->lock); | 2138 | spin_unlock_bh(&session->lock); |
2128 | mutex_unlock(&session->eh_mutex); | 2139 | mutex_unlock(&session->eh_mutex); |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0d7b4e79415c..f876b0ae521a 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <scsi/scsi_transport_iscsi.h> | 30 | #include <scsi/scsi_transport_iscsi.h> |
31 | #include <scsi/iscsi_if.h> | 31 | #include <scsi/iscsi_if.h> |
32 | 32 | ||
33 | #define ISCSI_SESSION_ATTRS 18 | 33 | #define ISCSI_SESSION_ATTRS 19 |
34 | #define ISCSI_CONN_ATTRS 11 | 34 | #define ISCSI_CONN_ATTRS 11 |
35 | #define ISCSI_HOST_ATTRS 4 | 35 | #define ISCSI_HOST_ATTRS 4 |
36 | #define ISCSI_TRANSPORT_VERSION "2.0-867" | 36 | #define ISCSI_TRANSPORT_VERSION "2.0-867" |
@@ -221,6 +221,54 @@ static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid) | |||
221 | * The following functions can be used by LLDs that allocate | 221 | * The following functions can be used by LLDs that allocate |
222 | * their own scsi_hosts or by software iscsi LLDs | 222 | * their own scsi_hosts or by software iscsi LLDs |
223 | */ | 223 | */ |
224 | static struct { | ||
225 | int value; | ||
226 | char *name; | ||
227 | } iscsi_session_state_names[] = { | ||
228 | { ISCSI_SESSION_LOGGED_IN, "LOGGED_IN" }, | ||
229 | { ISCSI_SESSION_FAILED, "FAILED" }, | ||
230 | { ISCSI_SESSION_FREE, "FREE" }, | ||
231 | }; | ||
232 | |||
233 | const char *iscsi_session_state_name(int state) | ||
234 | { | ||
235 | int i; | ||
236 | char *name = NULL; | ||
237 | |||
238 | for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) { | ||
239 | if (iscsi_session_state_names[i].value == state) { | ||
240 | name = iscsi_session_state_names[i].name; | ||
241 | break; | ||
242 | } | ||
243 | } | ||
244 | return name; | ||
245 | } | ||
246 | |||
247 | int iscsi_session_chkready(struct iscsi_cls_session *session) | ||
248 | { | ||
249 | unsigned long flags; | ||
250 | int err; | ||
251 | |||
252 | spin_lock_irqsave(&session->lock, flags); | ||
253 | switch (session->state) { | ||
254 | case ISCSI_SESSION_LOGGED_IN: | ||
255 | err = 0; | ||
256 | break; | ||
257 | case ISCSI_SESSION_FAILED: | ||
258 | err = DID_IMM_RETRY << 16; | ||
259 | break; | ||
260 | case ISCSI_SESSION_FREE: | ||
261 | err = DID_NO_CONNECT << 16; | ||
262 | break; | ||
263 | default: | ||
264 | err = DID_NO_CONNECT << 16; | ||
265 | break; | ||
266 | } | ||
267 | spin_unlock_irqrestore(&session->lock, flags); | ||
268 | return err; | ||
269 | } | ||
270 | EXPORT_SYMBOL_GPL(iscsi_session_chkready); | ||
271 | |||
224 | static void iscsi_session_release(struct device *dev) | 272 | static void iscsi_session_release(struct device *dev) |
225 | { | 273 | { |
226 | struct iscsi_cls_session *session = iscsi_dev_to_session(dev); | 274 | struct iscsi_cls_session *session = iscsi_dev_to_session(dev); |
@@ -259,26 +307,57 @@ static void session_recovery_timedout(struct work_struct *work) | |||
259 | struct iscsi_cls_session *session = | 307 | struct iscsi_cls_session *session = |
260 | container_of(work, struct iscsi_cls_session, | 308 | container_of(work, struct iscsi_cls_session, |
261 | recovery_work.work); | 309 | recovery_work.work); |
310 | unsigned long flags; | ||
262 | 311 | ||
263 | dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " | 312 | dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " |
264 | "out after %d secs\n", session->recovery_tmo); | 313 | "out after %d secs\n", session->recovery_tmo); |
265 | 314 | ||
315 | spin_lock_irqsave(&session->lock, flags); | ||
316 | switch (session->state) { | ||
317 | case ISCSI_SESSION_FAILED: | ||
318 | session->state = ISCSI_SESSION_FREE; | ||
319 | break; | ||
320 | case ISCSI_SESSION_LOGGED_IN: | ||
321 | case ISCSI_SESSION_FREE: | ||
322 | /* we raced with the unblock's flush */ | ||
323 | spin_unlock_irqrestore(&session->lock, flags); | ||
324 | return; | ||
325 | } | ||
326 | spin_unlock_irqrestore(&session->lock, flags); | ||
327 | |||
266 | if (session->transport->session_recovery_timedout) | 328 | if (session->transport->session_recovery_timedout) |
267 | session->transport->session_recovery_timedout(session); | 329 | session->transport->session_recovery_timedout(session); |
268 | 330 | ||
269 | scsi_target_unblock(&session->dev); | 331 | scsi_target_unblock(&session->dev); |
270 | } | 332 | } |
271 | 333 | ||
272 | void iscsi_unblock_session(struct iscsi_cls_session *session) | 334 | void __iscsi_unblock_session(struct iscsi_cls_session *session) |
273 | { | 335 | { |
274 | if (!cancel_delayed_work(&session->recovery_work)) | 336 | if (!cancel_delayed_work(&session->recovery_work)) |
275 | flush_workqueue(iscsi_eh_timer_workq); | 337 | flush_workqueue(iscsi_eh_timer_workq); |
276 | scsi_target_unblock(&session->dev); | 338 | scsi_target_unblock(&session->dev); |
277 | } | 339 | } |
340 | |||
341 | void iscsi_unblock_session(struct iscsi_cls_session *session) | ||
342 | { | ||
343 | unsigned long flags; | ||
344 | |||
345 | spin_lock_irqsave(&session->lock, flags); | ||
346 | session->state = ISCSI_SESSION_LOGGED_IN; | ||
347 | spin_unlock_irqrestore(&session->lock, flags); | ||
348 | |||
349 | __iscsi_unblock_session(session); | ||
350 | } | ||
278 | EXPORT_SYMBOL_GPL(iscsi_unblock_session); | 351 | EXPORT_SYMBOL_GPL(iscsi_unblock_session); |
279 | 352 | ||
280 | void iscsi_block_session(struct iscsi_cls_session *session) | 353 | void iscsi_block_session(struct iscsi_cls_session *session) |
281 | { | 354 | { |
355 | unsigned long flags; | ||
356 | |||
357 | spin_lock_irqsave(&session->lock, flags); | ||
358 | session->state = ISCSI_SESSION_FAILED; | ||
359 | spin_unlock_irqrestore(&session->lock, flags); | ||
360 | |||
282 | scsi_target_block(&session->dev); | 361 | scsi_target_block(&session->dev); |
283 | queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work, | 362 | queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work, |
284 | session->recovery_tmo * HZ); | 363 | session->recovery_tmo * HZ); |
@@ -327,10 +406,12 @@ iscsi_alloc_session(struct Scsi_Host *shost, | |||
327 | 406 | ||
328 | session->transport = transport; | 407 | session->transport = transport; |
329 | session->recovery_tmo = 120; | 408 | session->recovery_tmo = 120; |
409 | session->state = ISCSI_SESSION_FREE; | ||
330 | INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); | 410 | INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); |
331 | INIT_LIST_HEAD(&session->host_list); | 411 | INIT_LIST_HEAD(&session->host_list); |
332 | INIT_LIST_HEAD(&session->sess_list); | 412 | INIT_LIST_HEAD(&session->sess_list); |
333 | INIT_WORK(&session->unbind_work, __iscsi_unbind_session); | 413 | INIT_WORK(&session->unbind_work, __iscsi_unbind_session); |
414 | spin_lock_init(&session->lock); | ||
334 | 415 | ||
335 | /* this is released in the dev's release function */ | 416 | /* this is released in the dev's release function */ |
336 | scsi_host_get(shost); | 417 | scsi_host_get(shost); |
@@ -444,7 +525,10 @@ void iscsi_remove_session(struct iscsi_cls_session *session) | |||
444 | * If we are blocked let commands flow again. The lld or iscsi | 525 | * If we are blocked let commands flow again. The lld or iscsi |
445 | * layer should set up the queuecommand to fail commands. | 526 | * layer should set up the queuecommand to fail commands. |
446 | */ | 527 | */ |
447 | iscsi_unblock_session(session); | 528 | spin_lock_irqsave(&session->lock, flags); |
529 | session->state = ISCSI_SESSION_FREE; | ||
530 | spin_unlock_irqrestore(&session->lock, flags); | ||
531 | __iscsi_unblock_session(session); | ||
448 | iscsi_unbind_session(session); | 532 | iscsi_unbind_session(session); |
449 | /* | 533 | /* |
450 | * If the session dropped while removing devices then we need to make | 534 | * If the session dropped while removing devices then we need to make |
@@ -661,16 +745,23 @@ EXPORT_SYMBOL_GPL(iscsi_recv_pdu); | |||
661 | 745 | ||
662 | void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) | 746 | void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) |
663 | { | 747 | { |
748 | struct iscsi_cls_session *session = iscsi_conn_to_session(conn); | ||
664 | struct nlmsghdr *nlh; | 749 | struct nlmsghdr *nlh; |
665 | struct sk_buff *skb; | 750 | struct sk_buff *skb; |
666 | struct iscsi_uevent *ev; | 751 | struct iscsi_uevent *ev; |
667 | struct iscsi_internal *priv; | 752 | struct iscsi_internal *priv; |
668 | int len = NLMSG_SPACE(sizeof(*ev)); | 753 | int len = NLMSG_SPACE(sizeof(*ev)); |
754 | unsigned long flags; | ||
669 | 755 | ||
670 | priv = iscsi_if_transport_lookup(conn->transport); | 756 | priv = iscsi_if_transport_lookup(conn->transport); |
671 | if (!priv) | 757 | if (!priv) |
672 | return; | 758 | return; |
673 | 759 | ||
760 | spin_lock_irqsave(&session->lock, flags); | ||
761 | if (session->state == ISCSI_SESSION_LOGGED_IN) | ||
762 | session->state = ISCSI_SESSION_FAILED; | ||
763 | spin_unlock_irqrestore(&session->lock, flags); | ||
764 | |||
674 | skb = alloc_skb(len, GFP_ATOMIC); | 765 | skb = alloc_skb(len, GFP_ATOMIC); |
675 | if (!skb) { | 766 | if (!skb) { |
676 | dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored " | 767 | dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored " |
@@ -1246,6 +1337,15 @@ iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0); | |||
1246 | iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0); | 1337 | iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0); |
1247 | iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0); | 1338 | iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0); |
1248 | 1339 | ||
1340 | static ssize_t | ||
1341 | show_priv_session_state(struct class_device *cdev, char *buf) | ||
1342 | { | ||
1343 | struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); | ||
1344 | return sprintf(buf, "%s\n", iscsi_session_state_name(session->state)); | ||
1345 | } | ||
1346 | static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state, | ||
1347 | NULL); | ||
1348 | |||
1249 | #define iscsi_priv_session_attr_show(field, format) \ | 1349 | #define iscsi_priv_session_attr_show(field, format) \ |
1250 | static ssize_t \ | 1350 | static ssize_t \ |
1251 | show_priv_session_##field(struct class_device *cdev, char *buf) \ | 1351 | show_priv_session_##field(struct class_device *cdev, char *buf) \ |
@@ -1472,6 +1572,7 @@ iscsi_register_transport(struct iscsi_transport *tt) | |||
1472 | SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO); | 1572 | SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO); |
1473 | SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO); | 1573 | SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO); |
1474 | SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); | 1574 | SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); |
1575 | SETUP_PRIV_SESSION_RD_ATTR(state); | ||
1475 | 1576 | ||
1476 | BUG_ON(count > ISCSI_SESSION_ATTRS); | 1577 | BUG_ON(count > ISCSI_SESSION_ATTRS); |
1477 | priv->session_attrs[count] = NULL; | 1578 | priv->session_attrs[count] = NULL; |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 71eda24114e9..278011fb3c2f 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -135,6 +135,14 @@ static inline void* iscsi_next_hdr(struct iscsi_cmd_task *ctask) | |||
135 | return (void*)ctask->hdr + ctask->hdr_len; | 135 | return (void*)ctask->hdr + ctask->hdr_len; |
136 | } | 136 | } |
137 | 137 | ||
138 | /* Connection's states */ | ||
139 | enum { | ||
140 | ISCSI_CONN_INITIAL_STAGE, | ||
141 | ISCSI_CONN_STARTED, | ||
142 | ISCSI_CONN_STOPPED, | ||
143 | ISCSI_CONN_CLEANUP_WAIT, | ||
144 | }; | ||
145 | |||
138 | struct iscsi_conn { | 146 | struct iscsi_conn { |
139 | struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ | 147 | struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ |
140 | void *dd_data; /* iscsi_transport data */ | 148 | void *dd_data; /* iscsi_transport data */ |
@@ -227,6 +235,17 @@ struct iscsi_pool { | |||
227 | int max; /* Max number of elements */ | 235 | int max; /* Max number of elements */ |
228 | }; | 236 | }; |
229 | 237 | ||
238 | /* Session's states */ | ||
239 | enum { | ||
240 | ISCSI_STATE_FREE = 1, | ||
241 | ISCSI_STATE_LOGGED_IN, | ||
242 | ISCSI_STATE_FAILED, | ||
243 | ISCSI_STATE_TERMINATE, | ||
244 | ISCSI_STATE_IN_RECOVERY, | ||
245 | ISCSI_STATE_RECOVERY_FAILED, | ||
246 | ISCSI_STATE_LOGGING_OUT, | ||
247 | }; | ||
248 | |||
230 | struct iscsi_session { | 249 | struct iscsi_session { |
231 | /* | 250 | /* |
232 | * Syncs up the scsi eh thread with the iscsi eh thread when sending | 251 | * Syncs up the scsi eh thread with the iscsi eh thread when sending |
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 404f11d331d6..0e869d9a3856 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h | |||
@@ -149,13 +149,6 @@ extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error); | |||
149 | extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, | 149 | extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, |
150 | char *data, uint32_t data_size); | 150 | char *data, uint32_t data_size); |
151 | 151 | ||
152 | |||
153 | /* Connection's states */ | ||
154 | #define ISCSI_CONN_INITIAL_STAGE 0 | ||
155 | #define ISCSI_CONN_STARTED 1 | ||
156 | #define ISCSI_CONN_STOPPED 2 | ||
157 | #define ISCSI_CONN_CLEANUP_WAIT 3 | ||
158 | |||
159 | struct iscsi_cls_conn { | 152 | struct iscsi_cls_conn { |
160 | struct list_head conn_list; /* item in connlist */ | 153 | struct list_head conn_list; /* item in connlist */ |
161 | void *dd_data; /* LLD private data */ | 154 | void *dd_data; /* LLD private data */ |
@@ -169,19 +162,21 @@ struct iscsi_cls_conn { | |||
169 | #define iscsi_dev_to_conn(_dev) \ | 162 | #define iscsi_dev_to_conn(_dev) \ |
170 | container_of(_dev, struct iscsi_cls_conn, dev) | 163 | container_of(_dev, struct iscsi_cls_conn, dev) |
171 | 164 | ||
172 | /* Session's states */ | 165 | #define iscsi_conn_to_session(_conn) \ |
173 | #define ISCSI_STATE_FREE 1 | 166 | iscsi_dev_to_session(_conn->dev.parent) |
174 | #define ISCSI_STATE_LOGGED_IN 2 | 167 | |
175 | #define ISCSI_STATE_FAILED 3 | 168 | /* iscsi class session state */ |
176 | #define ISCSI_STATE_TERMINATE 4 | 169 | enum { |
177 | #define ISCSI_STATE_IN_RECOVERY 5 | 170 | ISCSI_SESSION_LOGGED_IN, |
178 | #define ISCSI_STATE_RECOVERY_FAILED 6 | 171 | ISCSI_SESSION_FAILED, |
179 | #define ISCSI_STATE_LOGGING_OUT 7 | 172 | ISCSI_SESSION_FREE, |
173 | }; | ||
180 | 174 | ||
181 | struct iscsi_cls_session { | 175 | struct iscsi_cls_session { |
182 | struct list_head sess_list; /* item in session_list */ | 176 | struct list_head sess_list; /* item in session_list */ |
183 | struct list_head host_list; | 177 | struct list_head host_list; |
184 | struct iscsi_transport *transport; | 178 | struct iscsi_transport *transport; |
179 | spinlock_t lock; | ||
185 | 180 | ||
186 | /* recovery fields */ | 181 | /* recovery fields */ |
187 | int recovery_tmo; | 182 | int recovery_tmo; |
@@ -190,6 +185,7 @@ struct iscsi_cls_session { | |||
190 | 185 | ||
191 | int target_id; | 186 | int target_id; |
192 | 187 | ||
188 | int state; | ||
193 | int sid; /* session id */ | 189 | int sid; /* session id */ |
194 | void *dd_data; /* LLD private data */ | 190 | void *dd_data; /* LLD private data */ |
195 | struct device dev; /* sysfs transport/container device */ | 191 | struct device dev; /* sysfs transport/container device */ |
@@ -214,6 +210,7 @@ struct iscsi_host { | |||
214 | /* | 210 | /* |
215 | * session and connection functions that can be used by HW iSCSI LLDs | 211 | * session and connection functions that can be used by HW iSCSI LLDs |
216 | */ | 212 | */ |
213 | extern int iscsi_session_chkready(struct iscsi_cls_session *session); | ||
217 | extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost, | 214 | extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost, |
218 | struct iscsi_transport *transport); | 215 | struct iscsi_transport *transport); |
219 | extern int iscsi_add_session(struct iscsi_cls_session *session, | 216 | extern int iscsi_add_session(struct iscsi_cls_session *session, |