Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 154017
b: refs/heads/master
c: d355e57
h: refs/heads/master
i:
  154015: 40da598
v: v3
  • Loading branch information
Mike Christie authored and James Bottomley committed Jun 21, 2009
1 parent 6cbc984 commit 1820e66
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9194c6264040d71f851236437a392594b26e5b91
refs/heads/master: d355e57d58193b89283b0c8153649f0427b0bdad
62 changes: 49 additions & 13 deletions trunk/drivers/scsi/libiscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
task = iscsi_itt_to_ctask(conn, hdr->itt);
if (!task)
return ISCSI_ERR_BAD_ITT;
task->last_xfer = jiffies;
break;
case ISCSI_OP_R2T:
/*
Expand Down Expand Up @@ -1192,10 +1193,12 @@ static int iscsi_xmit_task(struct iscsi_conn *conn)
spin_unlock_bh(&conn->session->lock);
rc = conn->session->tt->xmit_task(task);
spin_lock_bh(&conn->session->lock);
__iscsi_put_task(task);
if (!rc)
if (!rc) {
/* done with this task */
task->last_xfer = jiffies;
conn->task = NULL;
}
__iscsi_put_task(task);
return rc;
}

Expand Down Expand Up @@ -1361,6 +1364,9 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
task->state = ISCSI_TASK_PENDING;
task->conn = conn;
task->sc = sc;
task->have_checked_conn = false;
task->last_timeout = jiffies;
task->last_xfer = jiffies;
INIT_LIST_HEAD(&task->running);
return task;
}
Expand Down Expand Up @@ -1716,17 +1722,18 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
return 0;
}

static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
{
enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
struct iscsi_task *task = NULL;
struct iscsi_cls_session *cls_session;
struct iscsi_session *session;
struct iscsi_conn *conn;
enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;

cls_session = starget_to_session(scsi_target(scmd->device));
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;

ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd);
ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", sc);

spin_lock(&session->lock);
if (session->state != ISCSI_STATE_LOGGED_IN) {
Expand All @@ -1745,6 +1752,26 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
goto done;
}

task = (struct iscsi_task *)sc->SCp.ptr;
if (!task)
goto done;
/*
* If we have sent (at least queued to the network layer) a pdu or
* recvd one for the task since the last timeout ask for
* more time. If on the next timeout we have not made progress
* we can check if it is the task or connection when we send the
* nop as a ping.
*/
if (time_after_eq(task->last_xfer, task->last_timeout)) {
ISCSI_DBG_CONN(conn, "Command making progress. Asking "
"scsi-ml for more time to complete. "
"Last data recv at %lu. Last timeout was at "
"%lu\n.", task->last_xfer, task->last_timeout);
task->have_checked_conn = false;
rc = BLK_EH_RESET_TIMER;
goto done;
}

if (!conn->recv_timeout && !conn->ping_timeout)
goto done;
/*
Expand All @@ -1755,20 +1782,29 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
rc = BLK_EH_RESET_TIMER;
goto done;
}

/* Assumes nop timeout is shorter than scsi cmd timeout */
if (task->have_checked_conn)
goto done;

/*
* if we are about to check the transport then give the command
* more time
* Checking the transport already or nop from a cmd timeout still
* running
*/
if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
jiffies)) {
if (conn->ping_task) {
task->have_checked_conn = true;
rc = BLK_EH_RESET_TIMER;
goto done;
}

/* if in the middle of checking the transport then give us more time */
if (conn->ping_task)
rc = BLK_EH_RESET_TIMER;
/* Make sure there is a transport check done */
iscsi_send_nopout(conn, NULL);
task->have_checked_conn = true;
rc = BLK_EH_RESET_TIMER;

done:
if (task)
task->last_timeout = jiffies;
spin_unlock(&session->lock);
ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
"timer reset" : "nh");
Expand Down
6 changes: 4 additions & 2 deletions trunk/drivers/scsi/libiscsi_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
"offset=%d, datalen=%d)\n",
tcp_task->data_offset,
tcp_conn->in.datalen);
task->last_xfer = jiffies;
rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
sdb->table.sgl,
sdb->table.nents,
Expand Down Expand Up @@ -713,9 +714,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
rc = ISCSI_ERR_BAD_ITT;
else if (ahslen)
rc = ISCSI_ERR_AHSLEN;
else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
else if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
task->last_xfer = jiffies;
rc = iscsi_tcp_r2t_rsp(conn, task);
else
} else
rc = ISCSI_ERR_PROTO;
spin_unlock(&conn->session->lock);
break;
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/scsi/libiscsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ struct iscsi_task {
struct scsi_cmnd *sc; /* associated SCSI cmd*/
struct iscsi_conn *conn; /* used connection */

/* data processing tracking */
unsigned long last_xfer;
unsigned long last_timeout;
bool have_checked_conn;
/* state set/tested under session->lock */
int state;
atomic_t refcount;
Expand Down

0 comments on commit 1820e66

Please sign in to comment.