Skip to content

Commit 8d899e7

Browse files
Mark LordJeff Garzik
authored andcommitted
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: Mark Lord <[email protected]> Signed-off-by: Jeff Garzik <[email protected]>
1 parent cd00608 commit 8d899e7

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

drivers/ata/libata-eh.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,26 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
20462046
return action;
20472047
}
20482048

2049+
/**
2050+
* ata_eh_worth_retry - analyze error and decide whether to retry
2051+
* @qc: qc to possibly retry
2052+
*
2053+
* Look at the cause of the error and decide if a retry
2054+
* might be useful or not. We don't want to retry media errors
2055+
* because the drive itself has probably already taken 10-30 seconds
2056+
* doing its own internal retries before reporting the failure.
2057+
*/
2058+
static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
2059+
{
2060+
if (qc->flags & AC_ERR_MEDIA)
2061+
return 0; /* don't retry media errors */
2062+
if (qc->flags & ATA_QCFLAG_IO)
2063+
return 1; /* otherwise retry anything from fs stack */
2064+
if (qc->err_mask & AC_ERR_INVALID)
2065+
return 0; /* don't retry these */
2066+
return qc->err_mask != AC_ERR_DEV; /* retry if not dev error */
2067+
}
2068+
20492069
/**
20502070
* ata_eh_link_autopsy - analyze error and determine recovery action
20512071
* @link: host link to perform autopsy on
@@ -2120,9 +2140,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
21202140
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
21212141

21222142
/* determine whether the command is worth retrying */
2123-
if (qc->flags & ATA_QCFLAG_IO ||
2124-
(!(qc->err_mask & AC_ERR_INVALID) &&
2125-
qc->err_mask != AC_ERR_DEV))
2143+
if (ata_eh_worth_retry(qc))
21262144
qc->flags |= ATA_QCFLAG_RETRY;
21272145

21282146
/* accumulate error info */

0 commit comments

Comments
 (0)