From: Igor Pylypiv <ipylypiv@google.com>
To: Damien Le Moal <dlemoal@kernel.org>
Cc: Niklas Cassel <cassel@kernel.org>, Tejun Heo <tj@kernel.org>,
Hannes Reinecke <hare@suse.de>,
linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: Re: [PATCH v3 2/6] ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1
Date: Thu, 27 Jun 2024 20:55:57 +0000 [thread overview]
Message-ID: <Zn3R3R_xJFvyNJU-@google.com> (raw)
In-Reply-To: <785a0460-36d5-4e4a-99ea-114081c55bc7@kernel.org>
On Thu, Jun 27, 2024 at 09:16:09AM +0900, Damien Le Moal wrote:
> On 6/27/24 08:04, Igor Pylypiv wrote:
> > Current ata_gen_passthru_sense() code performs two actions:
> > 1. Generates sense data based on the ATA 'status' and ATA 'error' fields.
> > 2. Populates "ATA Status Return sense data descriptor" / "Fixed format
> > sense data" with ATA taskfile fields.
> >
> > The problem is that #1 generates sense data even when a valid sense data
> > is already present (ATA_QCFLAG_SENSE_VALID is set). Factoring out #2 into
> > a separate function allows us to generate sense data only when there is
> > no valid sense data (ATA_QCFLAG_SENSE_VALID is not set).
> >
> > As a bonus, we can now delete a FIXME comment in atapi_qc_complete()
> > which states that we don't want to translate taskfile registers into
> > sense descriptors for ATAPI.
> >
> > Cc: stable@vger.kernel.org
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
> > Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
>
> I wonder if we can find the patch that introduced the bug in the first place so
> that we can add a Fixes tag. I have not checked. This may have been wrong since
> a long time ago...
This code was first introduced in 2005 in commit b095518ef51c3 ("[libata]
ATA passthru (arbitrary ATA command execution)").
ATA_QCFLAG_SENSE_VALID was introduced a year later in commit 9ec957f2002b
("[PATCH] libata-eh-fw: add flags and operations for new EH").
IIUC, ATA_QCFLAG_SENSE_VALID has not been set for ATA drives until 2016
when the support for fetching the sense data was added in 5b01e4b9efa0
("libata: Implement NCQ autosense") and commit e87fd28cf9a2d ("libata:
Implement support for sense data reporting").
To me none of the commits looks like a good candidate for the Fixes tag.
What are your thoughts on this?
>
> > ---
> > drivers/ata/libata-scsi.c | 158 +++++++++++++++++++++-----------------
> > 1 file changed, 86 insertions(+), 72 deletions(-)
> >
> > diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> > index a9e44ad4c2de..26b1263f5c7c 100644
> > --- a/drivers/ata/libata-scsi.c
> > +++ b/drivers/ata/libata-scsi.c
> > @@ -230,6 +230,80 @@ void ata_scsi_set_sense_information(struct ata_device *dev,
> > SCSI_SENSE_BUFFERSIZE, information);
> > }
> >
> > +/**
> > + * ata_scsi_set_passthru_sense_fields - Set ATA fields in sense buffer
> > + * @qc: ATA PASS-THROUGH command.
> > + *
> > + * Populates "ATA Status Return sense data descriptor" / "Fixed format
> > + * sense data" with ATA taskfile fields.
> > + *
> > + * LOCKING:
> > + * None.
> > + */
> > +static void ata_scsi_set_passthru_sense_fields(struct ata_queued_cmd *qc)
> > +{
> > + struct scsi_cmnd *cmd = qc->scsicmd;
> > + struct ata_taskfile *tf = &qc->result_tf;
> > + unsigned char *sb = cmd->sense_buffer;
> > +
> > + if ((sb[0] & 0x7f) >= 0x72) {
> > + unsigned char *desc;
> > + u8 len;
> > +
> > + /* descriptor format */
> > + len = sb[7];
> > + desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
> > + if (!desc) {
> > + if (SCSI_SENSE_BUFFERSIZE < len + 14)
> > + return;
> > + sb[7] = len + 14;
> > + desc = sb + 8 + len;
> > + }
> > + desc[0] = 9;
> > + desc[1] = 12;
> > + /*
> > + * Copy registers into sense buffer.
> > + */
> > + desc[2] = 0x00;
> > + desc[3] = tf->error;
> > + desc[5] = tf->nsect;
> > + desc[7] = tf->lbal;
> > + desc[9] = tf->lbam;
> > + desc[11] = tf->lbah;
> > + desc[12] = tf->device;
> > + desc[13] = tf->status;
> > +
> > + /*
> > + * Fill in Extend bit, and the high order bytes
> > + * if applicable.
> > + */
> > + if (tf->flags & ATA_TFLAG_LBA48) {
> > + desc[2] |= 0x01;
> > + desc[4] = tf->hob_nsect;
> > + desc[6] = tf->hob_lbal;
> > + desc[8] = tf->hob_lbam;
> > + desc[10] = tf->hob_lbah;
> > + }
> > + } else {
> > + /* Fixed sense format */
> > + sb[0] |= 0x80;
> > + sb[3] = tf->error;
> > + sb[4] = tf->status;
> > + sb[5] = tf->device;
> > + sb[6] = tf->nsect;
> > + if (tf->flags & ATA_TFLAG_LBA48) {
> > + sb[8] |= 0x80;
> > + if (tf->hob_nsect)
> > + sb[8] |= 0x40;
> > + if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
> > + sb[8] |= 0x20;
> > + }
> > + sb[9] = tf->lbal;
> > + sb[10] = tf->lbam;
> > + sb[11] = tf->lbah;
> > + }
> > +}
> > +
> > static void ata_scsi_set_invalid_field(struct ata_device *dev,
> > struct scsi_cmnd *cmd, u16 field, u8 bit)
> > {
> > @@ -837,10 +911,8 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
> > * ata_gen_passthru_sense - Generate check condition sense block.
> > * @qc: Command that completed.
> > *
> > - * This function is specific to the ATA descriptor format sense
> > - * block specified for the ATA pass through commands. Regardless
> > - * of whether the command errored or not, return a sense
> > - * block. Copy all controller registers into the sense
> > + * This function is specific to the ATA pass through commands.
> > + * Regardless of whether the command errored or not, return a sense
> > * block. If there was no error, we get the request from an ATA
> > * passthrough command, so we use the following sense data:
> > * sk = RECOVERED ERROR
> > @@ -875,63 +947,6 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> > */
> > scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
> > }
> > -
> > - if ((sb[0] & 0x7f) >= 0x72) {
> > - unsigned char *desc;
> > - u8 len;
> > -
> > - /* descriptor format */
> > - len = sb[7];
> > - desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
> > - if (!desc) {
> > - if (SCSI_SENSE_BUFFERSIZE < len + 14)
> > - return;
> > - sb[7] = len + 14;
> > - desc = sb + 8 + len;
> > - }
> > - desc[0] = 9;
> > - desc[1] = 12;
> > - /*
> > - * Copy registers into sense buffer.
> > - */
> > - desc[2] = 0x00;
> > - desc[3] = tf->error;
> > - desc[5] = tf->nsect;
> > - desc[7] = tf->lbal;
> > - desc[9] = tf->lbam;
> > - desc[11] = tf->lbah;
> > - desc[12] = tf->device;
> > - desc[13] = tf->status;
> > -
> > - /*
> > - * Fill in Extend bit, and the high order bytes
> > - * if applicable.
> > - */
> > - if (tf->flags & ATA_TFLAG_LBA48) {
> > - desc[2] |= 0x01;
> > - desc[4] = tf->hob_nsect;
> > - desc[6] = tf->hob_lbal;
> > - desc[8] = tf->hob_lbam;
> > - desc[10] = tf->hob_lbah;
> > - }
> > - } else {
> > - /* Fixed sense format */
> > - sb[0] |= 0x80;
> > - sb[3] = tf->error;
> > - sb[4] = tf->status;
> > - sb[5] = tf->device;
> > - sb[6] = tf->nsect;
> > - if (tf->flags & ATA_TFLAG_LBA48) {
> > - sb[8] |= 0x80;
> > - if (tf->hob_nsect)
> > - sb[8] |= 0x40;
> > - if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
> > - sb[8] |= 0x20;
> > - }
> > - sb[9] = tf->lbal;
> > - sb[10] = tf->lbam;
> > - sb[11] = tf->lbah;
> > - }
> > }
> >
> > /**
> > @@ -1634,6 +1649,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
> > u8 *cdb = cmd->cmnd;
> > int need_sense = (qc->err_mask != 0) &&
> > !(qc->flags & ATA_QCFLAG_SENSE_VALID);
> > + int need_passthru_sense = (qc->err_mask != 0) ||
> > + (qc->flags & ATA_QCFLAG_SENSE_VALID);
> >
> > /* For ATA pass thru (SAT) commands, generate a sense block if
> > * user mandated it or if there's an error. Note that if we
> > @@ -1645,13 +1662,16 @@ 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))
> > - ata_gen_passthru_sense(qc);
> > - else if (need_sense)
> > + ((cdb[2] & 0x20) || need_passthru_sense)) {
> > + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
> > + ata_gen_passthru_sense(qc);
> > + ata_scsi_set_passthru_sense_fields(qc);
> > + } else if (need_sense) {
> > ata_gen_ata_sense(qc);
> > - else
> > + } else {
> > /* Keep the SCSI ML and status byte, clear host byte. */
> > cmd->result &= 0x0000ffff;
> > + }
> >
> > ata_qc_done(qc);
> > }
> > @@ -2590,14 +2610,8 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
> > /* handle completion from EH */
> > if (unlikely(err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID)) {
> >
> > - if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
> > - /* FIXME: not quite right; we don't want the
> > - * translation of taskfile registers into a
> > - * sense descriptors, since that's only
> > - * correct for ATA, not ATAPI
> > - */
> > + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
> > ata_gen_passthru_sense(qc);
> > - }
> >
> > /* SCSI EH automatically locks door if sdev->locked is
> > * set. Sometimes door lock request continues to
>
> --
> Damien Le Moal
> Western Digital Research
>
Thanks,
Igor
next prev parent reply other threads:[~2024-06-27 20:56 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-26 23:04 [PATCH v3 0/6] ATA PASS-THROUGH sense data fixes Igor Pylypiv
2024-06-26 23:04 ` [PATCH v3 1/6] ata: libata-scsi: Fix offsets for the fixed format sense data Igor Pylypiv
2024-06-27 12:08 ` Niklas Cassel
2024-06-27 21:21 ` Igor Pylypiv
2024-06-28 6:47 ` Hannes Reinecke
2024-06-28 15:49 ` Niklas Cassel
2024-06-28 18:25 ` Niklas Cassel
2024-06-28 23:17 ` Igor Pylypiv
2024-06-26 23:04 ` [PATCH v3 2/6] ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1 Igor Pylypiv
2024-06-27 0:16 ` Damien Le Moal
2024-06-27 20:55 ` Igor Pylypiv [this message]
2024-06-28 3:48 ` Damien Le Moal
2024-06-27 14:14 ` Niklas Cassel
2024-06-27 15:15 ` Niklas Cassel
2024-06-27 21:54 ` Igor Pylypiv
2024-06-28 18:44 ` Niklas Cassel
2024-06-28 23:31 ` Igor Pylypiv
2024-06-29 3:09 ` Niklas Cassel
2024-07-01 20:00 ` Igor Pylypiv
2024-06-26 23:04 ` [PATCH v3 3/6] ata: libata-scsi: Remove redundant sense_buffer memsets Igor Pylypiv
2024-06-26 23:04 ` [PATCH v3 4/6] ata: libata-scsi: Do not pass ATA device id to ata_to_sense_error() Igor Pylypiv
2024-06-26 23:04 ` [PATCH v3 5/6] ata: libata: Set ATA_QCFLAG_RTF_FILLED in fill_result_tf() Igor Pylypiv
2024-06-28 20:12 ` Niklas Cassel
2024-06-28 23:08 ` Igor Pylypiv
2024-06-26 23:04 ` [PATCH v3 6/6] ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf Igor Pylypiv
2024-06-27 0:19 ` Damien Le Moal
2024-06-27 22:03 ` Igor Pylypiv
2024-06-27 6:16 ` Hannes Reinecke
2024-06-28 19:42 ` Niklas Cassel
2024-06-28 23:15 ` Igor Pylypiv
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zn3R3R_xJFvyNJU-@google.com \
--to=ipylypiv@google.com \
--cc=cassel@kernel.org \
--cc=dlemoal@kernel.org \
--cc=hare@suse.de \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.