lkml.org 
[lkml]   [2007]   [May]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] libata: fix shutdown warning message printing
    Unlocking ap->lock and ssleeping don't work because SCSI commands can
    be issued from completion path without context. Reimplement delayed
    completion by allowing translation functions to override
    qc->scsidone(), storing the original completion function to
    scmd->scsi_done() and overriding qc->scsidone() with a function which
    schedules delayed invocation of scmd->scsi_done().

    This isn't pretty at all but all the ugly parts are thankfully
    contained in the stop translation path where the compat feature is
    implemented.

    Signed-off-by: Tejun Heo <htejun@gmail.com>

    diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
    index dd81fa7..07b5a3d 100644
    --- a/drivers/ata/libata-scsi.c
    +++ b/drivers/ata/libata-scsi.c
    @@ -893,6 +893,23 @@ int ata_scsi_change_queue_depth(struct s
    return queue_depth;
    }

    +/* XXX: for ata_spindown_compat */
    +static void ata_delayed_done_timerfn(unsigned long arg)
    +{
    + struct scsi_cmnd *scmd = (void *)arg;
    +
    + scmd->scsi_done(scmd);
    +}
    +
    +/* XXX: for ata_spindown_compat */
    +static void ata_delayed_done(struct scsi_cmnd *scmd)
    +{
    + static struct timer_list timer;
    +
    + setup_timer(&timer, ata_delayed_done_timerfn, (unsigned long)scmd);
    + mod_timer(&timer, jiffies + 5 * HZ);
    +}
    +
    /**
    * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
    * @qc: Storage for translated ATA taskfile
    @@ -952,19 +969,21 @@ static unsigned int ata_scsi_start_stop_
    if (ata_spindown_compat &&
    (system_state == SYSTEM_HALT ||
    system_state == SYSTEM_POWER_OFF)) {
    - static int warned = 0;
    + static unsigned long warned = 0;

    - if (!warned) {
    - spin_unlock_irq(qc->ap->lock);
    + if (!test_and_set_bit(0, &warned)) {
    ata_dev_printk(qc->dev, KERN_WARNING,
    "DISK MIGHT NOT BE SPUN DOWN PROPERLY. "
    "UPDATE SHUTDOWN UTILITY\n");
    ata_dev_printk(qc->dev, KERN_WARNING,
    "For more info, visit "
    "http://linux-ata.org/shutdown.html\n");
    - warned = 1;
    - ssleep(5);
    - spin_lock_irq(qc->ap->lock);
    +
    + /* ->scsi_done is not used, use it for
    + * delayed completion.
    + */
    + scmd->scsi_done = qc->scsidone;
    + qc->scsidone = ata_delayed_done;
    }
    scmd->result = SAM_STAT_GOOD;
    return 1;
    @@ -1488,14 +1507,14 @@ static int ata_scsi_translate(struct ata

    early_finish:
    ata_qc_free(qc);
    - done(cmd);
    + qc->scsidone(cmd);
    DPRINTK("EXIT - early finish (good or error)\n");
    return 0;

    err_did:
    ata_qc_free(qc);
    cmd->result = (DID_ERROR << 16);
    - done(cmd);
    + qc->scsidone(cmd);
    err_mem:
    DPRINTK("EXIT - internal\n");
    return 0;
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2007-05-14 17:29    [W:0.025 / U:1.296 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site