diff options
author | grog <grog@FreeBSD.org> | 2001-05-22 02:31:08 +0000 |
---|---|---|
committer | grog <grog@FreeBSD.org> | 2001-05-22 02:31:08 +0000 |
commit | aa9ab5296b71394518487f31cde37fa4e0702ce6 (patch) | |
tree | 016f0094b254b41c3d4f9cefa635b3fd6bfbdc24 /sys/dev | |
parent | 0e53f607e9ec4a2cfddabc6ebb5c3cda7338ae62 (diff) | |
download | FreeBSD-src-aa9ab5296b71394518487f31cde37fa4e0702ce6.zip FreeBSD-src-aa9ab5296b71394518487f31cde37fa4e0702ce6.tar.gz |
complete_rqe:
In case of error, check the VF_RETRYERRORS flag in the subdisk and
don't take the subdisk down if it's set, just retry the I/O.
Requested by: peter
If the buffer has been copied (XFR_COPYBUF), release the copied
buffer when the I/O completes.
Suggested by: alfred
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/vinum/vinuminterrupt.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/sys/dev/vinum/vinuminterrupt.c b/sys/dev/vinum/vinuminterrupt.c index d5ce417..461c06b 100644 --- a/sys/dev/vinum/vinuminterrupt.c +++ b/sys/dev/vinum/vinuminterrupt.c @@ -39,7 +39,7 @@ * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * - * $Id: vinuminterrupt.c,v 1.9 2000/02/16 01:59:02 grog Exp grog $ + * $Id: vinuminterrupt.c,v 1.12 2000/11/24 03:41:42 grog Exp grog $ * $FreeBSD$ */ @@ -67,6 +67,8 @@ complete_rqe(struct buf *bp) struct rqgroup *rqg; struct buf *ubp; /* user buffer */ struct drive *drive; + struct sd *sd; + char *gravity; /* for error messages */ rqe = (struct rqelement *) bp; /* point to the element element that completed */ rqg = rqe->rqg; /* and the request group */ @@ -84,20 +86,48 @@ complete_rqe(struct buf *bp) ||(vinum_conf.active == VINUM_MAXACTIVE)) /* or the global limit */ wakeup(&launch_requests); /* let another one at it */ if ((bp->b_io.bio_flags & BIO_ERROR) != 0) { /* transfer in error */ + gravity = ""; + sd = &SD[rqe->sdno]; + if (bp->b_error != 0) /* did it return a number? */ rq->error = bp->b_error; /* yes, put it in. */ else if (rq->error == 0) /* no: do we have one already? */ rq->error = EIO; /* no: catchall "I/O error" */ - SD[rqe->sdno].lasterror = rq->error; + sd->lasterror = rq->error; if (bp->b_iocmd == BIO_READ) { /* read operation */ - log(LOG_ERR, "%s: fatal read I/O error\n", SD[rqe->sdno].name); - set_sd_state(rqe->sdno, sd_crashed, setstate_force); /* subdisk is crashed */ + if ((rq->error == ENXIO) || (sd->flags & VF_RETRYERRORS) == 0) { + gravity = " fatal"; + set_sd_state(rqe->sdno, sd_crashed, setstate_force); /* subdisk is crashed */ + } + log(LOG_ERR, + "%s:%s read error, block %d for %ld bytes\n", + gravity, + sd->name, + bp->b_blkno, + bp->b_bcount); } else { /* write operation */ - log(LOG_ERR, "%s: fatal write I/O error\n", SD[rqe->sdno].name); - set_sd_state(rqe->sdno, sd_stale, setstate_force); /* subdisk is stale */ + if ((rq->error == ENXIO) || (sd->flags & VF_RETRYERRORS) == 0) { + gravity = "fatal "; + set_sd_state(rqe->sdno, sd_stale, setstate_force); /* subdisk is stale */ + } + log(LOG_ERR, + "%s:%s write error, block %d for %ld bytes\n", + gravity, + sd->name, + bp->b_blkno, + bp->b_bcount); } + log(LOG_ERR, + "%s: user buffer block %d for %ld bytes\n", + sd->name, + ubp->b_blkno, + ubp->b_bcount); if (rq->error == ENXIO) { /* the drive's down too */ - log(LOG_ERR, "%s: fatal drive I/O error\n", DRIVE[rqe->driveno].label.name); + log(LOG_ERR, + "%s: fatal drive I/O error, block %d for %ld bytes\n", + DRIVE[rqe->driveno].label.name, + bp->b_blkno, + bp->b_bcount); DRIVE[rqe->driveno].lasterror = rq->error; set_drive_state(rqe->driveno, /* take the drive down */ drive_down, @@ -192,6 +222,10 @@ complete_rqe(struct buf *bp) ubp->b_resid = 0; /* completed our transfer */ if (rq->isplex == 0) /* volume request, */ VOL[rq->volplex.volno].active--; /* another request finished */ + if (rq->flags & XFR_COPYBUF) { + Free(ubp->b_data); + ubp->b_data = rq->save_data; + } bufdone(ubp); /* top level buffer completed */ freerq(rq); /* return the request storage */ } |