* libata: a fix and a cleanup @ 2015-10-03 17:21 Christoph Hellwig 2015-10-03 17:21 ` [PATCH 1/2] libata: only call ->done once all per-tag ressources are released Christoph Hellwig 2015-10-03 17:21 ` [PATCH 2/2] libata: cleanup ata_scsi_qc_complete Christoph Hellwig 0 siblings, 2 replies; 9+ messages in thread From: Christoph Hellwig @ 2015-10-03 17:21 UTC (permalink / raw) To: linux-ide The first patch fixes order of command completion vs tag freeing, and the second is a trivial cleanup of something I noticed while digging into that area. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] libata: only call ->done once all per-tag ressources are released 2015-10-03 17:21 libata: a fix and a cleanup Christoph Hellwig @ 2015-10-03 17:21 ` Christoph Hellwig 2015-10-04 17:34 ` Tejun Heo 2015-10-03 17:21 ` [PATCH 2/2] libata: cleanup ata_scsi_qc_complete Christoph Hellwig 1 sibling, 1 reply; 9+ messages in thread From: Christoph Hellwig @ 2015-10-03 17:21 UTC (permalink / raw) To: linux-ide Without this the SCSI midlayer can race and queue another command before the tag data has been released, which could lead to incorrect manipulation of the ata command state. Signed-off-by: Christoph Hellwig <hch@lst.de> --- drivers/ata/libata-scsi.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0d7f0da..8445620 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1757,6 +1757,15 @@ nothing_to_do: return 1; } +static void ata_qc_done(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + void (*done)(struct scsi_cmnd *) = qc->scsidone; + + ata_qc_free(qc); + done(cmd); +} + static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -1793,9 +1802,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) if (need_sense && !ap->ops->error_handler) ata_dump_status(ap->print_id, &qc->result_tf); - qc->scsidone(cmd); - - ata_qc_free(qc); + ata_qc_done(qc); } /** @@ -2594,8 +2601,7 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc) ata_gen_passthru_sense(qc); } - qc->scsidone(qc->scsicmd); - ata_qc_free(qc); + ata_qc_done(qc); } /* is it pointless to prefer PIO for "safety reasons"? */ @@ -2690,8 +2696,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) qc->dev->sdev->locked = 0; qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; - qc->scsidone(cmd); - ata_qc_free(qc); + ata_qc_done(qc); return; } @@ -2735,8 +2740,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) cmd->result = SAM_STAT_GOOD; } - qc->scsidone(cmd); - ata_qc_free(qc); + ata_qc_done(qc); } /** * atapi_xlat - Initialize PACKET taskfile -- 1.9.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] libata: only call ->done once all per-tag ressources are released 2015-10-03 17:21 ` [PATCH 1/2] libata: only call ->done once all per-tag ressources are released Christoph Hellwig @ 2015-10-04 17:34 ` Tejun Heo 2015-10-05 6:01 ` Christoph Hellwig 2015-10-08 8:25 ` [PATCH 1/2 v2] " Christoph Hellwig 0 siblings, 2 replies; 9+ messages in thread From: Tejun Heo @ 2015-10-04 17:34 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linux-ide Hello, Christoph. On Sat, Oct 03, 2015 at 07:21:10PM +0200, Christoph Hellwig wrote: > Without this the SCSI midlayer can race and queue another command > before the tag data has been released, which could lead to incorrect > manipulation of the ata command state. > > Signed-off-by: Christoph Hellwig <hch@lst.de> Hmmm... has this actually been observed? All these are run under ata port lock and so is the command issue path, so even if the tag gets reissued, it will have to wait till the completion path is done. Thanks. -- tejun ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] libata: only call ->done once all per-tag ressources are released 2015-10-04 17:34 ` Tejun Heo @ 2015-10-05 6:01 ` Christoph Hellwig 2015-10-06 17:28 ` Tejun Heo 2015-10-08 8:25 ` [PATCH 1/2 v2] " Christoph Hellwig 1 sibling, 1 reply; 9+ messages in thread From: Christoph Hellwig @ 2015-10-05 6:01 UTC (permalink / raw) To: Tejun Heo; +Cc: Christoph Hellwig, linux-ide On Sun, Oct 04, 2015 at 01:34:29PM -0400, Tejun Heo wrote: > Hmmm... has this actually been observed? All these are run under ata > port lock and so is the command issue path, so even if the tag gets > reissued, it will have to wait till the completion path is done. No - I stumbled over this while trying to debug https://lkml.org/lkml/2015/6/25/620 (which could use some libata experience, btw), but it didn't help. I still would like to see it fixes as similar patterns in SCSI drivers have caused crashes. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] libata: only call ->done once all per-tag ressources are released 2015-10-05 6:01 ` Christoph Hellwig @ 2015-10-06 17:28 ` Tejun Heo 0 siblings, 0 replies; 9+ messages in thread From: Tejun Heo @ 2015-10-06 17:28 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linux-ide Hello, Christoph. On Mon, Oct 05, 2015 at 08:01:17AM +0200, Christoph Hellwig wrote: > On Sun, Oct 04, 2015 at 01:34:29PM -0400, Tejun Heo wrote: > > Hmmm... has this actually been observed? All these are run under ata > > port lock and so is the command issue path, so even if the tag gets > > reissued, it will have to wait till the completion path is done. > > No - I stumbled over this while trying to debug > https://lkml.org/lkml/2015/6/25/620 (which could use some libata experience, > btw), but it didn't help. I still would like to see it fixes as similar > patterns in SCSI drivers have caused crashes. So, given the locking, the bug doesn't exist. I don't think switching to a safer pattern is a bad thing but the patch needs updated description and comment explanining that it isn't a bug fix and the specific ordering isn't strictly necessary. Thanks. -- tejun ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2 v2] libata: only call ->done once all per-tag ressources are released 2015-10-04 17:34 ` Tejun Heo 2015-10-05 6:01 ` Christoph Hellwig @ 2015-10-08 8:25 ` Christoph Hellwig 2015-10-12 16:23 ` Tejun Heo 1 sibling, 1 reply; 9+ messages in thread From: Christoph Hellwig @ 2015-10-08 8:25 UTC (permalink / raw) To: Tejun Heo; +Cc: linux-ide When calling ->done before releasing resources we could run into a race where the SCSI midlayer sends another command and races with the resources beeing manipulated. For libata this can't currently happen as synchronization happens at a higher level, but I'd still like to fix it to future proof libata and to avoid copy & paste into SCSI drivers where this pattern has led to reproducible crashes. Signed-off-by: Christoph Hellwig <hch@lst.de> --- drivers/ata/libata-scsi.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0d7f0da..8445620 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1757,6 +1757,15 @@ nothing_to_do: return 1; } +static void ata_qc_done(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + void (*done)(struct scsi_cmnd *) = qc->scsidone; + + ata_qc_free(qc); + done(cmd); +} + static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -1793,9 +1802,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) if (need_sense && !ap->ops->error_handler) ata_dump_status(ap->print_id, &qc->result_tf); - qc->scsidone(cmd); - - ata_qc_free(qc); + ata_qc_done(qc); } /** @@ -2594,8 +2601,7 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc) ata_gen_passthru_sense(qc); } - qc->scsidone(qc->scsicmd); - ata_qc_free(qc); + ata_qc_done(qc); } /* is it pointless to prefer PIO for "safety reasons"? */ @@ -2690,8 +2696,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) qc->dev->sdev->locked = 0; qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; - qc->scsidone(cmd); - ata_qc_free(qc); + ata_qc_done(qc); return; } @@ -2735,8 +2740,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) cmd->result = SAM_STAT_GOOD; } - qc->scsidone(cmd); - ata_qc_free(qc); + ata_qc_done(qc); } /** * atapi_xlat - Initialize PACKET taskfile -- 1.9.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2 v2] libata: only call ->done once all per-tag ressources are released 2015-10-08 8:25 ` [PATCH 1/2 v2] " Christoph Hellwig @ 2015-10-12 16:23 ` Tejun Heo 0 siblings, 0 replies; 9+ messages in thread From: Tejun Heo @ 2015-10-12 16:23 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linux-ide On Thu, Oct 08, 2015 at 10:25:41AM +0200, Christoph Hellwig wrote: > When calling ->done before releasing resources we could run into a > race where the SCSI midlayer sends another command and races with > the resources beeing manipulated. For libata this can't currently > happen as synchronization happens at a higher level, but I'd still > like to fix it to future proof libata and to avoid copy & paste > into SCSI drivers where this pattern has led to reproducible crashes. > > Signed-off-by: Christoph Hellwig <hch@lst.de> Applied to libata/for-4.4. Thanks. -- tejun ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] libata: cleanup ata_scsi_qc_complete 2015-10-03 17:21 libata: a fix and a cleanup Christoph Hellwig 2015-10-03 17:21 ` [PATCH 1/2] libata: only call ->done once all per-tag ressources are released Christoph Hellwig @ 2015-10-03 17:21 ` Christoph Hellwig 2015-10-04 17:39 ` Tejun Heo 1 sibling, 1 reply; 9+ messages in thread From: Christoph Hellwig @ 2015-10-03 17:21 UTC (permalink / raw) To: linux-ide Remove an incorrect comment and untangle an if statement in ata_scsi_qc_complete. Signed-off-by: Christoph Hellwig <hch@lst.de> --- drivers/ata/libata-scsi.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8445620..7feceec 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1783,21 +1783,12 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE */ if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && - ((cdb[2] & 0x20) || need_sense)) { + ((cdb[2] & 0x20) || need_sense)) ata_gen_passthru_sense(qc); - } else { - if (!need_sense) { - cmd->result = SAM_STAT_GOOD; - } else { - /* TODO: decide which descriptor format to use - * for 48b LBA devices and call that here - * instead of the fixed desc, which is only - * good for smaller LBA (and maybe CHS?) - * devices. - */ - ata_gen_ata_sense(qc); - } - } + else if (need_sense) + ata_gen_ata_sense(qc); + else + cmd->result = SAM_STAT_GOOD; if (need_sense && !ap->ops->error_handler) ata_dump_status(ap->print_id, &qc->result_tf); -- 1.9.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] libata: cleanup ata_scsi_qc_complete 2015-10-03 17:21 ` [PATCH 2/2] libata: cleanup ata_scsi_qc_complete Christoph Hellwig @ 2015-10-04 17:39 ` Tejun Heo 0 siblings, 0 replies; 9+ messages in thread From: Tejun Heo @ 2015-10-04 17:39 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linux-ide On Sat, Oct 03, 2015 at 07:21:11PM +0200, Christoph Hellwig wrote: > Remove an incorrect comment and untangle an if statement in > ata_scsi_qc_complete. > > Signed-off-by: Christoph Hellwig <hch@lst.de> Applied to libata/for-4.4. Thanks. -- tejun ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-10-12 16:23 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-10-03 17:21 libata: a fix and a cleanup Christoph Hellwig 2015-10-03 17:21 ` [PATCH 1/2] libata: only call ->done once all per-tag ressources are released Christoph Hellwig 2015-10-04 17:34 ` Tejun Heo 2015-10-05 6:01 ` Christoph Hellwig 2015-10-06 17:28 ` Tejun Heo 2015-10-08 8:25 ` [PATCH 1/2 v2] " Christoph Hellwig 2015-10-12 16:23 ` Tejun Heo 2015-10-03 17:21 ` [PATCH 2/2] libata: cleanup ata_scsi_qc_complete Christoph Hellwig 2015-10-04 17:39 ` Tejun Heo
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.