diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2006-08-31 18:09:33 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-09-02 14:37:36 -0400 |
commit | f47f2cf5d4acf929a3aaa6957c3fc4622c358703 (patch) | |
tree | 6bf770ac6a789f926728b1881a7eee64a463404f /drivers/scsi/libiscsi.c | |
parent | ca5186842a6d85e982e3d572ecd407453d0c5116 (diff) |
[SCSI] libiscsi: check that command ptr is set before accessing it
If the scsi eh sends a TUR and the session is down we could
return SCSI_ML_HOST_BUSY. scsi eh will ignore this and send
ask us to abort the command and we blindly accesst the
command ptr.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 864c6284e83c..12b5c1800740 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -192,6 +192,8 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask) | |||
192 | 192 | ||
193 | ctask->state = ISCSI_TASK_COMPLETED; | 193 | ctask->state = ISCSI_TASK_COMPLETED; |
194 | ctask->sc = NULL; | 194 | ctask->sc = NULL; |
195 | /* SCSI eh reuses commands to verify us */ | ||
196 | sc->SCp.ptr = NULL; | ||
195 | list_del_init(&ctask->running); | 197 | list_del_init(&ctask->running); |
196 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); | 198 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); |
197 | sc->scsi_done(sc); | 199 | sc->scsi_done(sc); |
@@ -737,6 +739,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
737 | 739 | ||
738 | sc->scsi_done = done; | 740 | sc->scsi_done = done; |
739 | sc->result = 0; | 741 | sc->result = 0; |
742 | sc->SCp.ptr = NULL; | ||
740 | 743 | ||
741 | host = sc->device->host; | 744 | host = sc->device->host; |
742 | session = iscsi_hostdata(host->hostdata); | 745 | session = iscsi_hostdata(host->hostdata); |
@@ -801,9 +804,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
801 | 804 | ||
802 | list_add_tail(&ctask->running, &conn->xmitqueue); | 805 | list_add_tail(&ctask->running, &conn->xmitqueue); |
803 | debug_scsi( | 806 | debug_scsi( |
804 | "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", | 807 | "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d " |
808 | "win %d]\n", | ||
805 | sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", | 809 | sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", |
806 | conn->id, (long)sc, ctask->itt, sc->request_bufflen, | 810 | conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen, |
807 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); | 811 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); |
808 | spin_unlock(&session->lock); | 812 | spin_unlock(&session->lock); |
809 | 813 | ||
@@ -1134,11 +1138,24 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1134 | 1138 | ||
1135 | int iscsi_eh_abort(struct scsi_cmnd *sc) | 1139 | int iscsi_eh_abort(struct scsi_cmnd *sc) |
1136 | { | 1140 | { |
1137 | struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; | 1141 | struct iscsi_cmd_task *ctask; |
1138 | struct iscsi_conn *conn = ctask->conn; | 1142 | struct iscsi_conn *conn; |
1139 | struct iscsi_session *session = conn->session; | 1143 | struct iscsi_session *session; |
1140 | int rc; | 1144 | int rc; |
1141 | 1145 | ||
1146 | /* | ||
1147 | * if session was ISCSI_STATE_IN_RECOVERY then we may not have | ||
1148 | * got the command. | ||
1149 | */ | ||
1150 | if (!sc->SCp.ptr) { | ||
1151 | debug_scsi("sc never reached iscsi layer or it completed.\n"); | ||
1152 | return SUCCESS; | ||
1153 | } | ||
1154 | |||
1155 | ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; | ||
1156 | conn = ctask->conn; | ||
1157 | session = conn->session; | ||
1158 | |||
1142 | conn->eh_abort_cnt++; | 1159 | conn->eh_abort_cnt++; |
1143 | debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); | 1160 | debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); |
1144 | 1161 | ||