aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-04-06 22:13:39 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-04-14 15:05:09 -0400
commit30a6c65236f9d26e3325cae468f330b833a3878c (patch)
tree355519ccc74d4b3984c06d7dcb5852282e47c845
parentfd7255f51a13ea915099c7e488001dfbbeb05104 (diff)
[SCSI] iscsi: fix up iscsi eh
The current iscsi_tcp eh is not nicely setup for dm-multipath and performs some extra task management functions when they are not needed. The attached patch: - Fixes the TMF issues. If a session is rebuilt then we do not send aborts. - Fixes the problem where if the host reset fired, we would return SUCCESS even though we had not really done anything yet. This ends up causing problem with scsi_error.c's TUR. - If someone has turned on the userspace nop daemon code to try and detect network problems before the scsi command timeout we can now drop and clean up the session before the scsi command timesout and fires the eh speeding up the time it takes for a command to go from one patch to another. For network problems we fail the command with DID_BUS_BUSY so if failfast is set scsi_decide_disposition fails the command up to dm for it to try on another path. - And we had to add some basic iscsi session block code. Previously if we were trying to repair a session we would retrun a MLQUEUE code in the queuecommand. This worked but it was not the most efficient or pretty thing to do since it would take a while to relogin to the target. For iscsi_tcp/open-iscsi a lot of the iscsi error handler is in userspace the block code is pretty bare. We will be adding to that for qla4xxx. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/iscsi_tcp.c659
-rw-r--r--drivers/scsi/iscsi_tcp.h3
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c152
-rw-r--r--include/scsi/iscsi_if.h2
-rw-r--r--include/scsi/scsi_transport_iscsi.h19
5 files changed, 561 insertions, 274 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 6e510f3cfbf6..aca3e23b1b9e 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -82,6 +82,9 @@ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
82/* global data */ 82/* global data */
83static kmem_cache_t *taskcache; 83static kmem_cache_t *taskcache;
84 84
85#define session_to_cls(_sess) \
86 hostdata_session(_sess->host->hostdata)
87
85static inline void 88static inline void
86iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) 89iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
87{ 90{
@@ -230,17 +233,19 @@ iscsi_hdr_extract(struct iscsi_conn *conn)
230 return 0; 233 return 0;
231} 234}
232 235
233static inline void 236/*
234iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 237 * must be called with session lock
238 */
239static void
240__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
235{ 241{
236 struct scsi_cmnd *sc = ctask->sc;
237 struct iscsi_session *session = conn->session; 242 struct iscsi_session *session = conn->session;
243 struct scsi_cmnd *sc;
238 244
239 spin_lock(&session->lock); 245 sc = ctask->sc;
240 if (unlikely(!sc)) { 246 if (unlikely(!sc))
241 spin_unlock(&session->lock);
242 return; 247 return;
243 } 248
244 if (sc->sc_data_direction == DMA_TO_DEVICE) { 249 if (sc->sc_data_direction == DMA_TO_DEVICE) {
245 struct iscsi_data_task *dtask, *n; 250 struct iscsi_data_task *dtask, *n;
246 /* WRITE: cleanup Data-Out's if any */ 251 /* WRITE: cleanup Data-Out's if any */
@@ -252,7 +257,20 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
252 ctask->xmstate = XMSTATE_IDLE; 257 ctask->xmstate = XMSTATE_IDLE;
253 ctask->r2t = NULL; 258 ctask->r2t = NULL;
254 ctask->sc = NULL; 259 ctask->sc = NULL;
260 list_del(&ctask->running);
261
255 __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); 262 __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
263
264 sc->scsi_done(sc);
265}
266
267static void
268iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
269{
270 struct iscsi_session *session = conn->session;
271
272 spin_lock(&session->lock);
273 __iscsi_ctask_cleanup(conn, ctask);
256 spin_unlock(&session->lock); 274 spin_unlock(&session->lock);
257} 275}
258 276
@@ -311,7 +329,6 @@ out:
311 (long)sc, sc->result, ctask->itt); 329 (long)sc, sc->result, ctask->itt);
312 conn->scsirsp_pdus_cnt++; 330 conn->scsirsp_pdus_cnt++;
313 iscsi_ctask_cleanup(conn, ctask); 331 iscsi_ctask_cleanup(conn, ctask);
314 sc->scsi_done(sc);
315 return rc; 332 return rc;
316} 333}
317 334
@@ -395,6 +412,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
395 412
396 dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); 413 dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
397 BUG_ON(!dtask); 414 BUG_ON(!dtask);
415 INIT_LIST_HEAD(&dtask->item);
398 hdr = &dtask->hdr; 416 hdr = &dtask->hdr;
399 memset(hdr, 0, sizeof(struct iscsi_data)); 417 memset(hdr, 0, sizeof(struct iscsi_data));
400 hdr->ttt = r2t->ttt; 418 hdr->ttt = r2t->ttt;
@@ -710,8 +728,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
710 conn->tmfrsp_pdus_cnt++; 728 conn->tmfrsp_pdus_cnt++;
711 spin_lock(&session->lock); 729 spin_lock(&session->lock);
712 if (conn->tmabort_state == TMABORT_INITIAL) { 730 if (conn->tmabort_state == TMABORT_INITIAL) {
713 __kfifo_put(session->mgmtpool.queue,
714 (void*)&mtask, sizeof(void*));
715 conn->tmabort_state = 731 conn->tmabort_state =
716 ((struct iscsi_tm_rsp *)hdr)-> 732 ((struct iscsi_tm_rsp *)hdr)->
717 response == ISCSI_TMF_RSP_COMPLETE ? 733 response == ISCSI_TMF_RSP_COMPLETE ?
@@ -986,7 +1002,6 @@ done:
986 (long)sc, sc->result, ctask->itt); 1002 (long)sc, sc->result, ctask->itt);
987 conn->scsirsp_pdus_cnt++; 1003 conn->scsirsp_pdus_cnt++;
988 iscsi_ctask_cleanup(conn, ctask); 1004 iscsi_ctask_cleanup(conn, ctask);
989 sc->scsi_done(sc);
990 } 1005 }
991 1006
992 return rc; 1007 return rc;
@@ -1460,6 +1475,7 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1460 1475
1461 dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); 1476 dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
1462 BUG_ON(!dtask); 1477 BUG_ON(!dtask);
1478 INIT_LIST_HEAD(&dtask->item);
1463 hdr = &dtask->hdr; 1479 hdr = &dtask->hdr;
1464 memset(hdr, 0, sizeof(struct iscsi_data)); 1480 memset(hdr, 0, sizeof(struct iscsi_data));
1465 hdr->ttt = r2t->ttt; 1481 hdr->ttt = r2t->ttt;
@@ -1506,6 +1522,7 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1506 1522
1507 dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); 1523 dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
1508 BUG_ON(!dtask); 1524 BUG_ON(!dtask);
1525 INIT_LIST_HEAD(&dtask->item);
1509 hdr = &dtask->hdr; 1526 hdr = &dtask->hdr;
1510 memset(hdr, 0, sizeof(struct iscsi_data)); 1527 memset(hdr, 0, sizeof(struct iscsi_data));
1511 hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); 1528 hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
@@ -1550,6 +1567,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1550 1567
1551 BUG_ON(__kfifo_len(ctask->r2tqueue)); 1568 BUG_ON(__kfifo_len(ctask->r2tqueue));
1552 1569
1570 INIT_LIST_HEAD(&ctask->running);
1553 ctask->sc = sc; 1571 ctask->sc = sc;
1554 ctask->conn = conn; 1572 ctask->conn = conn;
1555 ctask->hdr.opcode = ISCSI_OP_SCSI_CMD; 1573 ctask->hdr.opcode = ISCSI_OP_SCSI_CMD;
@@ -1680,7 +1698,7 @@ iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1680 if (mtask->data_count) 1698 if (mtask->data_count)
1681 mtask->xmstate |= XMSTATE_IMM_DATA; 1699 mtask->xmstate |= XMSTATE_IMM_DATA;
1682 if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && 1700 if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
1683 conn->stop_stage != STOP_CONN_RECOVER && 1701 conn->stop_stage != STOP_CONN_RECOVER &&
1684 conn->hdrdgst_en) 1702 conn->hdrdgst_en)
1685 iscsi_hdr_digest(conn, &mtask->headbuf, 1703 iscsi_hdr_digest(conn, &mtask->headbuf,
1686 (u8*)mtask->hdrext); 1704 (u8*)mtask->hdrext);
@@ -2226,6 +2244,7 @@ iscsi_data_xmit(struct iscsi_conn *conn)
2226 /* process command queue */ 2244 /* process command queue */
2227 while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, 2245 while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
2228 sizeof(void*))) { 2246 sizeof(void*))) {
2247 list_add_tail(&conn->ctask->running, &conn->run_list);
2229 if (iscsi_ctask_xmit(conn, conn->ctask)) 2248 if (iscsi_ctask_xmit(conn, conn->ctask))
2230 goto again; 2249 goto again;
2231 } 2250 }
@@ -2277,11 +2296,14 @@ iscsi_xmitworker(void *data)
2277 mutex_unlock(&conn->xmitmutex); 2296 mutex_unlock(&conn->xmitmutex);
2278} 2297}
2279 2298
2280#define FAILURE_BAD_HOST 1 2299enum {
2281#define FAILURE_SESSION_FAILED 2 2300 FAILURE_BAD_HOST = 1,
2282#define FAILURE_SESSION_FREED 3 2301 FAILURE_SESSION_FAILED,
2283#define FAILURE_WINDOW_CLOSED 4 2302 FAILURE_SESSION_FREED,
2284#define FAILURE_SESSION_TERMINATE 5 2303 FAILURE_WINDOW_CLOSED,
2304 FAILURE_SESSION_TERMINATE,
2305 FAILURE_SESSION_RECOVERY_TIMEOUT,
2306};
2285 2307
2286static int 2308static int
2287iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) 2309iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
@@ -2297,12 +2319,14 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
2297 2319
2298 host = sc->device->host; 2320 host = sc->device->host;
2299 session = iscsi_hostdata(host->hostdata); 2321 session = iscsi_hostdata(host->hostdata);
2300 BUG_ON(host != session->host);
2301 2322
2302 spin_lock(&session->lock); 2323 spin_lock(&session->lock);
2303 2324
2304 if (session->state != ISCSI_STATE_LOGGED_IN) { 2325 if (session->state != ISCSI_STATE_LOGGED_IN) {
2305 if (session->state == ISCSI_STATE_FAILED) { 2326 if (session->recovery_failed) {
2327 reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
2328 goto fault;
2329 } else if (session->state == ISCSI_STATE_FAILED) {
2306 reason = FAILURE_SESSION_FAILED; 2330 reason = FAILURE_SESSION_FAILED;
2307 goto reject; 2331 goto reject;
2308 } else if (session->state == ISCSI_STATE_TERMINATE) { 2332 } else if (session->state == ISCSI_STATE_TERMINATE) {
@@ -2350,11 +2374,6 @@ fault:
2350 spin_unlock(&session->lock); 2374 spin_unlock(&session->lock);
2351 printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n", 2375 printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n",
2352 sc->cmnd[0], reason); 2376 sc->cmnd[0], reason);
2353 sc->sense_buffer[0] = 0x70;
2354 sc->sense_buffer[2] = NOT_READY;
2355 sc->sense_buffer[7] = 0x6;
2356 sc->sense_buffer[12] = 0x08;
2357 sc->sense_buffer[13] = 0x00;
2358 sc->result = (DID_NO_CONNECT << 16); 2377 sc->result = (DID_NO_CONNECT << 16);
2359 sc->resid = sc->request_bufflen; 2378 sc->resid = sc->request_bufflen;
2360 sc->scsi_done(sc); 2379 sc->scsi_done(sc);
@@ -2445,6 +2464,7 @@ iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
2445 conn->id = conn_idx; 2464 conn->id = conn_idx;
2446 conn->exp_statsn = 0; 2465 conn->exp_statsn = 0;
2447 conn->tmabort_state = TMABORT_INITIAL; 2466 conn->tmabort_state = TMABORT_INITIAL;
2467 INIT_LIST_HEAD(&conn->run_list);
2448 2468
2449 /* initial operational parameters */ 2469 /* initial operational parameters */
2450 conn->hdr_size = sizeof(struct iscsi_hdr); 2470 conn->hdr_size = sizeof(struct iscsi_hdr);
@@ -2701,6 +2721,22 @@ iscsi_conn_bind(struct iscsi_cls_session *cls_session,
2701 return 0; 2721 return 0;
2702} 2722}
2703 2723
2724static void
2725iscsi_session_recovery_timedout(struct iscsi_cls_session *csession)
2726{
2727 struct Scsi_Host *shost = iscsi_session_to_shost(csession);
2728 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
2729 struct iscsi_conn *conn = session->leadconn;
2730
2731 spin_lock_bh(&session->lock);
2732 if (session->state != ISCSI_STATE_LOGGED_IN) {
2733 session->recovery_failed = 1;
2734 if (conn)
2735 wake_up(&conn->ehwait);
2736 }
2737 spin_unlock_bh(&session->lock);
2738}
2739
2704static int 2740static int
2705iscsi_conn_start(struct iscsi_cls_conn *cls_conn) 2741iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
2706{ 2742{
@@ -2716,7 +2752,6 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
2716 } 2752 }
2717 2753
2718 sk = conn->sock->sk; 2754 sk = conn->sock->sk;
2719
2720 write_lock_bh(&sk->sk_callback_lock); 2755 write_lock_bh(&sk->sk_callback_lock);
2721 spin_lock_bh(&session->lock); 2756 spin_lock_bh(&session->lock);
2722 conn->c_stage = ISCSI_CONN_STARTED; 2757 conn->c_stage = ISCSI_CONN_STARTED;
@@ -2732,8 +2767,13 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
2732 conn->stop_stage = 0; 2767 conn->stop_stage = 0;
2733 conn->tmabort_state = TMABORT_INITIAL; 2768 conn->tmabort_state = TMABORT_INITIAL;
2734 session->age++; 2769 session->age++;
2770 session->recovery_failed = 0;
2771 spin_unlock_bh(&session->lock);
2772 write_unlock_bh(&sk->sk_callback_lock);
2773
2774 iscsi_unblock_session(session_to_cls(session));
2735 wake_up(&conn->ehwait); 2775 wake_up(&conn->ehwait);
2736 break; 2776 return 0;
2737 case STOP_CONN_TERM: 2777 case STOP_CONN_TERM:
2738 session->conn_cnt++; 2778 session->conn_cnt++;
2739 conn->stop_stage = 0; 2779 conn->stop_stage = 0;
@@ -2752,105 +2792,199 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
2752 return 0; 2792 return 0;
2753} 2793}
2754 2794
2755static void 2795static int
2756iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) 2796iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
2757{ 2797{
2758 struct iscsi_conn *conn = cls_conn->dd_data; 2798 struct iscsi_conn *conn = ctask->conn;
2759 struct iscsi_session *session = conn->session; 2799 struct iscsi_session *session = conn->session;
2800 struct iscsi_mgmt_task *mtask;
2801
2802 if (!ctask->mtask)
2803 return -EINVAL;
2804
2805 while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*))) {
2806 if (mtask == ctask->mtask)
2807 break;
2808 __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
2809 }
2810
2811 __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
2812 sizeof(void*));
2813 ctask->mtask = NULL;
2814 return 0;
2815}
2816
2817static void
2818fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, int err)
2819{
2820 struct iscsi_r2t_info *r2t;
2821 struct scsi_cmnd *sc;
2822
2823 /* flush ctask's r2t queues */
2824 while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
2825 __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
2826
2827 iscsi_ctask_mtask_cleanup(ctask);
2828
2829 sc = ctask->sc;
2830 if (!sc)
2831 return;
2832
2833 sc->result = err;
2834 sc->resid = sc->request_bufflen;
2835
2836 __iscsi_ctask_cleanup(conn, ctask);
2837}
2838
2839/* Fail commands. Mutex and session lock held */
2840static void
2841fail_all_commands(struct iscsi_session *session, struct iscsi_conn *conn)
2842{
2843 struct iscsi_cmd_task *ctask, *tmp;
2844
2845 /* flush pending */
2846 while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
2847 debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
2848 ctask->itt);
2849 fail_command(conn, ctask, DID_BUS_BUSY << 16);
2850 }
2851
2852 /* fail running */
2853 list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
2854 debug_scsi("failing in progress sc %p itt 0x%x\n",
2855 ctask->sc, ctask->itt);
2856 fail_command(conn, ctask, DID_BUS_BUSY << 16);
2857 }
2858
2859 conn->ctask = NULL;
2860}
2861
2862static void
2863flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
2864{
2865 struct iscsi_mgmt_task *mtask;
2866
2867 /* TODO: handle running pdus */
2868 while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
2869 __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
2870 if (mtask == conn->login_mtask)
2871 continue;
2872 __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
2873 sizeof(void*));
2874 }
2875
2876 if (conn->mtask && conn->mtask != conn->login_mtask)
2877 __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
2878 sizeof(void*));
2879 conn->mtask = NULL;
2880}
2881
2882static void
2883iscsi_suspend_conn_rx(struct iscsi_conn *conn)
2884{
2760 struct sock *sk; 2885 struct sock *sk;
2761 unsigned long flags;
2762 2886
2763 BUG_ON(!conn->sock); 2887 BUG_ON(!conn->sock);
2764 sk = conn->sock->sk; 2888 sk = conn->sock->sk;
2765 write_lock_bh(&sk->sk_callback_lock); 2889 write_lock_bh(&sk->sk_callback_lock);
2766 set_bit(SUSPEND_BIT, &conn->suspend_rx); 2890 set_bit(SUSPEND_BIT, &conn->suspend_rx);
2767 write_unlock_bh(&sk->sk_callback_lock); 2891 write_unlock_bh(&sk->sk_callback_lock);
2892}
2768 2893
2769 mutex_lock(&conn->xmitmutex); 2894static void
2770 2895iscsi_start_session_recovery(struct iscsi_session *session,
2771 spin_lock_irqsave(session->host->host_lock, flags); 2896 struct iscsi_conn *conn, int flag)
2772 spin_lock(&session->lock); 2897{
2898 spin_lock_bh(&session->lock);
2899 if (conn->stop_stage == STOP_CONN_RECOVER ||
2900 conn->stop_stage == STOP_CONN_TERM) {
2901 spin_unlock_bh(&session->lock);
2902 return;
2903 }
2773 conn->stop_stage = flag; 2904 conn->stop_stage = flag;
2905 spin_unlock_bh(&session->lock);
2906
2907 iscsi_suspend_conn_rx(conn);
2908
2909 mutex_lock(&conn->xmitmutex);
2910 spin_lock_bh(&session->lock);
2774 conn->c_stage = ISCSI_CONN_STOPPED; 2911 conn->c_stage = ISCSI_CONN_STOPPED;
2775 set_bit(SUSPEND_BIT, &conn->suspend_tx); 2912 set_bit(SUSPEND_BIT, &conn->suspend_tx);
2776 2913
2777 if (flag != STOP_CONN_SUSPEND) 2914 session->conn_cnt--;
2778 session->conn_cnt--;
2779
2780 if (session->conn_cnt == 0 || session->leadconn == conn) 2915 if (session->conn_cnt == 0 || session->leadconn == conn)
2781 session->state = ISCSI_STATE_FAILED; 2916 session->state = ISCSI_STATE_FAILED;
2782 2917
2783 spin_unlock(&session->lock); 2918 spin_unlock_bh(&session->lock);
2784 spin_unlock_irqrestore(session->host->host_lock, flags);
2785
2786 if (flag == STOP_CONN_TERM || flag == STOP_CONN_RECOVER) {
2787 struct iscsi_cmd_task *ctask;
2788 struct iscsi_mgmt_task *mtask;
2789 2919
2790 /* 2920 /*
2791 * Socket must go now. 2921 * Socket must go now.
2792 */ 2922 */
2793 sock_hold(conn->sock->sk); 2923 sock_hold(conn->sock->sk);
2794 iscsi_conn_restore_callbacks(conn); 2924 iscsi_conn_restore_callbacks(conn);
2795 sock_put(conn->sock->sk); 2925 sock_put(conn->sock->sk);
2796 2926
2797 /* 2927 /*
2798 * flush xmit queues. 2928 * flush queues.
2799 */ 2929 */
2800 spin_lock_bh(&session->lock); 2930 spin_lock_bh(&session->lock);
2801 while (__kfifo_get(conn->writequeue, (void*)&ctask, 2931 fail_all_commands(session, conn);
2802 sizeof(void*)) || 2932 flush_control_queues(session, conn);
2803 __kfifo_get(conn->xmitqueue, (void*)&ctask, 2933 spin_unlock_bh(&session->lock);
2804 sizeof(void*))) {
2805 struct iscsi_r2t_info *r2t;
2806
2807 /*
2808 * flush ctask's r2t queues
2809 */
2810 while (__kfifo_get(ctask->r2tqueue, (void*)&r2t,
2811 sizeof(void*)))
2812 __kfifo_put(ctask->r2tpool.queue, (void*)&r2t,
2813 sizeof(void*));
2814 2934
2815 spin_unlock_bh(&session->lock); 2935 /*
2816 local_bh_disable(); 2936 * release socket only after we stopped data_xmit()
2817 iscsi_ctask_cleanup(conn, ctask); 2937 * activity and flushed all outstandings
2818 local_bh_enable(); 2938 */
2819 spin_lock_bh(&session->lock); 2939 sock_release(conn->sock);
2820 } 2940 conn->sock = NULL;
2821 conn->ctask = NULL;
2822 while (__kfifo_get(conn->immqueue, (void*)&mtask,
2823 sizeof(void*)) ||
2824 __kfifo_get(conn->mgmtqueue, (void*)&mtask,
2825 sizeof(void*))) {
2826 __kfifo_put(session->mgmtpool.queue,
2827 (void*)&mtask, sizeof(void*));
2828 }
2829 conn->mtask = NULL;
2830 spin_unlock_bh(&session->lock);
2831 2941
2832 /* 2942 /*
2833 * release socket only after we stopped data_xmit() 2943 * for connection level recovery we should not calculate
2834 * activity and flushed all outstandings 2944 * header digest. conn->hdr_size used for optimization
2835 */ 2945 * in hdr_extract() and will be re-negotiated at
2836 sock_release(conn->sock); 2946 * set_param() time.
2837 conn->sock = NULL; 2947 */
2948 if (flag == STOP_CONN_RECOVER) {
2949 conn->hdr_size = sizeof(struct iscsi_hdr);
2950 conn->hdrdgst_en = 0;
2951 conn->datadgst_en = 0;
2838 2952
2839 /* 2953 if (session->state == ISCSI_STATE_FAILED)
2840 * for connection level recovery we should not calculate 2954 iscsi_block_session(session_to_cls(session));
2841 * header digest. conn->hdr_size used for optimization
2842 * in hdr_extract() and will be re-negotiated at
2843 * set_param() time.
2844 */
2845 if (flag == STOP_CONN_RECOVER) {
2846 conn->hdr_size = sizeof(struct iscsi_hdr);
2847 conn->hdrdgst_en = 0;
2848 conn->datadgst_en = 0;
2849 }
2850 } 2955 }
2851 mutex_unlock(&conn->xmitmutex); 2956 mutex_unlock(&conn->xmitmutex);
2852} 2957}
2853 2958
2959static void
2960iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
2961{
2962 struct iscsi_conn *conn = cls_conn->dd_data;
2963 struct iscsi_session *session = conn->session;
2964
2965 switch (flag) {
2966 case STOP_CONN_RECOVER:
2967 case STOP_CONN_TERM:
2968 iscsi_start_session_recovery(session, conn, flag);
2969 return;
2970 case STOP_CONN_SUSPEND:
2971 iscsi_suspend_conn_rx(conn);
2972
2973 mutex_lock(&conn->xmitmutex);
2974 spin_lock_bh(&session->lock);
2975
2976 conn->stop_stage = flag;
2977 conn->c_stage = ISCSI_CONN_STOPPED;
2978 set_bit(SUSPEND_BIT, &conn->suspend_tx);
2979
2980 spin_unlock_bh(&session->lock);
2981 mutex_unlock(&conn->xmitmutex);
2982 break;
2983 default:
2984 printk(KERN_ERR "invalid stop flag %d\n", flag);
2985 }
2986}
2987
2854static int 2988static int
2855iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, 2989iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
2856 char *data, uint32_t data_size) 2990 char *data, uint32_t data_size)
@@ -2940,23 +3074,54 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
2940static int 3074static int
2941iscsi_eh_host_reset(struct scsi_cmnd *sc) 3075iscsi_eh_host_reset(struct scsi_cmnd *sc)
2942{ 3076{
2943 struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; 3077 struct Scsi_Host *host = sc->device->host;
2944 struct iscsi_conn *conn = ctask->conn; 3078 struct iscsi_session *session = iscsi_hostdata(host->hostdata);
2945 struct iscsi_session *session = conn->session; 3079 struct iscsi_conn *conn = session->leadconn;
3080 int fail_session = 0;
2946 3081
2947 spin_lock_bh(&session->lock); 3082 spin_lock_bh(&session->lock);
2948 if (session->state == ISCSI_STATE_TERMINATE) { 3083 if (session->state == ISCSI_STATE_TERMINATE) {
3084failed:
2949 debug_scsi("failing host reset: session terminated " 3085 debug_scsi("failing host reset: session terminated "
2950 "[CID %d age %d]", conn->id, session->age); 3086 "[CID %d age %d]", conn->id, session->age);
2951 spin_unlock_bh(&session->lock); 3087 spin_unlock_bh(&session->lock);
2952 return FAILED; 3088 return FAILED;
2953 } 3089 }
3090
3091 if (sc->SCp.phase == session->age) {
3092 debug_scsi("failing connection CID %d due to SCSI host reset",
3093 conn->id);
3094 fail_session = 1;
3095 }
2954 spin_unlock_bh(&session->lock); 3096 spin_unlock_bh(&session->lock);
2955 3097
2956 debug_scsi("failing connection CID %d due to SCSI host reset " 3098 /*
2957 "[itt 0x%x age %d]", conn->id, ctask->itt, 3099 * we drop the lock here but the leadconn cannot be destoyed while
2958 session->age); 3100 * we are in the scsi eh
2959 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); 3101 */
3102 if (fail_session) {
3103 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
3104 /*
3105 * if userspace cannot respond then we must kick this off
3106 * here for it
3107 */
3108 iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER);
3109 }
3110
3111 debug_scsi("iscsi_eh_host_reset wait for relogin\n");
3112 wait_event_interruptible(conn->ehwait,
3113 session->state == ISCSI_STATE_TERMINATE ||
3114 session->state == ISCSI_STATE_LOGGED_IN ||
3115 session->recovery_failed);
3116 if (signal_pending(current))
3117 flush_signals(current);
3118
3119 spin_lock_bh(&session->lock);
3120 if (session->state == ISCSI_STATE_LOGGED_IN)
3121 printk(KERN_INFO "host reset succeeded\n");
3122 else
3123 goto failed;
3124 spin_unlock_bh(&session->lock);
2960 3125
2961 return SUCCESS; 3126 return SUCCESS;
2962} 3127}
@@ -2970,8 +3135,6 @@ iscsi_tmabort_timedout(unsigned long data)
2970 3135
2971 spin_lock(&session->lock); 3136 spin_lock(&session->lock);
2972 if (conn->tmabort_state == TMABORT_INITIAL) { 3137 if (conn->tmabort_state == TMABORT_INITIAL) {
2973 __kfifo_put(session->mgmtpool.queue,
2974 (void*)&ctask->mtask, sizeof(void*));
2975 conn->tmabort_state = TMABORT_TIMEDOUT; 3138 conn->tmabort_state = TMABORT_TIMEDOUT;
2976 debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n", 3139 debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n",
2977 (long)ctask->sc, ctask->itt); 3140 (long)ctask->sc, ctask->itt);
@@ -2981,186 +3144,163 @@ iscsi_tmabort_timedout(unsigned long data)
2981 spin_unlock(&session->lock); 3144 spin_unlock(&session->lock);
2982} 3145}
2983 3146
3147/* must be called with the mutex lock */
2984static int 3148static int
2985iscsi_eh_abort(struct scsi_cmnd *sc) 3149iscsi_exec_abort_task(struct scsi_cmnd *sc, struct iscsi_cmd_task *ctask)
2986{ 3150{
2987 int rc;
2988 struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
2989 struct iscsi_conn *conn = ctask->conn; 3151 struct iscsi_conn *conn = ctask->conn;
2990 struct iscsi_session *session = conn->session; 3152 struct iscsi_session *session = conn->session;
2991 3153 struct iscsi_tm *hdr = &conn->tmhdr;
2992 conn->eh_abort_cnt++; 3154 int rc;
2993 debug_scsi("aborting [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
2994 3155
2995 /* 3156 /*
2996 * two cases for ERL=0 here: 3157 * ctask timed out but session is OK requests must be serialized.
2997 *
2998 * 1) connection-level failure;
2999 * 2) recovery due protocol error;
3000 */ 3158 */
3001 mutex_lock(&conn->xmitmutex); 3159 memset(hdr, 0, sizeof(struct iscsi_tm));
3002 spin_lock_bh(&session->lock); 3160 hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
3003 if (session->state != ISCSI_STATE_LOGGED_IN) { 3161 hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
3004 if (session->state == ISCSI_STATE_TERMINATE) { 3162 hdr->flags |= ISCSI_FLAG_CMD_FINAL;
3005 spin_unlock_bh(&session->lock); 3163 memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
3006 mutex_unlock(&conn->xmitmutex); 3164 hdr->rtt = ctask->hdr.itt;
3007 goto failed; 3165 hdr->refcmdsn = ctask->hdr.cmdsn;
3008 }
3009 spin_unlock_bh(&session->lock);
3010 } else {
3011 struct iscsi_tm *hdr = &conn->tmhdr;
3012 3166
3013 /* 3167 rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
3014 * Still LOGGED_IN... 3168 NULL, 0);
3015 */ 3169 if (rc) {
3170 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
3171 debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc);
3172 return rc;
3173 }
3016 3174
3017 if (!ctask->sc || sc->SCp.phase != session->age) { 3175 debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
3018 /*
3019 * 1) ctask completed before time out. But session
3020 * is still ok => Happy Retry.
3021 * 2) session was re-open during time out of ctask.
3022 */
3023 spin_unlock_bh(&session->lock);
3024 mutex_unlock(&conn->xmitmutex);
3025 goto success;
3026 }
3027 conn->tmabort_state = TMABORT_INITIAL;
3028 spin_unlock_bh(&session->lock);
3029 3176
3030 /* 3177 spin_lock_bh(&session->lock);
3031 * ctask timed out but session is OK 3178 ctask->mtask = (struct iscsi_mgmt_task *)
3032 * ERL=0 requires task mgmt abort to be issued on each 3179 session->mgmt_cmds[(hdr->itt & ITT_MASK) -
3033 * failed command. requests must be serialized. 3180 ISCSI_MGMT_ITT_OFFSET];
3034 */ 3181
3035 memset(hdr, 0, sizeof(struct iscsi_tm)); 3182 if (conn->tmabort_state == TMABORT_INITIAL) {
3036 hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; 3183 conn->tmfcmd_pdus_cnt++;
3037 hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; 3184 conn->tmabort_timer.expires = 10*HZ + jiffies;
3038 hdr->flags |= ISCSI_FLAG_CMD_FINAL; 3185 conn->tmabort_timer.function = iscsi_tmabort_timedout;
3039 memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); 3186 conn->tmabort_timer.data = (unsigned long)ctask;
3040 hdr->rtt = ctask->hdr.itt; 3187 add_timer(&conn->tmabort_timer);
3041 hdr->refcmdsn = ctask->hdr.cmdsn; 3188 debug_scsi("abort set timeout [itt 0x%x]", ctask->itt);
3042
3043 rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
3044 NULL, 0);
3045 if (rc) {
3046 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
3047 debug_scsi("abort sent failure [itt 0x%x]", ctask->itt);
3048 } else {
3049 struct iscsi_r2t_info *r2t;
3050
3051 /*
3052 * TMF abort vs. TMF response race logic
3053 */
3054 spin_lock_bh(&session->lock);
3055 ctask->mtask = (struct iscsi_mgmt_task *)
3056 session->mgmt_cmds[(hdr->itt & ITT_MASK) -
3057 ISCSI_MGMT_ITT_OFFSET];
3058 /*
3059 * have to flush r2tqueue to avoid r2t leaks
3060 */
3061 while (__kfifo_get(ctask->r2tqueue, (void*)&r2t,
3062 sizeof(void*))) {
3063 __kfifo_put(ctask->r2tpool.queue, (void*)&r2t,
3064 sizeof(void*));
3065 }
3066 if (conn->tmabort_state == TMABORT_INITIAL) {
3067 conn->tmfcmd_pdus_cnt++;
3068 conn->tmabort_timer.expires = 3*HZ + jiffies;
3069 conn->tmabort_timer.function =
3070 iscsi_tmabort_timedout;
3071 conn->tmabort_timer.data = (unsigned long)ctask;
3072 add_timer(&conn->tmabort_timer);
3073 debug_scsi("abort sent [itt 0x%x]", ctask->itt);
3074 } else {
3075 if (!ctask->sc ||
3076 conn->tmabort_state == TMABORT_SUCCESS) {
3077 conn->tmabort_state = TMABORT_INITIAL;
3078 spin_unlock_bh(&session->lock);
3079 mutex_unlock(&conn->xmitmutex);
3080 goto success;
3081 }
3082 conn->tmabort_state = TMABORT_INITIAL;
3083 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
3084 }
3085 spin_unlock_bh(&session->lock);
3086 }
3087 } 3189 }
3190 spin_unlock_bh(&session->lock);
3088 mutex_unlock(&conn->xmitmutex); 3191 mutex_unlock(&conn->xmitmutex);
3089 3192
3090
3091 /* 3193 /*
3092 * block eh thread until: 3194 * block eh thread until:
3093 * 3195 *
3094 * 1) abort response; 3196 * 1) abort response
3095 * 2) abort timeout; 3197 * 2) abort timeout
3096 * 3) session re-opened; 3198 * 3) session is terminated or restarted or userspace has
3097 * 4) session terminated; 3199 * given up on recovery
3098 */ 3200 */
3099 for (;;) { 3201 wait_event_interruptible(conn->ehwait,
3100 int p_state = session->state; 3202 sc->SCp.phase != session->age ||
3101 3203 session->state != ISCSI_STATE_LOGGED_IN ||
3102 rc = wait_event_interruptible(conn->ehwait, 3204 conn->tmabort_state != TMABORT_INITIAL ||
3103 (p_state == ISCSI_STATE_LOGGED_IN ? 3205 session->recovery_failed);
3104 (session->state == ISCSI_STATE_TERMINATE || 3206 if (signal_pending(current))
3105 conn->tmabort_state != TMABORT_INITIAL) : 3207 flush_signals(current);
3106 (session->state == ISCSI_STATE_TERMINATE || 3208 del_timer_sync(&conn->tmabort_timer);
3107 session->state == ISCSI_STATE_LOGGED_IN)));
3108 if (rc) {
3109 /* shutdown.. */
3110 session->state = ISCSI_STATE_TERMINATE;
3111 goto failed;
3112 }
3113 3209
3114 if (signal_pending(current)) 3210 mutex_lock(&conn->xmitmutex);
3115 flush_signals(current); 3211 return 0;
3212}
3116 3213
3117 if (session->state == ISCSI_STATE_TERMINATE) 3214static int
3118 goto failed; 3215iscsi_eh_abort(struct scsi_cmnd *sc)
3216{
3217 struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
3218 struct iscsi_cmd_task *tmp_ctask;
3219 struct iscsi_conn *conn = ctask->conn;
3220 struct iscsi_session *session = conn->session;
3221 int rc;
3119 3222
3120 spin_lock_bh(&session->lock); 3223 conn->eh_abort_cnt++;
3121 if (sc->SCp.phase == session->age && 3224 debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
3122 (conn->tmabort_state == TMABORT_TIMEDOUT || 3225
3123 conn->tmabort_state == TMABORT_FAILED)) { 3226 mutex_lock(&conn->xmitmutex);
3124 conn->tmabort_state = TMABORT_INITIAL; 3227 spin_lock_bh(&session->lock);
3125 if (!ctask->sc) { 3228
3126 /* 3229 /*
3127 * ctask completed before tmf abort response or 3230 * If we are not logged in or we have started a new session
3128 * time out. 3231 * then let the host reset code handle this
3129 * But session is still ok => Happy Retry. 3232 */
3130 */ 3233 if (session->state != ISCSI_STATE_LOGGED_IN ||
3131 spin_unlock_bh(&session->lock); 3234 sc->SCp.phase != session->age)
3132 break; 3235 goto failed;
3133 } 3236
3134 spin_unlock_bh(&session->lock); 3237 /* ctask completed before time out */
3135 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); 3238 if (!ctask->sc)
3136 continue; 3239 goto success;
3240
3241 /* what should we do here ? */
3242 if (conn->ctask == ctask) {
3243 printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing "
3244 "abort\n", sc, ctask->itt);
3245 goto failed;
3246 }
3247
3248 /* check for the easy pending cmd abort */
3249 while (__kfifo_get(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*))) {
3250 if (tmp_ctask->itt == ctask->itt) {
3251 debug_scsi("found pending task\n");
3252 goto success;
3137 } 3253 }
3254 __kfifo_put(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*));
3255 }
3256
3257 conn->tmabort_state = TMABORT_INITIAL;
3258
3259 spin_unlock_bh(&session->lock);
3260 rc = iscsi_exec_abort_task(sc, ctask);
3261 spin_lock_bh(&session->lock);
3262
3263 iscsi_ctask_mtask_cleanup(ctask);
3264 if (rc || sc->SCp.phase != session->age ||
3265 session->state != ISCSI_STATE_LOGGED_IN)
3266 goto failed;
3267
3268 /* ctask completed before tmf abort response */
3269 if (!ctask->sc) {
3270 debug_scsi("sc completed while abort in progress\n");
3271 goto success;
3272 }
3273
3274 if (conn->tmabort_state != TMABORT_SUCCESS) {
3138 spin_unlock_bh(&session->lock); 3275 spin_unlock_bh(&session->lock);
3139 break; 3276 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
3277 spin_lock_bh(&session->lock);
3278 goto failed;
3140 } 3279 }
3141 3280
3142success: 3281success:
3143 debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); 3282 debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
3144 rc = SUCCESS; 3283 spin_unlock_bh(&session->lock);
3145 goto exit;
3146
3147failed:
3148 debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
3149 rc = FAILED;
3150
3151exit:
3152 del_timer_sync(&conn->tmabort_timer);
3153 3284
3154 mutex_lock(&conn->xmitmutex); 3285 /* clean up task if aborted */
3155 if (conn->sock) { 3286 if (conn->sock) {
3156 struct sock *sk = conn->sock->sk; 3287 struct sock *sk = conn->sock->sk;
3157 3288
3158 write_lock_bh(&sk->sk_callback_lock); 3289 write_lock_bh(&sk->sk_callback_lock);
3159 iscsi_ctask_cleanup(conn, ctask); 3290 spin_lock(&session->lock);
3291 fail_command(conn, ctask, DRIVER_TIMEOUT << 24);
3292 spin_unlock(&session->lock);
3160 write_unlock_bh(&sk->sk_callback_lock); 3293 write_unlock_bh(&sk->sk_callback_lock);
3161 } 3294 }
3162 mutex_unlock(&conn->xmitmutex); 3295 mutex_unlock(&conn->xmitmutex);
3163 return rc; 3296 return SUCCESS;
3297
3298failed:
3299 spin_unlock_bh(&session->lock);
3300 mutex_unlock(&conn->xmitmutex);
3301
3302 debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
3303 return FAILED;
3164} 3304}
3165 3305
3166static int 3306static int
@@ -3359,16 +3499,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
3359 struct iscsi_conn *conn = cls_conn->dd_data; 3499 struct iscsi_conn *conn = cls_conn->dd_data;
3360 struct iscsi_session *session = conn->session; 3500 struct iscsi_session *session = conn->session;
3361 3501
3362 spin_lock_bh(&session->lock);
3363 if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
3364 conn->stop_stage != STOP_CONN_RECOVER) {
3365 printk(KERN_ERR "iscsi_tcp: can not change parameter [%d]\n",
3366 param);
3367 spin_unlock_bh(&session->lock);
3368 return 0;
3369 }
3370 spin_unlock_bh(&session->lock);
3371
3372 switch(param) { 3502 switch(param) {
3373 case ISCSI_PARAM_MAX_RECV_DLENGTH: { 3503 case ISCSI_PARAM_MAX_RECV_DLENGTH: {
3374 char *saveptr = conn->data; 3504 char *saveptr = conn->data;
@@ -3691,6 +3821,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
3691 .stop_conn = iscsi_conn_stop, 3821 .stop_conn = iscsi_conn_stop,
3692 .send_pdu = iscsi_conn_send_pdu, 3822 .send_pdu = iscsi_conn_send_pdu,
3693 .get_stats = iscsi_conn_get_stats, 3823 .get_stats = iscsi_conn_get_stats,
3824 .session_recovery_timedout = iscsi_session_recovery_timedout,
3694}; 3825};
3695 3826
3696static int __init 3827static int __init
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index ba26741ac154..12ef64179b4c 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -159,6 +159,7 @@ struct iscsi_conn {
159 struct kfifo *immqueue; /* immediate xmit queue */ 159 struct kfifo *immqueue; /* immediate xmit queue */
160 struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ 160 struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */
161 struct kfifo *xmitqueue; /* data-path cmd queue */ 161 struct kfifo *xmitqueue; /* data-path cmd queue */
162 struct list_head run_list; /* list of cmds in progress */
162 struct work_struct xmitwork; /* per-conn. xmit workqueue */ 163 struct work_struct xmitwork; /* per-conn. xmit workqueue */
163 struct mutex xmitmutex; /* serializes connection xmit, 164 struct mutex xmitmutex; /* serializes connection xmit,
164 * access to kfifos: * 165 * access to kfifos: *
@@ -228,6 +229,7 @@ struct iscsi_session {
228 * - mgmtpool, * 229 * - mgmtpool, *
229 * - r2tpool */ 230 * - r2tpool */
230 int state; /* session state */ 231 int state; /* session state */
232 int recovery_failed;
231 struct list_head item; 233 struct list_head item;
232 void *auth_client; 234 void *auth_client;
233 int conn_cnt; 235 int conn_cnt;
@@ -310,6 +312,7 @@ struct iscsi_cmd_task {
310 struct iscsi_conn *conn; /* used connection */ 312 struct iscsi_conn *conn; /* used connection */
311 struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ 313 struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */
312 314
315 struct list_head running; /* running cmd list */
313 struct iscsi_r2t_info *r2t; /* in progress R2T */ 316 struct iscsi_r2t_info *r2t; /* in progress R2T */
314 struct iscsi_queue r2tpool; 317 struct iscsi_queue r2tpool;
315 struct kfifo *r2tqueue; 318 struct kfifo *r2tqueue;
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 72a71ebc9d03..e2b67e34d92e 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -31,17 +31,17 @@
31#include <scsi/scsi_transport_iscsi.h> 31#include <scsi/scsi_transport_iscsi.h>
32#include <scsi/iscsi_if.h> 32#include <scsi/iscsi_if.h>
33 33
34#define ISCSI_SESSION_ATTRS 10 34#define ISCSI_SESSION_ATTRS 11
35#define ISCSI_CONN_ATTRS 10 35#define ISCSI_CONN_ATTRS 10
36#define ISCSI_HOST_ATTRS 0
36 37
37struct iscsi_internal { 38struct iscsi_internal {
38 struct scsi_transport_template t; 39 struct scsi_transport_template t;
39 struct iscsi_transport *iscsi_transport; 40 struct iscsi_transport *iscsi_transport;
40 struct list_head list; 41 struct list_head list;
41 struct class_device cdev; 42 struct class_device cdev;
42 /* 43
43 * We do not have any private or other attrs. 44 struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
44 */
45 struct transport_container conn_cont; 45 struct transport_container conn_cont;
46 struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1]; 46 struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
47 struct transport_container session_cont; 47 struct transport_container session_cont;
@@ -114,6 +114,24 @@ static struct attribute_group iscsi_transport_group = {
114 .attrs = iscsi_transport_attrs, 114 .attrs = iscsi_transport_attrs,
115}; 115};
116 116
117static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
118 struct class_device *cdev)
119{
120 struct Scsi_Host *shost = dev_to_shost(dev);
121 struct iscsi_host *ihost = shost->shost_data;
122
123 memset(ihost, 0, sizeof(*ihost));
124 INIT_LIST_HEAD(&ihost->sessions);
125 mutex_init(&ihost->mutex);
126 return 0;
127}
128
129static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
130 "iscsi_host",
131 iscsi_setup_host,
132 NULL,
133 NULL);
134
117static DECLARE_TRANSPORT_CLASS(iscsi_session_class, 135static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
118 "iscsi_session", 136 "iscsi_session",
119 NULL, 137 NULL,
@@ -225,6 +243,54 @@ static int iscsi_is_session_dev(const struct device *dev)
225 return dev->release == iscsi_session_release; 243 return dev->release == iscsi_session_release;
226} 244}
227 245
246static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
247 uint id, uint lun)
248{
249 struct iscsi_host *ihost = shost->shost_data;
250 struct iscsi_cls_session *session;
251
252 mutex_lock(&ihost->mutex);
253 list_for_each_entry(session, &ihost->sessions, host_list) {
254 if ((channel == SCAN_WILD_CARD ||
255 channel == session->channel) &&
256 (id == SCAN_WILD_CARD || id == session->target_id))
257 scsi_scan_target(&session->dev, session->channel,
258 session->target_id, lun, 1);
259 }
260 mutex_unlock(&ihost->mutex);
261
262 return 0;
263}
264
265static void session_recovery_timedout(void *data)
266{
267 struct iscsi_cls_session *session = data;
268
269 dev_printk(KERN_INFO, &session->dev, "session recovery timed out "
270 "after %d secs\n", session->recovery_tmo);
271
272 if (session->transport->session_recovery_timedout)
273 session->transport->session_recovery_timedout(session);
274
275 scsi_target_unblock(&session->dev);
276}
277
278void iscsi_unblock_session(struct iscsi_cls_session *session)
279{
280 if (!cancel_delayed_work(&session->recovery_work))
281 flush_scheduled_work();
282 scsi_target_unblock(&session->dev);
283}
284EXPORT_SYMBOL_GPL(iscsi_unblock_session);
285
286void iscsi_block_session(struct iscsi_cls_session *session)
287{
288 scsi_target_block(&session->dev);
289 schedule_delayed_work(&session->recovery_work,
290 session->recovery_tmo * HZ);
291}
292EXPORT_SYMBOL_GPL(iscsi_block_session);
293
228/** 294/**
229 * iscsi_create_session - create iscsi class session 295 * iscsi_create_session - create iscsi class session
230 * @shost: scsi host 296 * @shost: scsi host
@@ -233,8 +299,10 @@ static int iscsi_is_session_dev(const struct device *dev)
233 * This can be called from a LLD or iscsi_transport. 299 * This can be called from a LLD or iscsi_transport.
234 **/ 300 **/
235struct iscsi_cls_session * 301struct iscsi_cls_session *
236iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) 302iscsi_create_session(struct Scsi_Host *shost,
303 struct iscsi_transport *transport, int channel)
237{ 304{
305 struct iscsi_host *ihost;
238 struct iscsi_cls_session *session; 306 struct iscsi_cls_session *session;
239 int err; 307 int err;
240 308
@@ -246,13 +314,22 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
246 if (!session) 314 if (!session)
247 goto module_put; 315 goto module_put;
248 session->transport = transport; 316 session->transport = transport;
317 session->recovery_tmo = 120;
318 INIT_WORK(&session->recovery_work, session_recovery_timedout, session);
319 INIT_LIST_HEAD(&session->host_list);
320 INIT_LIST_HEAD(&session->sess_list);
249 321
250 if (transport->sessiondata_size) 322 if (transport->sessiondata_size)
251 session->dd_data = &session[1]; 323 session->dd_data = &session[1];
252 324
253 /* this is released in the dev's release function */ 325 /* this is released in the dev's release function */
254 scsi_host_get(shost); 326 scsi_host_get(shost);
327 ihost = shost->shost_data;
328
255 session->sid = iscsi_session_nr++; 329 session->sid = iscsi_session_nr++;
330 session->channel = channel;
331 session->target_id = ihost->next_target_id++;
332
256 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", 333 snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
257 session->sid); 334 session->sid);
258 session->dev.parent = &shost->shost_gendev; 335 session->dev.parent = &shost->shost_gendev;
@@ -265,6 +342,10 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
265 } 342 }
266 transport_register_device(&session->dev); 343 transport_register_device(&session->dev);
267 344
345 mutex_lock(&ihost->mutex);
346 list_add(&session->host_list, &ihost->sessions);
347 mutex_unlock(&ihost->mutex);
348
268 return session; 349 return session;
269 350
270free_session: 351free_session:
@@ -285,6 +366,16 @@ EXPORT_SYMBOL_GPL(iscsi_create_session);
285 **/ 366 **/
286int iscsi_destroy_session(struct iscsi_cls_session *session) 367int iscsi_destroy_session(struct iscsi_cls_session *session)
287{ 368{
369 struct Scsi_Host *shost = iscsi_session_to_shost(session);
370 struct iscsi_host *ihost = shost->shost_data;
371
372 if (!cancel_delayed_work(&session->recovery_work))
373 flush_scheduled_work();
374
375 mutex_lock(&ihost->mutex);
376 list_del(&session->host_list);
377 mutex_unlock(&ihost->mutex);
378
288 transport_unregister_device(&session->dev); 379 transport_unregister_device(&session->dev);
289 device_unregister(&session->dev); 380 device_unregister(&session->dev);
290 return 0; 381 return 0;
@@ -435,7 +526,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
435 if (scsi_add_host(shost, NULL)) 526 if (scsi_add_host(shost, NULL))
436 goto free_host; 527 goto free_host;
437 528
438 session = iscsi_create_session(shost, transport); 529 session = iscsi_create_session(shost, transport, 0);
439 if (!session) 530 if (!session)
440 goto remove_host; 531 goto remove_host;
441 532
@@ -466,12 +557,13 @@ int iscsi_transport_destroy_session(struct Scsi_Host *shost)
466 struct iscsi_cls_session *session; 557 struct iscsi_cls_session *session;
467 unsigned long flags; 558 unsigned long flags;
468 559
469 scsi_remove_host(shost);
470 session = hostdata_session(shost->hostdata); 560 session = hostdata_session(shost->hostdata);
471 spin_lock_irqsave(&sesslock, flags); 561 spin_lock_irqsave(&sesslock, flags);
472 list_del(&session->sess_list); 562 list_del(&session->sess_list);
473 spin_unlock_irqrestore(&sesslock, flags); 563 spin_unlock_irqrestore(&sesslock, flags);
474 iscsi_destroy_session(session); 564 iscsi_destroy_session(session);
565
566 scsi_remove_host(shost);
475 /* ref from host alloc */ 567 /* ref from host alloc */
476 scsi_host_put(shost); 568 scsi_host_put(shost);
477 return 0; 569 return 0;
@@ -594,6 +686,7 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
594 } 686 }
595 687
596 spin_lock_irqsave(&zone->freelock, flags); 688 spin_lock_irqsave(&zone->freelock, flags);
689 INIT_LIST_HEAD(skb_to_lh(skb));
597 list_add(skb_to_lh(skb), &zone->freequeue); 690 list_add(skb_to_lh(skb), &zone->freequeue);
598 spin_unlock_irqrestore(&zone->freelock, flags); 691 spin_unlock_irqrestore(&zone->freelock, flags);
599 692
@@ -888,6 +981,11 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
888 return -EINVAL; 981 return -EINVAL;
889 982
890 switch (ev->u.set_param.param) { 983 switch (ev->u.set_param.param) {
984 case ISCSI_PARAM_SESS_RECOVERY_TMO:
985 iscsi_copy_param(ev, &value, data);
986 if (value != 0)
987 session->recovery_tmo = value;
988 break;
891 case ISCSI_PARAM_TARGET_NAME: 989 case ISCSI_PARAM_TARGET_NAME:
892 /* this should not change between logins */ 990 /* this should not change between logins */
893 if (session->targetname) 991 if (session->targetname)
@@ -980,7 +1078,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
980 ev->r.retcode = transport->start_conn(conn); 1078 ev->r.retcode = transport->start_conn(conn);
981 else 1079 else
982 err = -EINVAL; 1080 err = -EINVAL;
983
984 break; 1081 break;
985 case ISCSI_UEVENT_STOP_CONN: 1082 case ISCSI_UEVENT_STOP_CONN:
986 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid); 1083 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
@@ -1198,6 +1295,7 @@ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
1198 NULL) 1295 NULL)
1199iscsi_priv_session_attr(targetname, "%s"); 1296iscsi_priv_session_attr(targetname, "%s");
1200iscsi_priv_session_attr(tpgt, "%d"); 1297iscsi_priv_session_attr(tpgt, "%d");
1298iscsi_priv_session_attr(recovery_tmo, "%d");
1201 1299
1202#define iscsi_priv_conn_attr_show(field, format) \ 1300#define iscsi_priv_conn_attr_show(field, format) \
1203static ssize_t \ 1301static ssize_t \
@@ -1289,6 +1387,24 @@ static int iscsi_conn_match(struct attribute_container *cont,
1289 return &priv->conn_cont.ac == cont; 1387 return &priv->conn_cont.ac == cont;
1290} 1388}
1291 1389
1390static int iscsi_host_match(struct attribute_container *cont,
1391 struct device *dev)
1392{
1393 struct Scsi_Host *shost;
1394 struct iscsi_internal *priv;
1395
1396 if (!scsi_is_host_device(dev))
1397 return 0;
1398
1399 shost = dev_to_shost(dev);
1400 if (!shost->transportt ||
1401 shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
1402 return 0;
1403
1404 priv = to_iscsi_internal(shost->transportt);
1405 return &priv->t.host_attrs.ac == cont;
1406}
1407
1292struct scsi_transport_template * 1408struct scsi_transport_template *
1293iscsi_register_transport(struct iscsi_transport *tt) 1409iscsi_register_transport(struct iscsi_transport *tt)
1294{ 1410{
@@ -1307,6 +1423,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
1307 return NULL; 1423 return NULL;
1308 INIT_LIST_HEAD(&priv->list); 1424 INIT_LIST_HEAD(&priv->list);
1309 priv->iscsi_transport = tt; 1425 priv->iscsi_transport = tt;
1426 priv->t.user_scan = iscsi_user_scan;
1310 1427
1311 priv->cdev.class = &iscsi_transport_class; 1428 priv->cdev.class = &iscsi_transport_class;
1312 snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name); 1429 snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
@@ -1318,6 +1435,14 @@ iscsi_register_transport(struct iscsi_transport *tt)
1318 if (err) 1435 if (err)
1319 goto unregister_cdev; 1436 goto unregister_cdev;
1320 1437
1438 /* host parameters */
1439 priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
1440 priv->t.host_attrs.ac.class = &iscsi_host_class.class;
1441 priv->t.host_attrs.ac.match = iscsi_host_match;
1442 priv->t.host_size = sizeof(struct iscsi_host);
1443 priv->host_attrs[0] = NULL;
1444 transport_container_register(&priv->t.host_attrs);
1445
1321 /* connection parameters */ 1446 /* connection parameters */
1322 priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; 1447 priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
1323 priv->conn_cont.ac.class = &iscsi_connection_class.class; 1448 priv->conn_cont.ac.class = &iscsi_connection_class.class;
@@ -1361,6 +1486,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
1361 SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); 1486 SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
1362 SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); 1487 SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
1363 SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); 1488 SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
1489 SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
1364 1490
1365 if (tt->param_mask & ISCSI_TARGET_NAME) 1491 if (tt->param_mask & ISCSI_TARGET_NAME)
1366 SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); 1492 SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
@@ -1408,6 +1534,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
1408 1534
1409 transport_container_unregister(&priv->conn_cont); 1535 transport_container_unregister(&priv->conn_cont);
1410 transport_container_unregister(&priv->session_cont); 1536 transport_container_unregister(&priv->session_cont);
1537 transport_container_unregister(&priv->t.host_attrs);
1411 1538
1412 sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); 1539 sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
1413 class_device_unregister(&priv->cdev); 1540 class_device_unregister(&priv->cdev);
@@ -1451,10 +1578,14 @@ static __init int iscsi_transport_init(void)
1451 if (err) 1578 if (err)
1452 return err; 1579 return err;
1453 1580
1454 err = transport_class_register(&iscsi_connection_class); 1581 err = transport_class_register(&iscsi_host_class);
1455 if (err) 1582 if (err)
1456 goto unregister_transport_class; 1583 goto unregister_transport_class;
1457 1584
1585 err = transport_class_register(&iscsi_connection_class);
1586 if (err)
1587 goto unregister_host_class;
1588
1458 err = transport_class_register(&iscsi_session_class); 1589 err = transport_class_register(&iscsi_session_class);
1459 if (err) 1590 if (err)
1460 goto unregister_conn_class; 1591 goto unregister_conn_class;
@@ -1482,6 +1613,8 @@ unregister_session_class:
1482 transport_class_unregister(&iscsi_session_class); 1613 transport_class_unregister(&iscsi_session_class);
1483unregister_conn_class: 1614unregister_conn_class:
1484 transport_class_unregister(&iscsi_connection_class); 1615 transport_class_unregister(&iscsi_connection_class);
1616unregister_host_class:
1617 transport_class_unregister(&iscsi_host_class);
1485unregister_transport_class: 1618unregister_transport_class:
1486 class_unregister(&iscsi_transport_class); 1619 class_unregister(&iscsi_transport_class);
1487 return err; 1620 return err;
@@ -1494,6 +1627,7 @@ static void __exit iscsi_transport_exit(void)
1494 netlink_unregister_notifier(&iscsi_nl_notifier); 1627 netlink_unregister_notifier(&iscsi_nl_notifier);
1495 transport_class_unregister(&iscsi_connection_class); 1628 transport_class_unregister(&iscsi_connection_class);
1496 transport_class_unregister(&iscsi_session_class); 1629 transport_class_unregister(&iscsi_session_class);
1630 transport_class_unregister(&iscsi_host_class);
1497 class_unregister(&iscsi_transport_class); 1631 class_unregister(&iscsi_transport_class);
1498} 1632}
1499 1633
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 2c3a89b64e71..eebe2b15161b 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -174,6 +174,7 @@ enum iscsi_param {
174 ISCSI_PARAM_TPGT, 174 ISCSI_PARAM_TPGT,
175 ISCSI_PARAM_PERSISTENT_ADDRESS, 175 ISCSI_PARAM_PERSISTENT_ADDRESS,
176 ISCSI_PARAM_PERSISTENT_PORT, 176 ISCSI_PARAM_PERSISTENT_PORT,
177 ISCSI_PARAM_SESS_RECOVERY_TMO,
177 178
178 /* pased in through bind conn using transport_fd */ 179 /* pased in through bind conn using transport_fd */
179 ISCSI_PARAM_CONN_PORT, 180 ISCSI_PARAM_CONN_PORT,
@@ -201,6 +202,7 @@ enum iscsi_param {
201#define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT) 202#define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT)
202#define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS) 203#define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS)
203#define ISCSI_PERSISTENT_PORT (1 << ISCSI_PARAM_PERSISTENT_PORT) 204#define ISCSI_PERSISTENT_PORT (1 << ISCSI_PARAM_PERSISTENT_PORT)
205#define ISCSI_SESS_RECOVERY_TMO (1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
204#define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT) 206#define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT)
205#define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS) 207#define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS)
206 208
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 4b200645c84b..9d2b99159ee7 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -90,6 +90,7 @@ struct iscsi_transport {
90 char *data, uint32_t data_size); 90 char *data, uint32_t data_size);
91 void (*get_stats) (struct iscsi_cls_conn *conn, 91 void (*get_stats) (struct iscsi_cls_conn *conn,
92 struct iscsi_stats *stats); 92 struct iscsi_stats *stats);
93 void (*session_recovery_timedout) (struct iscsi_cls_session *session);
93}; 94};
94 95
95/* 96/*
@@ -130,12 +131,20 @@ struct iscsi_cls_conn {
130 131
131struct iscsi_cls_session { 132struct iscsi_cls_session {
132 struct list_head sess_list; /* item in session_list */ 133 struct list_head sess_list; /* item in session_list */
134 struct list_head host_list;
133 struct iscsi_transport *transport; 135 struct iscsi_transport *transport;
134 136
135 /* iSCSI values used as unique id by userspace. */ 137 /* iSCSI values used as unique id by userspace. */
136 char *targetname; 138 char *targetname;
137 int tpgt; 139 int tpgt;
138 140
141 /* recovery fields */
142 int recovery_tmo;
143 struct work_struct recovery_work;
144
145 int target_id;
146 int channel;
147
139 int sid; /* session id */ 148 int sid; /* session id */
140 void *dd_data; /* LLD private data */ 149 void *dd_data; /* LLD private data */
141 struct device dev; /* sysfs transport/container device */ 150 struct device dev; /* sysfs transport/container device */
@@ -147,15 +156,23 @@ struct iscsi_cls_session {
147#define iscsi_session_to_shost(_session) \ 156#define iscsi_session_to_shost(_session) \
148 dev_to_shost(_session->dev.parent) 157 dev_to_shost(_session->dev.parent)
149 158
159struct iscsi_host {
160 int next_target_id;
161 struct list_head sessions;
162 struct mutex mutex;
163};
164
150/* 165/*
151 * session and connection functions that can be used by HW iSCSI LLDs 166 * session and connection functions that can be used by HW iSCSI LLDs
152 */ 167 */
153extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, 168extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
154 struct iscsi_transport *t); 169 struct iscsi_transport *t, int channel);
155extern int iscsi_destroy_session(struct iscsi_cls_session *session); 170extern int iscsi_destroy_session(struct iscsi_cls_session *session);
156extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, 171extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
157 uint32_t cid); 172 uint32_t cid);
158extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); 173extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
174extern void iscsi_unblock_session(struct iscsi_cls_session *session);
175extern void iscsi_block_session(struct iscsi_cls_session *session);
159 176
160/* 177/*
161 * session functions used by software iscsi 178 * session functions used by software iscsi