]> err.no Git - linux-2.6/commitdiff
[SCSI] libiscsi: check that command ptr is set before accessing it
authorMike Christie <michaelc@cs.wisc.edu>
Thu, 31 Aug 2006 22:09:33 +0000 (18:09 -0400)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Sat, 2 Sep 2006 18:37:36 +0000 (13:37 -0500)
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>
drivers/scsi/libiscsi.c

index 864c6284e83c36dcf430f5e4a61c965f6fff8a62..12b5c1800740dae36d6aab0f7bea64ed2a96f87a 100644 (file)
@@ -192,6 +192,8 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
 
        ctask->state = ISCSI_TASK_COMPLETED;
        ctask->sc = NULL;
+       /* SCSI eh reuses commands to verify us */
+       sc->SCp.ptr = NULL;
        list_del_init(&ctask->running);
        __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
        sc->scsi_done(sc);
@@ -737,6 +739,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 
        sc->scsi_done = done;
        sc->result = 0;
+       sc->SCp.ptr = NULL;
 
        host = sc->device->host;
        session = iscsi_hostdata(host->hostdata);
@@ -801,9 +804,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 
        list_add_tail(&ctask->running, &conn->xmitqueue);
        debug_scsi(
-              "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
+              "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d "
+               "win %d]\n",
                sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
-               conn->id, (long)sc, ctask->itt, sc->request_bufflen,
+               conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
                session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
        spin_unlock(&session->lock);
 
@@ -1134,11 +1138,24 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
 
 int iscsi_eh_abort(struct scsi_cmnd *sc)
 {
-       struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
-       struct iscsi_conn *conn = ctask->conn;
-       struct iscsi_session *session = conn->session;
+       struct iscsi_cmd_task *ctask;
+       struct iscsi_conn *conn;
+       struct iscsi_session *session;
        int rc;
 
+       /*
+        * if session was ISCSI_STATE_IN_RECOVERY then we may not have
+        * got the command.
+        */
+       if (!sc->SCp.ptr) {
+               debug_scsi("sc never reached iscsi layer or it completed.\n");
+               return SUCCESS;
+       }
+
+       ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+       conn = ctask->conn;
+       session = conn->session;
+
        conn->eh_abort_cnt++;
        debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);