2007-05-14 15:26:41

by Tejun Heo

[permalink] [raw]
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 <[email protected]>

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;


2007-05-14 15:45:23

by James Bottomley

[permalink] [raw]
Subject: Re: [PATCH] libata: fix shutdown warning message printing

On Mon, 2007-05-14 at 17:26 +0200, Tejun Heo wrote:
> 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 <[email protected]>

Heh, very clever, but a bit of a hack (however, no better way I can see
to do it given the layering constraints).

Acked-by: James Bottomley <[email protected]>

James


2007-05-16 05:22:19

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH] libata: fix shutdown warning message printing

Tejun Heo wrote:
> 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 <[email protected]>

applied to #upstream-fixes