diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 303 |
1 files changed, 147 insertions, 156 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 10bcf42cb65..1b495afe6d1 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -33,6 +33,7 @@ #include <linux/delay.h> #include <linux/kfifo.h> #include <linux/scatterlist.h> +#include <linux/mutex.h> #include <net/tcp.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> @@ -86,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) { sg_init_one(&ibuf->sg, (u8 *)vbuf, size); ibuf->sent = 0; + ibuf->use_sendmsg = 0; } static inline void iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) { - ibuf->sg.page = (void*)vbuf; - ibuf->sg.offset = (unsigned int)-1; + ibuf->sg.page = virt_to_page(vbuf); + ibuf->sg.offset = offset_in_page(vbuf); ibuf->sg.length = size; ibuf->sent = 0; -} - -static inline void* -iscsi_buf_iov_base(struct iscsi_buf *ibuf) -{ - return (char*)ibuf->sg.page + ibuf->sent; + ibuf->use_sendmsg = 1; } static inline void iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) { + ibuf->sg.page = sg->page; + ibuf->sg.offset = sg->offset; + ibuf->sg.length = sg->length; /* * Fastpath: sg element fits into single page */ - if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) { - ibuf->sg.page = sg->page; - ibuf->sg.offset = sg->offset; - ibuf->sg.length = sg->length; - } else - iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length); + if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page)) + ibuf->use_sendmsg = 0; + else + ibuf->use_sendmsg = 1; ibuf->sent = 0; } @@ -356,7 +354,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct scsi_cmnd *sc = ctask->sc; conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; - if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { + if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) { int res_count = be32_to_cpu(rhdr->residual_count); if (res_count > 0 && @@ -366,9 +364,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } else sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) - sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) { + } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) { sc->resid = be32_to_cpu(rhdr->residual_count); sc->result = (DID_OK << 16) | rhdr->cmd_status; } else @@ -529,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); - schedule_work(&conn->xmitwork); + scsi_queue_work(session->host, &conn->xmitwork); conn->r2t_pdus_cnt++; spin_unlock(&session->lock); @@ -686,7 +682,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) switch(conn->in.opcode) { case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: - case ISCSI_OP_LOGOUT_RSP: + case ISCSI_OP_LOGOUT_RSP: rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)hdr); if (rc) @@ -727,12 +723,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn) } spin_unlock(&session->lock); break; - case ISCSI_OP_NOOP_IN: + case ISCSI_OP_NOOP_IN: if (hdr->ttt != ISCSI_RESERVED_TAG) { rc = ISCSI_ERR_PROTO; break; } - rc = iscsi_check_assign_cmdsn(session, + rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)hdr); if (rc) break; @@ -767,7 +763,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) rc = iscsi_recv_pdu(iscsi_handle(conn), hdr, NULL, 0); - } else + } else rc = ISCSI_ERR_PROTO; break; case ISCSI_OP_REJECT: @@ -929,7 +925,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) sc->request_bufflen, ctask->data_offset); if (rc == -EAGAIN) return rc; - if (conn->datadgst_en) + if (conn->datadgst_en) iscsi_recv_digest_update(conn, sc->request_buffer, i); rc = 0; goto done; @@ -1024,7 +1020,7 @@ iscsi_data_recv(struct iscsi_conn *conn) conn->in.hdr = &conn->hdr; conn->senselen = (conn->data[0] << 8) | conn->data[1]; rc = iscsi_cmd_rsp(conn, conn->in.ctask); - if (!rc && conn->datadgst_en) + if (!rc && conn->datadgst_en) iscsi_recv_digest_update(conn, conn->data, conn->in.datalen); } @@ -1051,7 +1047,7 @@ iscsi_data_recv(struct iscsi_conn *conn) rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, conn->data, conn->in.datalen); - if (!rc && conn->datadgst_en && + if (!rc && conn->datadgst_en && conn->in.opcode != ISCSI_OP_LOGIN_RSP) iscsi_recv_digest_update(conn, conn->data, conn->in.datalen); @@ -1271,7 +1267,7 @@ iscsi_write_space(struct sock *sk) conn->old_write_space(sk); debug_tcp("iscsi_write_space: cid %d\n", conn->id); clear_bit(SUSPEND_BIT, &conn->suspend_tx); - schedule_work(&conn->xmitwork); + scsi_queue_work(conn->session->host, &conn->xmitwork); } static void @@ -1312,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) * @buf: buffer to write from * @size: actual size to write * @flags: socket's flags - * - * Notes: - * depending on buffer will use tcp_sendpage() or tcp_sendmsg(). - * buf->sg.offset == -1 tells us that buffer is non S/G and forces - * to use tcp_sendmsg(). */ static inline int -iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) +iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) { - int res; - - if ((int)buf->sg.offset >= 0) { - int offset = buf->sg.offset + buf->sent; - - /* tcp_sendpage */ - res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags); - } else { - struct msghdr msg; - - buf->iov.iov_base = iscsi_buf_iov_base(buf); - buf->iov.iov_len = size; - - memset(&msg, 0, sizeof(struct msghdr)); - - /* tcp_sendmsg */ - res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size); - } + struct socket *sk = conn->sock; + int offset = buf->sg.offset + buf->sent; - return res; + /* + * if we got use_sg=0 or are sending something we kmallocd + * then we did not have to do kmap (kmap returns page_address) + * + * if we got use_sg > 0, but had to drop down, we do not + * set clustering so this should only happen for that + * slab case. + */ + if (buf->use_sendmsg) + return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); + else + return conn->sendpage(sk, buf->sg.page, offset, size, flags); } /** @@ -1355,7 +1341,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) static inline int iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) { - struct socket *sk = conn->sock; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1364,7 +1349,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) if (buf->sent + size != buf->sg.length || datalen) flags |= MSG_MORE; - res = iscsi_send(sk, buf, size, flags); + res = iscsi_send(conn, buf, size, flags); debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); if (res >= 0) { conn->txdata_octets += res; @@ -1395,7 +1380,6 @@ static inline int iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, int *count, int *sent) { - struct socket *sk = conn->sock; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1406,7 +1390,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, if (buf->sent + size != buf->sg.length || *count != size) flags |= MSG_MORE; - res = iscsi_send(sk, buf, size, flags); + res = iscsi_send(conn, buf, size, flags); debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", size, buf->sent, *count, *sent, res); if (res >= 0) { @@ -1434,19 +1418,6 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ctask->digest_count = 4; } -static inline void -iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf) -{ - struct scatterlist sg; - - if (buf->sg.offset != -1) - crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1); - else { - sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length); - crypto_digest_update(conn->data_tx_tfm, &sg, 1); - } -} - static inline int iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_buf *buf, uint32_t *digest, int final) @@ -1680,7 +1651,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, zero_data(ctask->hdr.dlength); } - iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, + iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, sizeof(struct iscsi_hdr)); conn->scsicmd_pdus_cnt++; } @@ -1746,7 +1717,7 @@ static inline int handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { ctask->xmstate &= ~XMSTATE_R_HDR; - if (conn->hdrdgst_en) + if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { BUG_ON(ctask->xmstate != XMSTATE_IDLE); @@ -1760,7 +1731,7 @@ static inline int handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { ctask->xmstate &= ~XMSTATE_W_HDR; - if (conn->hdrdgst_en) + if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { ctask->xmstate |= XMSTATE_W_HDR; @@ -1809,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) return -EAGAIN; } if (conn->datadgst_en) - iscsi_buf_data_digest_update(conn, &ctask->sendbuf); + crypto_digest_update(conn->data_tx_tfm, + &ctask->sendbuf.sg, 1); if (!ctask->imm_count) break; @@ -1894,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) * so pass it */ if (conn->datadgst_en && ctask->sent - start > 0) - iscsi_buf_data_digest_update(conn, &ctask->sendbuf); + crypto_digest_update(conn->data_tx_tfm, + &ctask->sendbuf.sg, 1); if (!ctask->data_count) break; @@ -1972,7 +1945,7 @@ solicit_again: BUG_ON(r2t->data_count < 0); if (conn->datadgst_en) - iscsi_buf_data_digest_update(conn, &r2t->sendbuf); + crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1); if (r2t->data_count) { BUG_ON(ctask->sc->use_sg == 0); @@ -2054,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } if (conn->datadgst_en) { - iscsi_buf_data_digest_update(conn, &ctask->sendbuf); + crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1); /* imm data? */ if (!dtask) { if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, @@ -2148,7 +2121,7 @@ unsolicit_head_again: solicit_head_again: r2t = ctask->r2t; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &r2t->headbuf, + iscsi_hdr_digest(conn, &r2t->headbuf, (u8*)r2t->dtask->hdrext); if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { ctask->xmstate &= ~XMSTATE_SOL_DATA; @@ -2300,10 +2273,10 @@ iscsi_xmitworker(void *data) /* * serialize Xmit worker on a per-connection basis. */ - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); if (iscsi_data_xmit(conn)) - schedule_work(&conn->xmitwork); - up(&conn->xmitsema); + scsi_queue_work(conn->session->host, &conn->xmitwork); + mutex_unlock(&conn->xmitmutex); } #define FAILURE_BAD_HOST 1 @@ -2367,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); spin_unlock(&session->lock); - if (!in_interrupt() && !down_trylock(&conn->xmitsema)) { - spin_unlock_irq(host->host_lock); - if (iscsi_data_xmit(conn)) - schedule_work(&conn->xmitwork); - up(&conn->xmitsema); - spin_lock_irq(host->host_lock); - } else - schedule_work(&conn->xmitwork); - + scsi_queue_work(host, &conn->xmitwork); return 0; reject: @@ -2462,17 +2427,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items) kfree(items); } -static iscsi_connh_t -iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) +static struct iscsi_cls_conn * +iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx) { - struct iscsi_session *session = iscsi_ptr(sessionh); - struct iscsi_conn *conn = NULL; + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + struct iscsi_conn *conn; + struct iscsi_cls_conn *cls_conn; - conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL); - if (conn == NULL) - goto conn_alloc_fail; - memset(conn, 0, sizeof(struct iscsi_conn)); + cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata), + conn_idx); + if (!cls_conn) + return NULL; + conn = cls_conn->dd_data; + memset(conn, 0, sizeof(struct iscsi_conn)); conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->in_progress = IN_PROGRESS_WAIT_HEADER; conn->id = conn_idx; @@ -2531,10 +2499,10 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) goto max_recv_dlenght_alloc_fail; init_timer(&conn->tmabort_timer); - init_MUTEX(&conn->xmitsema); + mutex_init(&conn->xmitmutex); init_waitqueue_head(&conn->ehwait); - return iscsi_handle(conn); + return cls_conn; max_recv_dlenght_alloc_fail: spin_lock_bh(&session->lock); @@ -2550,18 +2518,18 @@ immqueue_alloc_fail: writequeue_alloc_fail: kfifo_free(conn->xmitqueue); xmitqueue_alloc_fail: - kfree(conn); -conn_alloc_fail: - return iscsi_handle(NULL); + iscsi_destroy_conn(cls_conn); + return NULL; } static void -iscsi_conn_destroy(iscsi_connh_t connh) +iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) { - struct iscsi_conn *conn = iscsi_ptr(connh); + struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; + unsigned long flags; - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); set_bit(SUSPEND_BIT, &conn->suspend_tx); if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { struct sock *sk = conn->sock->sk; @@ -2592,19 +2560,19 @@ iscsi_conn_destroy(iscsi_connh_t connh) } spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); /* * Block until all in-progress commands for this connection * time out or fail. */ for (;;) { - spin_lock_bh(&conn->lock); + spin_lock_irqsave(session->host->host_lock, flags); if (!session->host->host_busy) { /* OK for ERL == 0 */ - spin_unlock_bh(&conn->lock); + spin_unlock_irqrestore(session->host->host_lock, flags); break; } - spin_unlock_bh(&conn->lock); + spin_unlock_irqrestore(session->host->host_lock, flags); msleep_interruptible(500); printk("conn_destroy(): host_busy %d host_failed %d\n", session->host->host_busy, session->host->host_failed); @@ -2652,7 +2620,8 @@ iscsi_conn_destroy(iscsi_connh_t connh) kfifo_free(conn->writequeue); kfifo_free(conn->immqueue); kfifo_free(conn->mgmtqueue); - kfree(conn); + + iscsi_destroy_conn(cls_conn); } static int @@ -2713,6 +2682,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, */ iscsi_conn_set_callbacks(conn); + conn->sendpage = conn->sock->ops->sendpage; + /* * set receive state machine into initial state */ @@ -2796,7 +2767,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) set_bit(SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&sk->sk_callback_lock); - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); spin_lock_irqsave(session->host->host_lock, flags); spin_lock(&session->lock); @@ -2878,7 +2849,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) conn->datadgst_en = 0; } } - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); } static int @@ -2963,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, else __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); - schedule_work(&conn->xmitwork); - + scsi_queue_work(session->host, &conn->xmitwork); return 0; } @@ -3029,12 +2999,12 @@ iscsi_eh_abort(struct scsi_cmnd *sc) * 1) connection-level failure; * 2) recovery due protocol error; */ - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); spin_lock_bh(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { if (session->state == ISCSI_STATE_TERMINATE) { spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); goto failed; } spin_unlock_bh(&session->lock); @@ -3052,7 +3022,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) * 2) session was re-open during time out of ctask. */ spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); goto success; } conn->tmabort_state = TMABORT_INITIAL; @@ -3107,7 +3077,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) conn->tmabort_state == TMABORT_SUCCESS) { conn->tmabort_state = TMABORT_INITIAL; spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); goto success; } conn->tmabort_state = TMABORT_INITIAL; @@ -3116,7 +3086,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) spin_unlock_bh(&session->lock); } } - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); /* @@ -3182,7 +3152,7 @@ failed: exit: del_timer_sync(&conn->tmabort_timer); - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); if (conn->sock) { struct sock *sk = conn->sock->sk; @@ -3190,7 +3160,7 @@ exit: iscsi_ctask_cleanup(conn, ctask); write_unlock_bh(&sk->sk_callback_lock); } - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); return rc; } @@ -3281,17 +3251,23 @@ static struct scsi_host_template iscsi_sht = { .this_id = -1, }; -static iscsi_sessionh_t -iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) +static struct iscsi_transport iscsi_tcp_transport; + +static struct Scsi_Host * +iscsi_session_create(struct scsi_transport_template *scsit, + uint32_t initial_cmdsn) { - int cmd_i; + struct Scsi_Host *shost; struct iscsi_session *session; + int cmd_i; - session = iscsi_hostdata(host->hostdata); - memset(session, 0, sizeof(struct iscsi_session)); + shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport); + if (!shost) + return NULL; - session->host = host; - session->id = host->host_no; + session = iscsi_hostdata(shost->hostdata); + memset(session, 0, sizeof(struct iscsi_session)); + session->host = shost; session->state = ISCSI_STATE_LOGGED_IN; session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; session->cmds_max = ISCSI_XMIT_CMDS_MAX; @@ -3335,7 +3311,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) if (iscsi_r2tpool_alloc(session)) goto r2tpool_alloc_fail; - return iscsi_handle(session); + return shost; r2tpool_alloc_fail: for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) @@ -3345,15 +3321,15 @@ immdata_alloc_fail: mgmtpool_alloc_fail: iscsi_pool_free(&session->cmdpool, (void**)session->cmds); cmdpool_alloc_fail: - return iscsi_handle(NULL); + return NULL; } static void -iscsi_session_destroy(iscsi_sessionh_t sessionh) +iscsi_session_destroy(struct Scsi_Host *shost) { + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); int cmd_i; struct iscsi_data_task *dtask, *n; - struct iscsi_session *session = iscsi_ptr(sessionh); for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; @@ -3369,6 +3345,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh) iscsi_r2tpool_free(session); iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); iscsi_pool_free(&session->cmdpool, (void**)session->cmds); + + iscsi_transport_destroy_session(shost); } static int @@ -3467,6 +3445,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, if (conn->data_rx_tfm) crypto_free_tfm(conn->data_rx_tfm); } + conn->sendpage = conn->datadgst_en ? + sock_no_sendpage : conn->sock->ops->sendpage; break; case ISCSI_PARAM_INITIAL_R2T_EN: session->initial_r2t_en = value; @@ -3515,25 +3495,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, } static int -iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, - uint32_t *value) +iscsi_session_get_param(struct Scsi_Host *shost, + enum iscsi_param param, uint32_t *value) { - struct iscsi_conn *conn = iscsi_ptr(connh); - struct iscsi_session *session = conn->session; + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); switch(param) { - case ISCSI_PARAM_MAX_RECV_DLENGTH: - *value = conn->max_recv_dlength; - break; - case ISCSI_PARAM_MAX_XMIT_DLENGTH: - *value = conn->max_xmit_dlength; - break; - case ISCSI_PARAM_HDRDGST_EN: - *value = conn->hdrdgst_en; - break; - case ISCSI_PARAM_DATADGST_EN: - *value = conn->datadgst_en; - break; case ISCSI_PARAM_INITIAL_R2T_EN: *value = session->initial_r2t_en; break; @@ -3571,6 +3538,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, return 0; } +static int +iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value) +{ + struct iscsi_conn *conn = data; + + switch(param) { + case ISCSI_PARAM_MAX_RECV_DLENGTH: + *value = conn->max_recv_dlength; + break; + case ISCSI_PARAM_MAX_XMIT_DLENGTH: + *value = conn->max_xmit_dlength; + break; + case ISCSI_PARAM_HDRDGST_EN: + *value = conn->hdrdgst_en; + break; + case ISCSI_PARAM_DATADGST_EN: + *value = conn->datadgst_en; + break; + default: + return ISCSI_ERR_PARAM_NOT_FOUND; + } + + return 0; +} + static void iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) { @@ -3601,9 +3593,9 @@ iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data, struct iscsi_conn *conn = iscsi_ptr(connh); int rc; - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); rc = iscsi_conn_send_generic(conn, hdr, data, data_size); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); return rc; } @@ -3615,6 +3607,7 @@ static struct iscsi_transport iscsi_tcp_transport = { | CAP_DATADGST, .host_template = &iscsi_sht, .hostdata_size = sizeof(struct iscsi_session), + .conndata_size = sizeof(struct iscsi_conn), .max_conn = 1, .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, .create_session = iscsi_session_create, @@ -3623,7 +3616,8 @@ static struct iscsi_transport iscsi_tcp_transport = { .bind_conn = iscsi_conn_bind, .destroy_conn = iscsi_conn_destroy, .set_param = iscsi_conn_set_param, - .get_param = iscsi_conn_get_param, + .get_conn_param = iscsi_conn_get_param, + .get_session_param = iscsi_session_get_param, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, .send_pdu = iscsi_conn_send_pdu, @@ -3633,8 +3627,6 @@ static struct iscsi_transport iscsi_tcp_transport = { static int __init iscsi_tcp_init(void) { - int error; - if (iscsi_max_lun < 1) { printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); return -EINVAL; @@ -3647,11 +3639,10 @@ iscsi_tcp_init(void) if (!taskcache) return -ENOMEM; - error = iscsi_register_transport(&iscsi_tcp_transport); - if (error) + if (!iscsi_register_transport(&iscsi_tcp_transport)) kmem_cache_destroy(taskcache); - return error; + return 0; } static void __exit |