From: miod Date: Wed, 14 Jan 2015 21:17:09 +0000 (+0000) Subject: When a read or write operation fails on a sector found on the bad block table, X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c237c638190ec928708ee2df027dc46c0ab41c87;p=openbsd When a read or write operation fails on a sector found on the bad block table, be sure to adjust the IOPB data pointer before redirecting the I/O for this particular sector to the replacement location. Otherwise, the data pointer still points to the first sector of the I/O, which may not necessarily be the one which failed. (This is yet another 19 years old bug, making your filesystems self-destruct even faster than intended) --- diff --git a/sys/arch/sparc/dev/xd.c b/sys/arch/sparc/dev/xd.c index 8d1c1196c73..3ec02b03d6e 100644 --- a/sys/arch/sparc/dev/xd.c +++ b/sys/arch/sparc/dev/xd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xd.c,v 1.68 2015/01/14 21:14:49 miod Exp $ */ +/* $OpenBSD: xd.c,v 1.69 2015/01/14 21:17:09 miod Exp $ */ /* $NetBSD: xd.c,v 1.37 1997/07/29 09:58:16 fair Exp $ */ /* @@ -1985,6 +1985,7 @@ xdc_error(xdcsc, iorq, iopb, rqno, comm) * standard */ iopb->headno = i % iorq->xd->nhead; iopb->sectno = i / iorq->xd->nhead; + iopb->daddr = (u_long) iorq->dbuf - DVMA_BASE; XDC_HWAIT(xdcsc, rqno); xdc_start(xdcsc, 1); /* resubmit */ return (XD_ERR_AOK); /* recovered! */ diff --git a/sys/arch/sparc/dev/xy.c b/sys/arch/sparc/dev/xy.c index e776a59d03d..e930135a3e8 100644 --- a/sys/arch/sparc/dev/xy.c +++ b/sys/arch/sparc/dev/xy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xy.c,v 1.65 2015/01/14 21:14:49 miod Exp $ */ +/* $OpenBSD: xy.c,v 1.66 2015/01/14 21:17:09 miod Exp $ */ /* $NetBSD: xy.c,v 1.26 1997/07/19 21:43:56 pk Exp $ */ /* @@ -1825,6 +1825,7 @@ xyc_error(xycsc, iorq, iopb, comm) int errno = iorq->errno; int erract = xyc_entoact(errno); int oldmode, advance, i; + u_long addr; if (erract == XY_ERA_RSET) { /* some errors require a reset */ oldmode = iorq->mode; @@ -1853,6 +1854,11 @@ xyc_error(xycsc, iorq, iopb, comm) * standard */ iopb->head = i % iorq->xy->nhead; iopb->sect = i / iorq->xy->nhead; + + addr = (u_long) iorq->dbuf - DVMA_BASE; + iopb->dataa = (addr & 0xffff); + iopb->datar = ((addr & 0xff0000) >> 16); + /* will resubmit when we come out of remove_iorq */ return (XY_ERR_AOK); /* recovered! */ }