Bug 7644 - Race: host lock is not acquired before calling ql_icmd
Summary: Race: host lock is not acquired before calling ql_icmd
Status: REJECTED INVALID
Alias: None
Product: SCSI Drivers
Classification: Unclassified
Component: Other (show other bugs)
Hardware: i386 Linux
: P2 normal
Assignee: scsi_drivers-other
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-12-06 16:11 UTC by Lin Tan
Modified: 2008-04-12 19:55 UTC (History)
2 users (show)

See Also:
Kernel Version: 2.6.19
Subsystem:
Regression: ---
Bisected commit-id:


Attachments

Description Lin Tan 2006-12-06 16:11:08 UTC
The caller of ql_icmd() should hold the host lock (from the head comments of
ql_icmd() shown below). But, the lock is not acquired in function
qlogicfas408_queuecommand(). All of these code is in file
drivers/scsi/qlogicfas408.c

/*
 *      Initiate scsi command - queueing handler 
 *      caller must hold host lock
 */

static void ql_icmd(struct scsi_cmnd *cmd)
{
        struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
        int     qbase = priv->qbase;
        int     int_type = priv->int_type;
        unsigned int i;

        priv->qabort = 0;

        REG0;
        /* clearing of interrupts and the fifo is needed */

 ...

------------------------------------------------------

int qlogicfas408_queuecommand(struct scsi_cmnd *cmd,
                              void (*done) (struct scsi_cmnd *))
{
        struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
        if (scmd_id(cmd) == priv->qinitid) {
                cmd->result = DID_BAD_TARGET << 16;
                done(cmd);
                return 0;
        }

        cmd->scsi_done = done;
        /* wait for the last command's interrupt to finish */
        while (priv->qlcmd != NULL) {
                barrier();
                cpu_relax();
        }
        ql_icmd(cmd);
        return 0;
}
Comment 1 Natalie Protasevich 2008-04-12 19:55:39 UTC
We do hold the lock in generic scsi code when call queuecommand.
in scsi_dispatch_cmd:

...
        spin_lock_irqsave(host->host_lock, flags);
        scsi_cmd_get_serial(host, cmd);

        if (unlikely(host->shost_state == SHOST_DEL)) {
                cmd->result = (DID_NO_CONNECT << 16);
                scsi_done(cmd);
        } else {
                rtn = host->hostt->queuecommand(cmd, scsi_done);
        }
        spin_unlock_irqrestore(host->host_lock, flags);
...

scsi_send)eh_command:

...
        spin_lock_irqsave(shost->host_lock, flags);
        scsi_log_send(scmd);
        shost->hostt->queuecommand(scmd, scsi_eh_done);
        spin_unlock_irqrestore(shost->host_lock, flags);
...

So it looks like we are good.

Note You need to log in before you can comment on or make changes to this bug.