Commit 8d899e70 authored by Mark Lord's avatar Mark Lord Committed by Jeff Garzik

libata-eh don't waste time retrying media errors (v3)

ATA and SATA drives have had built-in retries for media errors
for as long as they've been commonplace in computers (early 1990s).

When libata stumbles across a bad sector, it can waste minutes
sitting there doing retry after retry before finally giving up
and letting the higher layers deal with it.

This patch removes retries for media errors only.
Signed-off-by: default avatarMark Lord <mlord@pobox.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent cd006086
...@@ -2046,6 +2046,26 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, ...@@ -2046,6 +2046,26 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
return action; return action;
} }
/**
* ata_eh_worth_retry - analyze error and decide whether to retry
* @qc: qc to possibly retry
*
* Look at the cause of the error and decide if a retry
* might be useful or not. We don't want to retry media errors
* because the drive itself has probably already taken 10-30 seconds
* doing its own internal retries before reporting the failure.
*/
static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
{
if (qc->flags & AC_ERR_MEDIA)
return 0; /* don't retry media errors */
if (qc->flags & ATA_QCFLAG_IO)
return 1; /* otherwise retry anything from fs stack */
if (qc->err_mask & AC_ERR_INVALID)
return 0; /* don't retry these */
return qc->err_mask != AC_ERR_DEV; /* retry if not dev error */
}
/** /**
* ata_eh_link_autopsy - analyze error and determine recovery action * ata_eh_link_autopsy - analyze error and determine recovery action
* @link: host link to perform autopsy on * @link: host link to perform autopsy on
...@@ -2120,9 +2140,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) ...@@ -2120,9 +2140,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
/* determine whether the command is worth retrying */ /* determine whether the command is worth retrying */
if (qc->flags & ATA_QCFLAG_IO || if (ata_eh_worth_retry(qc))
(!(qc->err_mask & AC_ERR_INVALID) &&
qc->err_mask != AC_ERR_DEV))
qc->flags |= ATA_QCFLAG_RETRY; qc->flags |= ATA_QCFLAG_RETRY;
/* accumulate error info */ /* accumulate error info */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment