In some case, when an error is reported by the disk, the ahci controller

still reports a number of bytes transfered equal to bcount.
This then triggers a KASSERT in physio_biodone:
        if (done == todo)
		KASSERT(bp->b_error == 0);
Detect this case in wd(4) (so that the workaround works for other controllers
too if they have the same issue, or if the issue is with the drive)
and claim we didn't read/write anything.
This commit is contained in:
bouyer 2012-06-26 09:49:24 +00:00
parent cb9b109d3a
commit 931da08bf7

View File

@ -1,4 +1,4 @@
/* $NetBSD: wd.c,v 1.392 2012/02/02 19:43:02 tls Exp $ */
/* $NetBSD: wd.c,v 1.393 2012/06/26 09:49:24 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.392 2012/02/02 19:43:02 tls Exp $");
__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.393 2012/06/26 09:49:24 bouyer Exp $");
#include "opt_ata.h"
@ -819,6 +819,14 @@ noerror: if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0)
bp->b_error = EIO;
break;
}
if (__predict_false(bp->b_error != 0) && bp->b_resid == 0) {
/*
* the disk or controller sometimes report a complete
* xfer, when there has been an error. This is wrong,
* assume nothing got transfered in this case
*/
bp->b_resid = bp->b_bcount;
}
disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
(bp->b_flags & B_READ));
rnd_add_uint32(&wd->rnd_source, bp->b_blkno);