Skip to content

Commit

Permalink
[SCSI] libiscsi, iser, tcp: remove recv_lock
Browse files Browse the repository at this point in the history
The recv lock was defined so the iscsi layer could block
the recv path from processing IO during recovery. It
turns out iser just set a lock to that pointer which was pointless.

We now disconnect the transport connection before doing recovery
so we do not need the recv lock. For iscsi_tcp we still stop
the recv path incase older tools are being used.

This patch also has iscsi_itt_to_ctask user grab the session lock
and has the caller access the task with the lock or get a ref
to it in case the target is broken and sends a tmf success response
then sends data or a response for the command that was supposed to
be affected bty the tmf.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
  • Loading branch information
Mike Christie authored and James Bottomley committed Jul 12, 2008
1 parent 3cf7b23 commit 913e5bf
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 117 deletions.
20 changes: 10 additions & 10 deletions drivers/infiniband/ulp/iser/iscsi_iser.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,6 @@ iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
conn->max_recv_dlength = 128;

iser_conn = conn->dd_data;
/* currently this is the only field which need to be initiated */
rwlock_init(&iser_conn->lock);

conn->dd_data = iser_conn;
iser_conn->iscsi_conn = conn;

Expand Down Expand Up @@ -342,9 +339,6 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
ib_conn->iser_conn = iser_conn;
iser_conn->ib_conn = ib_conn;
iser_conn_get(ib_conn);

conn->recv_lock = &iser_conn->lock;

return 0;
}

Expand All @@ -355,12 +349,18 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
struct iscsi_iser_conn *iser_conn = conn->dd_data;
struct iser_conn *ib_conn = iser_conn->ib_conn;

iscsi_conn_stop(cls_conn, flag);
/*
* There is no unbind event so the stop callback
* must release the ref from the bind.
* Userspace may have goofed up and not bound the connection or
* might have only partially setup the connection.
*/
iser_conn_put(ib_conn);
if (ib_conn) {
iscsi_conn_stop(cls_conn, flag);
/*
* There is no unbind event so the stop callback
* must release the ref from the bind.
*/
iser_conn_put(ib_conn);
}
iser_conn->ib_conn = NULL;
}

Expand Down
2 changes: 0 additions & 2 deletions drivers/infiniband/ulp/iser/iscsi_iser.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,6 @@ struct iser_conn {
struct iscsi_iser_conn {
struct iscsi_conn *iscsi_conn;/* ptr to iscsi conn */
struct iser_conn *ib_conn; /* iSER IB conn */

rwlock_t lock;
};

struct iscsi_iser_task {
Expand Down
6 changes: 6 additions & 0 deletions drivers/infiniband/ulp/iser/iser_initiator.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,12 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
opcode = hdr->opcode & ISCSI_OPCODE_MASK;

if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
spin_lock(&conn->iscsi_conn->session->lock);
task = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
if (task)
__iscsi_get_task(task);
spin_unlock(&conn->iscsi_conn->session->lock);

if (!task)
iser_err("itt can't be matched to task!!! "
"conn %p opcode %d itt %d\n",
Expand All @@ -568,6 +573,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
iser_dbg("itt %d task %p\n",hdr->itt, task);
iser_task->status = ISER_TASK_STATUS_COMPLETED;
iser_task_rdma_finalize(iser_task);
iscsi_put_task(task);
}
}
iser_dto_buffs_release(dto);
Expand Down
73 changes: 39 additions & 34 deletions drivers/scsi/iscsi_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,6 @@ static int
iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
{
int rc = 0, opcode, ahslen;
struct iscsi_session *session = conn->session;
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct iscsi_task *task;

Expand Down Expand Up @@ -770,17 +769,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)

switch(opcode) {
case ISCSI_OP_SCSI_DATA_IN:
spin_lock(&conn->session->lock);
task = iscsi_itt_to_ctask(conn, hdr->itt);
if (!task)
return ISCSI_ERR_BAD_ITT;
if (!task->sc)
return ISCSI_ERR_NO_SCSI_CMD;
rc = ISCSI_ERR_BAD_ITT;
else
rc = iscsi_data_rsp(conn, task);
if (rc) {
spin_unlock(&conn->session->lock);
break;
}

spin_lock(&conn->session->lock);
rc = iscsi_data_rsp(conn, task);
spin_unlock(&conn->session->lock);
if (rc)
return rc;
if (tcp_conn->in.datalen) {
struct iscsi_tcp_task *tcp_task = task->dd_data;
struct hash_desc *rx_hash = NULL;
Expand All @@ -801,15 +800,19 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
"datalen=%d)\n", tcp_conn,
tcp_task->data_offset,
tcp_conn->in.datalen);
return iscsi_segment_seek_sg(&tcp_conn->in.segment,
sdb->table.sgl,
sdb->table.nents,
tcp_task->data_offset,
tcp_conn->in.datalen,
iscsi_tcp_process_data_in,
rx_hash);
rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
sdb->table.sgl,
sdb->table.nents,
tcp_task->data_offset,
tcp_conn->in.datalen,
iscsi_tcp_process_data_in,
rx_hash);
spin_unlock(&conn->session->lock);
return rc;
}
/* fall through */
rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
spin_unlock(&conn->session->lock);
break;
case ISCSI_OP_SCSI_CMD_RSP:
if (tcp_conn->in.datalen) {
iscsi_tcp_data_recv_prep(tcp_conn);
Expand All @@ -818,20 +821,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
break;
case ISCSI_OP_R2T:
spin_lock(&conn->session->lock);
task = iscsi_itt_to_ctask(conn, hdr->itt);
if (!task)
return ISCSI_ERR_BAD_ITT;
if (!task->sc)
return ISCSI_ERR_NO_SCSI_CMD;

if (ahslen)
rc = ISCSI_ERR_BAD_ITT;
else if (ahslen)
rc = ISCSI_ERR_AHSLEN;
else if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
spin_lock(&session->lock);
else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
rc = iscsi_r2t_rsp(conn, task);
spin_unlock(&session->lock);
} else
else
rc = ISCSI_ERR_PROTO;
spin_unlock(&conn->session->lock);
break;
case ISCSI_OP_LOGIN_RSP:
case ISCSI_OP_TEXT_RSP:
Expand Down Expand Up @@ -1553,7 +1553,6 @@ iscsi_tcp_release_conn(struct iscsi_conn *conn)

spin_lock_bh(&session->lock);
tcp_conn->sock = NULL;
conn->recv_lock = NULL;
spin_unlock_bh(&session->lock);
sockfd_put(sock);
}
Expand All @@ -1578,6 +1577,19 @@ static void
iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;

/* userspace may have goofed up and not bound us */
if (!tcp_conn->sock)
return;
/*
* Make sure our recv side is stopped.
* Older tools called conn stop before ep_disconnect
* so IO could still be coming in.
*/
write_lock_bh(&tcp_conn->sock->sk->sk_callback_lock);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
write_unlock_bh(&tcp_conn->sock->sk->sk_callback_lock);

iscsi_conn_stop(cls_conn, flag);
iscsi_tcp_release_conn(conn);
Expand Down Expand Up @@ -1671,13 +1683,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
sk->sk_allocation = GFP_ATOMIC;

/* FIXME: disable Nagle's algorithm */

/*
* Intercept TCP callbacks for sendfile like receive
* processing.
*/
conn->recv_lock = &sk->sk_callback_lock;
iscsi_conn_set_callbacks(conn);
tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
/*
Expand Down
Loading

0 comments on commit 913e5bf

Please sign in to comment.