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
This commit is contained in:
grog 2001-05-22 02:31:08 +00:00
parent 0e53f607e9
commit aa9ab5296b

View File

@ -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 */
}