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 /drivers/scsi | |
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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libiscsi.c | 41 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 107 |
2 files changed, 130 insertions, 18 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; |