diff options
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 6 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 151 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.h | 34 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 494 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 4 | ||||
-rw-r--r-- | include/scsi/iscsi_if.h | 2 | ||||
-rw-r--r-- | include/scsi/iscsi_proto.h | 2 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 25 |
8 files changed, 396 insertions, 322 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index bad8dacafd1..2eadb6d0ad8 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -220,12 +220,6 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn, debug_scsi("ctask deq [cid %d itt 0x%x]\n", conn->id, ctask->itt); - /* - * serialize with TMF AbortTask - */ - if (ctask->mtask) - return error; - /* Send the cmd PDU */ if (!iser_ctask->command_sent) { error = iser_send_command(conn, ctask); diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 57ce2251abc..4b226b88b68 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -197,7 +197,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (unlikely(!sc)) return; - tcp_ctask->xmstate = XMSTATE_VALUE_IDLE; + tcp_ctask->xmstate = XMSTATE_IDLE; tcp_ctask->r2t = NULL; } @@ -369,8 +369,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) spin_lock(&session->lock); iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); - if (!ctask->sc || ctask->mtask || - session->state != ISCSI_STATE_LOGGED_IN) { + if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in " "recovery...\n", ctask->itt); spin_unlock(&session->lock); @@ -409,11 +408,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->exp_datasn = r2tsn + 1; __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); - set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); - list_move_tail(&ctask->running, &conn->xmitqueue); - - scsi_queue_work(session->host, &conn->xmitwork); + tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT; conn->r2t_pdus_cnt++; + + iscsi_requeue_ctask(ctask); spin_unlock(&session->lock); return 0; @@ -1254,7 +1252,7 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask, tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); - set_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_W_PAD; } /** @@ -1269,7 +1267,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); - tcp_ctask->xmstate = 1 << XMSTATE_BIT_CMD_HDR_INIT; + tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT; } /** @@ -1283,10 +1281,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) * xmit. * * Management xmit state machine consists of these states: - * XMSTATE_BIT_IMM_HDR_INIT - calculate digest of PDU Header - * XMSTATE_BIT_IMM_HDR - PDU Header xmit in progress - * XMSTATE_BIT_IMM_DATA - PDU Data xmit in progress - * XMSTATE_VALUE_IDLE - management PDU is done + * XMSTATE_IMM_HDR_INIT - calculate digest of PDU Header + * XMSTATE_IMM_HDR - PDU Header xmit in progress + * XMSTATE_IMM_DATA - PDU Data xmit in progress + * XMSTATE_IDLE - management PDU is done **/ static int iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) @@ -1297,12 +1295,12 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", conn->id, tcp_mtask->xmstate, mtask->itt); - if (test_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate)) { + if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) { iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, sizeof(struct iscsi_hdr)); if (mtask->data_count) { - set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, mtask->data_count); @@ -1315,20 +1313,21 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) (u8*)tcp_mtask->hdrext); tcp_mtask->sent = 0; - clear_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate); - set_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); + tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT; + tcp_mtask->xmstate |= XMSTATE_IMM_HDR; } - if (test_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate)) { + if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, mtask->data_count); if (rc) return rc; - clear_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); + tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; } - if (test_and_clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate)) { + if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { BUG_ON(!mtask->data_count); + tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; /* FIXME: implement. * Virtual buffer could be spreaded across multiple pages... */ @@ -1338,13 +1337,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, &mtask->data_count, &tcp_mtask->sent); if (rc) { - set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; return rc; } } while (mtask->data_count); } - BUG_ON(tcp_mtask->xmstate != XMSTATE_VALUE_IDLE); + BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); if (mtask->hdr->itt == RESERVED_ITT) { struct iscsi_session *session = conn->session; @@ -1364,7 +1363,7 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc = 0; - if (test_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) { tcp_ctask->sent = 0; tcp_ctask->sg_count = 0; tcp_ctask->exp_datasn = 0; @@ -1389,21 +1388,21 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)tcp_ctask->hdrext); - clear_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; + tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; } - if (test_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) { rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); if (rc) return rc; - clear_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT; if (sc->sc_data_direction != DMA_TO_DEVICE) return 0; if (ctask->imm_count) { - set_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_IMM_DATA; iscsi_set_padding(tcp_ctask, ctask->imm_count); if (ctask->conn->datadgst_en) { @@ -1413,10 +1412,9 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } } - if (ctask->unsol_count) { - set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); - } + if (ctask->unsol_count) + tcp_ctask->xmstate |= + XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; } return rc; } @@ -1428,25 +1426,25 @@ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int sent = 0, rc; - if (test_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_W_PAD) { iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, tcp_ctask->pad_count); if (conn->datadgst_en) crypto_hash_update(&tcp_conn->tx_hash, &tcp_ctask->sendbuf.sg, tcp_ctask->sendbuf.sg.length); - } else if (!test_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate)) + } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD)) return 0; - clear_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); - clear_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_W_PAD; + tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD; debug_scsi("sending %d pad bytes for itt 0x%x\n", tcp_ctask->pad_count, ctask->itt); rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, &sent); if (rc) { debug_scsi("padding send failed %d\n", rc); - set_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD; } return rc; } @@ -1465,11 +1463,11 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, tcp_ctask = ctask->dd_data; tcp_conn = conn->dd_data; - if (!test_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate)) { + if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) { crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); iscsi_buf_init_iov(buf, (char*)digest, 4); } - clear_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST; rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); if (!rc) @@ -1478,7 +1476,7 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, else { debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", *digest, ctask->itt); - set_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST; } return rc; } @@ -1526,8 +1524,8 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_data_task *dtask; int rc; - set_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); - if (test_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate)) { + tcp_ctask->xmstate |= XMSTATE_UNS_DATA; + if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { dtask = &tcp_ctask->unsol_dtask; iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); @@ -1537,14 +1535,14 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)dtask->hdrext); - clear_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; iscsi_set_padding(tcp_ctask, ctask->data_count); } rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); if (rc) { - clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; + tcp_ctask->xmstate |= XMSTATE_UNS_HDR; return rc; } @@ -1565,15 +1563,16 @@ iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc; - if (test_and_clear_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { BUG_ON(!ctask->unsol_count); + tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; send_hdr: rc = iscsi_send_unsol_hdr(conn, ctask); if (rc) return rc; } - if (test_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; int start = tcp_ctask->sent; @@ -1583,14 +1582,14 @@ send_hdr: ctask->unsol_count -= tcp_ctask->sent - start; if (rc) return rc; - clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; /* * Done with the Data-Out. Next, check if we need * to send another unsolicited Data-Out. */ if (ctask->unsol_count) { debug_scsi("sending more uns\n"); - set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); + tcp_ctask->xmstate |= XMSTATE_UNS_INIT; goto send_hdr; } } @@ -1606,7 +1605,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn, struct iscsi_data_task *dtask; int left, rc; - if (test_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) { if (!tcp_ctask->r2t) { spin_lock_bh(&session->lock); __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, @@ -1620,19 +1619,19 @@ send_hdr: if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, (u8*)dtask->hdrext); - clear_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT; + tcp_ctask->xmstate |= XMSTATE_SOL_HDR; } - if (test_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { r2t = tcp_ctask->r2t; dtask = &r2t->dtask; rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); if (rc) return rc; - clear_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); - set_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; if (conn->datadgst_en) { iscsi_data_digest_init(conn->dd_data, tcp_ctask); @@ -1645,7 +1644,7 @@ send_hdr: r2t->sent); } - if (test_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { r2t = tcp_ctask->r2t; dtask = &r2t->dtask; @@ -1654,7 +1653,7 @@ send_hdr: &dtask->digestbuf, &dtask->digest); if (rc) return rc; - clear_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; /* * Done with this Data-Out. Next, check if we have @@ -1699,32 +1698,32 @@ send_hdr: * xmit stages. * *iscsi_send_cmd_hdr() - * XMSTATE_BIT_CMD_HDR_INIT - prepare Header and Data buffers Calculate - * Header Digest - * XMSTATE_BIT_CMD_HDR_XMIT - Transmit header in progress + * XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate + * Header Digest + * XMSTATE_CMD_HDR_XMIT - Transmit header in progress * *iscsi_send_padding - * XMSTATE_BIT_W_PAD - Prepare and send pading - * XMSTATE_BIT_W_RESEND_PAD - retry send pading + * XMSTATE_W_PAD - Prepare and send pading + * XMSTATE_W_RESEND_PAD - retry send pading * *iscsi_send_digest - * XMSTATE_BIT_W_RESEND_DATA_DIGEST - Finalize and send Data Digest - * XMSTATE_BIT_W_RESEND_DATA_DIGEST - retry sending digest + * XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest + * XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest * *iscsi_send_unsol_hdr - * XMSTATE_BIT_UNS_INIT - prepare un-solicit data header and digest - * XMSTATE_BIT_UNS_HDR - send un-solicit header + * XMSTATE_UNS_INIT - prepare un-solicit data header and digest + * XMSTATE_UNS_HDR - send un-solicit header * *iscsi_send_unsol_pdu - * XMSTATE_BIT_UNS_DATA - send un-solicit data in progress + * XMSTATE_UNS_DATA - send un-solicit data in progress * *iscsi_send_sol_pdu - * XMSTATE_BIT_SOL_HDR_INIT - solicit data header and digest initialize - * XMSTATE_BIT_SOL_HDR - send solicit header - * XMSTATE_BIT_SOL_DATA - send solicit data + * XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize + * XMSTATE_SOL_HDR - send solicit header + * XMSTATE_SOL_DATA - send solicit data * *iscsi_tcp_ctask_xmit - * XMSTATE_BIT_IMM_DATA - xmit managment data (??) + * XMSTATE_IMM_DATA - xmit managment data (??) **/ static int iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) @@ -1741,13 +1740,13 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) return 0; - if (test_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate)) { + if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, &tcp_ctask->sent, &ctask->imm_count, &tcp_ctask->immbuf, &tcp_ctask->immdigest); if (rc) return rc; - clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); + tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; } rc = iscsi_send_unsol_pdu(conn, ctask); @@ -1980,7 +1979,7 @@ static void iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) { struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; - tcp_mtask->xmstate = 1 << XMSTATE_BIT_IMM_HDR_INIT; + tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT; } static int @@ -2226,6 +2225,7 @@ static struct scsi_host_template iscsi_sht = { .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, .eh_abort_handler = iscsi_eh_abort, + .eh_device_reset_handler= iscsi_eh_device_reset, .eh_host_reset_handler = iscsi_eh_host_reset, .use_clustering = DISABLE_CLUSTERING, .slave_configure = iscsi_tcp_slave_configure, @@ -2257,7 +2257,8 @@ static struct iscsi_transport iscsi_tcp_transport = { ISCSI_PERSISTENT_ADDRESS | ISCSI_TARGET_NAME | ISCSI_TPGT | ISCSI_USERNAME | ISCSI_PASSWORD | - ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN, + ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | + ISCSI_FAST_ABORT, .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME, diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 68c36cc8997..7eba44df0a7 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -32,21 +32,21 @@ #define IN_PROGRESS_PAD_RECV 0x4 /* xmit state machine */ -#define XMSTATE_VALUE_IDLE 0 -#define XMSTATE_BIT_CMD_HDR_INIT 0 -#define XMSTATE_BIT_CMD_HDR_XMIT 1 -#define XMSTATE_BIT_IMM_HDR 2 -#define XMSTATE_BIT_IMM_DATA 3 -#define XMSTATE_BIT_UNS_INIT 4 -#define XMSTATE_BIT_UNS_HDR 5 -#define XMSTATE_BIT_UNS_DATA 6 -#define XMSTATE_BIT_SOL_HDR 7 -#define XMSTATE_BIT_SOL_DATA 8 -#define XMSTATE_BIT_W_PAD 9 -#define XMSTATE_BIT_W_RESEND_PAD 10 -#define XMSTATE_BIT_W_RESEND_DATA_DIGEST 11 -#define XMSTATE_BIT_IMM_HDR_INIT 12 -#define XMSTATE_BIT_SOL_HDR_INIT 13 +#define XMSTATE_IDLE 0x0 +#define XMSTATE_CMD_HDR_INIT 0x1 +#define XMSTATE_CMD_HDR_XMIT 0x2 +#define XMSTATE_IMM_HDR 0x4 +#define XMSTATE_IMM_DATA 0x8 +#define XMSTATE_UNS_INIT 0x10 +#define XMSTATE_UNS_HDR 0x20 +#define XMSTATE_UNS_DATA 0x40 +#define XMSTATE_SOL_HDR 0x80 +#define XMSTATE_SOL_DATA 0x100 +#define XMSTATE_W_PAD 0x200 +#define XMSTATE_W_RESEND_PAD 0x400 +#define XMSTATE_W_RESEND_DATA_DIGEST 0x800 +#define XMSTATE_IMM_HDR_INIT 0x1000 +#define XMSTATE_SOL_HDR_INIT 0x2000 #define ISCSI_PAD_LEN 4 #define ISCSI_SG_TABLESIZE SG_ALL @@ -122,7 +122,7 @@ struct iscsi_data_task { struct iscsi_tcp_mgmt_task { struct iscsi_hdr hdr; char hdrext[sizeof(__u32)]; /* Header-Digest */ - unsigned long xmstate; /* mgmt xmit progress */ + int xmstate; /* mgmt xmit progress */ struct iscsi_buf headbuf; /* header buffer */ struct iscsi_buf sendbuf; /* in progress buffer */ int sent; @@ -150,7 +150,7 @@ struct iscsi_tcp_cmd_task { int pad_count; /* padded bytes */ struct iscsi_buf headbuf; /* header buf (xmit) */ struct iscsi_buf sendbuf; /* in progress buffer*/ - unsigned long xmstate; /* xmit xtate machine */ + int xmstate; /* xmit xtate machine */ int sent; struct scatterlist *sg; /* per-cmd SG list */ struct scatterlist *bad_sg; /* assert statement */ diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 8b57af5baae..176458f3531 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -86,7 +86,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) * xmit thread */ if (!list_empty(&session->leadconn->xmitqueue) || - __kfifo_len(session->leadconn->mgmtqueue)) + !list_empty(&session->leadconn->mgmtqueue)) scsi_queue_work(session->host, &session->leadconn->xmitwork); } @@ -318,15 +318,15 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++; - if (conn->tmabort_state != TMABORT_INITIAL) + if (conn->tmf_state != TMF_QUEUED) return; if (tmf->response == ISCSI_TMF_RSP_COMPLETE) - conn->tmabort_state = TMABORT_SUCCESS; + conn->tmf_state = TMF_SUCCESS; else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) - conn->tmabort_state = TMABORT_NOT_FOUND; + conn->tmf_state = TMF_NOT_FOUND; else - conn->tmabort_state = TMABORT_FAILED; + conn->tmf_state = TMF_FAILED; wake_up(&conn->ehwait); } @@ -429,7 +429,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, */ if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; - list_del(&mtask->running); + list_del_init(&mtask->running); if (conn->login_mtask != mtask) __kfifo_put(session->mgmtpool.queue, (void*)&mtask, sizeof(void*)); @@ -451,10 +451,9 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; - list_del(&mtask->running); - if (conn->login_mtask != mtask) - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); + list_del_init(&mtask->running); + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); break; default: rc = ISCSI_ERR_BAD_OPCODE; @@ -609,7 +608,8 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn, session->tt->init_mgmt_task(conn, mtask); debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", - hdr->opcode, hdr->itt, mtask->data_count); + hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, + mtask->data_count); } static int iscsi_xmit_mtask(struct iscsi_conn *conn) @@ -658,21 +658,13 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) static int iscsi_xmit_ctask(struct iscsi_conn *conn) { struct iscsi_cmd_task *ctask = conn->ctask; - int rc = 0; - - /* - * serialize with TMF AbortTask - */ - if (ctask->state == ISCSI_TASK_ABORTING) - goto done; + int rc; __iscsi_get_ctask(ctask); spin_unlock_bh(&conn->session->lock); rc = conn->session->tt->xmit_cmd_task(conn, ctask); spin_lock_bh(&conn->session->lock); __iscsi_put_ctask(ctask); - -done: if (!rc) /* done with this ctask */ conn->ctask = NULL; @@ -680,6 +672,22 @@ done: } /** + * iscsi_requeue_ctask - requeue ctask to run from session workqueue + * @ctask: ctask to requeue + * + * LLDs that need to run a ctask from the session workqueue should call + * this. The session lock must be held. + */ +void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + + list_move_tail(&ctask->running, &conn->requeue); + scsi_queue_work(conn->session->host, &conn->xmitwork); +} +EXPORT_SYMBOL_GPL(iscsi_requeue_ctask); + +/** * iscsi_data_xmit - xmit any command into the scheduled connection * @conn: iscsi connection * @@ -717,36 +725,27 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) * overflow us with nop-ins */ check_mgmt: - while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, - sizeof(void*))) { + while (!list_empty(&conn->mgmtqueue)) { + conn->mtask = list_entry(conn->mgmtqueue.next, + struct iscsi_mgmt_task, running); iscsi_prep_mtask(conn, conn->mtask); - list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); + list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list); rc = iscsi_xmit_mtask(conn); if (rc) goto again; } - /* process command queue */ + /* process pending command queue */ while (!list_empty(&conn->xmitqueue)) { - /* - * iscsi tcp may readd the task to the xmitqueue to send - * write data - */ + if (conn->tmf_state == TMF_QUEUED) + break; + conn->ctask = list_entry(conn->xmitqueue.next, struct iscsi_cmd_task, running); - switch (conn->ctask->state) { - case ISCSI_TASK_ABORTING: - break; - case ISCSI_TASK_PENDING: - iscsi_prep_scsi_cmd_pdu(conn->ctask); - conn->session->tt->init_cmd_task(conn->ctask); - /* fall through */ - default: - conn->ctask->state = ISCSI_TASK_RUNNING; - break; - } + iscsi_prep_scsi_cmd_pdu(conn->ctask); + conn->session->tt->init_cmd_task(conn->ctask); + conn->ctask->state = ISCSI_TASK_RUNNING; list_move_tail(conn->xmitqueue.next, &conn->run_list); - rc = iscsi_xmit_ctask(conn); if (rc) goto again; @@ -755,7 +754,22 @@ check_mgmt: * we need to check the mgmt queue for nops that need to * be sent to aviod starvation */ - if (__kfifo_len(conn->mgmtqueue)) + if (!list_empty(&conn->mgmtqueue)) + goto check_mgmt; + } + + while (!list_empty(&conn->requeue)) { + if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL) + break; + + conn->ctask = list_entry(conn->requeue.next, + struct iscsi_cmd_task, running); + conn->ctask->state = ISCSI_TASK_RUNNING; + list_move_tail(conn->requeue.next, &conn->run_list); + rc = iscsi_xmit_ctask(conn); + if (rc) + goto again; + if (!list_empty(&conn->mgmtqueue)) goto check_mgmt; } spin_unlock_bh(&conn->session->lock); @@ -859,7 +873,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) atomic_set(&ctask->refcount, 1); ctask->state = ISCSI_TASK_PENDING; - ctask->mtask = NULL; ctask->conn = conn; ctask->sc = sc; INIT_LIST_HEAD(&ctask->running); @@ -929,9 +942,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } else mtask->data_count = 0; - INIT_LIST_HEAD(&mtask->running); memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); - __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); + INIT_LIST_HEAD(&mtask->running); + list_add_tail(&mtask->running, &conn->mgmtqueue); return mtask; } @@ -954,13 +967,12 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) { struct iscsi_session *session = class_to_transport_session(cls_session); - struct iscsi_conn *conn = session->leadconn; spin_lock_bh(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { session->state = ISCSI_STATE_RECOVERY_FAILED; - if (conn) - wake_up(&conn->ehwait); + if (session->leadconn) + wake_up(&session->leadconn->ehwait); } spin_unlock_bh(&session->lock); } @@ -971,7 +983,6 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc) struct Scsi_Host *host = sc->device->host; struct iscsi_session *session = iscsi_hostdata(host->hostdata); struct iscsi_conn *conn = session->leadconn; - int fail_session = 0; spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_TERMINATE) { @@ -982,19 +993,13 @@ failed: return FAILED; } - if (sc->SCp.phase == session->age) { - debug_scsi("failing connection CID %d due to SCSI host reset\n", - conn->id); - fail_session = 1; - } spin_unlock_bh(&session->lock); /* * we drop the lock here but the leadconn cannot be destoyed while * we are in the scsi eh */ - if (fail_session) - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); debug_scsi("iscsi_eh_host_reset wait for relogin\n"); wait_event_interruptible(conn->ehwait, @@ -1015,62 +1020,43 @@ failed: } EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); -static void iscsi_tmabort_timedout(unsigned long data) +static void iscsi_tmf_timedout(unsigned long data) { - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; - struct iscsi_conn *conn = ctask->conn; + struct iscsi_conn *conn = (struct iscsi_conn *)data; struct iscsi_session *session = conn->session; spin_lock(&session->lock); - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmabort_state = TMABORT_TIMEDOUT; - debug_scsi("tmabort timedout [sc %p itt 0x%x]\n", - ctask->sc, ctask->itt); + if (conn->tmf_state == TMF_QUEUED) { + conn->tmf_state = TMF_TIMEDOUT; + debug_scsi("tmf timedout\n"); /* unblock eh_abort() */ wake_up(&conn->ehwait); } spin_unlock(&session->lock); } -static int iscsi_exec_abort_task(struct scsi_cmnd *sc, - struct iscsi_cmd_task *ctask) +static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, + struct iscsi_tm *hdr, int age) { - struct iscsi_conn *conn = ctask->conn; struct iscsi_session *session = conn->session; - struct iscsi_tm *hdr = &conn->tmhdr; - - /* - * ctask timed out but session is OK requests must be serialized. - */ - memset(hdr, 0, sizeof(struct iscsi_tm)); - hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; - hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; - hdr->flags |= ISCSI_FLAG_CMD_FINAL; - memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); - hdr->rtt = ctask->hdr->itt; - hdr->refcmdsn = ctask->hdr->cmdsn; + struct iscsi_mgmt_task *mtask; - ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, - NULL, 0); - if (!ctask->mtask) { + mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, + NULL, 0); + if (!mtask) { spin_unlock_bh(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - spin_lock_bh(&session->lock) - debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt); + spin_lock_bh(&session->lock); + debug_scsi("tmf exec failure\n"); return -EPERM; } - ctask->state = ISCSI_TASK_ABORTING; - - debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); + conn->tmfcmd_pdus_cnt++; + conn->tmf_timer.expires = 30 * HZ + jiffies; + conn->tmf_timer.function = iscsi_tmf_timedout; + conn->tmf_timer.data = (unsigned long)conn; + add_timer(&conn->tmf_timer); + debug_scsi("tmf set timeout\n"); - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmfcmd_pdus_cnt++; - conn->tmabort_timer.expires = 20*HZ + jiffies; - conn->tmabort_timer.function = iscsi_tmabort_timedout; - conn->tmabort_timer.data = (unsigned long)ctask; - add_timer(&conn->tmabort_timer); - debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); - } spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); scsi_queue_work(session->host, &conn->xmitwork); @@ -1078,61 +1064,30 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, /* * block eh thread until: * - * 1) abort response - * 2) abort timeout + * 1) tmf response + * 2) tmf timeout * 3) session is terminated or restarted or userspace has * given up on recovery */ - wait_event_interruptible(conn->ehwait, - sc->SCp.phase != session->age || + wait_event_interruptible(conn->ehwait, age != session->age || session->state != ISCSI_STATE_LOGGED_IN || - conn->tmabort_state != TMABORT_INITIAL); + conn->tmf_state != TMF_QUEUED); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&conn->tmabort_timer); + del_timer_sync(&conn->tmf_timer); + mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); - return 0; -} - -/* - * session lock must be held - */ -static struct iscsi_mgmt_task * -iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) -{ - int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); - struct iscsi_mgmt_task *task; - - debug_scsi("searching %d tasks\n", nr_tasks); - - for (i = 0; i < nr_tasks; i++) { - __kfifo_get(fifo, (void*)&task, sizeof(void*)); - debug_scsi("check task %u\n", task->itt); - - if (task->itt == itt) { - debug_scsi("matched task\n"); - return task; - } + /* if the session drops it will clean up the mtask */ + if (age != session->age || + session->state != ISCSI_STATE_LOGGED_IN) + return -ENOTCONN; - __kfifo_put(fifo, (void*)&task, sizeof(void*)); + if (!list_empty(&mtask->running)) { + list_del_init(&mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); } - return NULL; -} - -static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) -{ - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - - if (!ctask->mtask) - return -EINVAL; - - if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt)) - list_del(&ctask->mtask->running); - __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, - sizeof(void*)); - ctask->mtask = NULL; return 0; } @@ -1156,7 +1111,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, conn->session->queued_cmdsn--; else conn->session->tt->cleanup_cmd_task(conn, ctask); - iscsi_ctask_mtask_cleanup(ctask); sc->result = err; scsi_set_resid(sc, scsi_bufflen(sc)); @@ -1166,6 +1120,44 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, __iscsi_put_ctask(ctask); } +/* + * Fail commands. session lock held and recv side suspended and xmit + * thread flushed + */ +static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) +{ + struct iscsi_cmd_task *ctask, *tmp; + + if (conn->ctask && (conn->ctask->sc->device->lun == lun || lun == -1)) + conn->ctask = NULL; + + /* flush pending */ + list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { + if (lun == ctask->sc->device->lun || lun == -1) { + debug_scsi("failing pending sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + } + + list_for_each_entry_safe(ctask, tmp, &conn->requeue, running) { + if (lun == ctask->sc->device->lun || lun == -1) { + debug_scsi("failing requeued sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + } + + /* fail all other running */ + list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { + if (lun == ctask->sc->device->lun || lun == -1) { + debug_scsi("failing in progress sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + } +} + static void iscsi_suspend_tx(struct iscsi_conn *conn) { set_bit(ISCSI_SUSPE |