Calling scsi_done() after the SCSI timer is fired

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi

I wonder if somebody could advice me. I am a SCSI LLDD developer. 
I have a question about an implementation of eh_abort_handler()
for SCSI hosts when SCSI command timer is fired. I may check out
the queue and look for a command given as an argument to abort. 
But, what I should do when the command is being processed. I can
not abort it halfway.

As I saw a statement to check if scmd->serial_number has been
cleared in scsi_try_to_abort_cmd, I got to think it makes sense
that let LLDD to keep processing the command and be going to call
scsi_done().

static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
{
        unsigned long flags;
        int rtn = FAILED;

        if (!scmd->device->host->hostt->eh_abort_handler)
                return rtn;

        /*
         * scsi_done was called just after the command timed out and
         * before
         * we had a chance to process it. (db)
         */
>>      if (scmd->serial_number == 0)
                return SUCCESS;

        scmd->owner = SCSI_OWNER_LOWLEVEL;

        spin_lock_irqsave(scmd->device->host->host_lock, flags);
        rtn = scmd->device->host->hostt->eh_abort_handler(scmd);
        spin_unlock_irqrestore(scmd->device->host->host_lock, flags);

        return rtn;
}

I soon realized this idea is wrong. Any calling scsi_done() isn't
significant after the timer is fired.


void scsi_done(struct scsi_cmnd *cmd)
{
        /*
         * We don't have to worry about this one timing out any more.
         * If we are unable to remove the timer, then the command
         * has already timed out.  In which case, we have no choice but
         * to
         * let the timeout function run, as we have no idea where in
         * fact
         * that function could really be.  It might be on another
         * processor,
         * etc, etc.
         */
        if (!scsi_delete_timer(cmd))
                return;
        __scsi_done(cmd);
}

int scsi_delete_timer(struct scsi_cmnd *scmd)
{
        int rtn;

        rtn = del_timer(&scmd->eh_timeout);

        SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
                                         " rtn: %d\n", __FUNCTION__,
                                         scmd, rtn));

        scmd->eh_timeout.data = (unsigned long)NULL;
        scmd->eh_timeout.function = NULL;

        return rtn;
}

LLDD calls scsi_done() and forget about the command. Therefore, I think
it could make sense to set cmd->serial_number = 0 in scsi_done() even
after the timer is fired.

void scsi_done(struct scsi_cmnd *cmd)
{

    ---- snip ----

        if (!scsi_delete_timer(cmd)) {
                cmd->serial_number = 0;
                return;
        }

        __scsi_done(cmd);
}


Or I should properly implement an error recovery function using
scsi_transport interface? I mean I return EH_HANDLED in
scmd->device->host->transportt->eh_timed_out(scmd)

Thanks and regrds,


Hiroki Takada

-- 
----------------------------------------------------------
Hiroki Takada <takada@xxxxxxxxxxxx>
Engineering Development Group, Super Storage Div. 
Core Micro Systems Inc.
2-22-2, Koishikawa, Bunkyo-Ku, Tokyo 112-0002
TEL : +81-50-5558-5410  (IP Phone)
TEL : +81-3-5802-6872  / FAX : +81-3-5802-5113
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux