1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Fix returning incorrect bio_resid value with failed BIO_DELETE requests.

Neither residual length reported for ATA/SCSI command nor one from another
BIO_DELETE request are in any way related to the value to be returned.
This commit is contained in:
Alexander Motin 2013-07-28 19:56:08 +00:00
parent 9fcd8e9ebd
commit 7651b989e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253752
2 changed files with 35 additions and 26 deletions

View File

@ -1684,6 +1684,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
struct ccb_ataio *ataio; struct ccb_ataio *ataio;
struct ccb_getdev *cgd; struct ccb_getdev *cgd;
struct cam_path *path; struct cam_path *path;
int state;
softc = (struct ada_softc *)periph->softc; softc = (struct ada_softc *)periph->softc;
ataio = &done_ccb->ataio; ataio = &done_ccb->ataio;
@ -1691,31 +1692,20 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("adadone\n")); CAM_DEBUG(path, CAM_DEBUG_TRACE, ("adadone\n"));
switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) { state = ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK;
switch (state) {
case ADA_CCB_BUFFER_IO: case ADA_CCB_BUFFER_IO:
case ADA_CCB_TRIM: case ADA_CCB_TRIM:
{ {
struct bio *bp; struct bio *bp;
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
int error; int error;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
error = adaerror(done_ccb, 0, 0); error = adaerror(done_ccb, 0, 0);
if (error == ERESTART) { if (error == ERESTART) {
/* A retry was scheduled, so just return. */ /* A retry was scheduled, so just return. */
return; return;
} }
if (error != 0) {
bp->bio_error = error;
bp->bio_resid = bp->bio_bcount;
bp->bio_flags |= BIO_ERROR;
} else {
bp->bio_resid = ataio->resid;
bp->bio_error = 0;
if (bp->bio_resid != 0)
bp->bio_flags |= BIO_ERROR;
}
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(path, cam_release_devq(path,
/*relsim_flags*/0, /*relsim_flags*/0,
@ -1725,15 +1715,25 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
} else { } else {
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
panic("REQ_CMP with QFRZN"); panic("REQ_CMP with QFRZN");
error = 0;
}
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
bp->bio_error = error;
if (error != 0) {
bp->bio_resid = bp->bio_bcount;
bp->bio_flags |= BIO_ERROR;
} else {
if (state == ADA_CCB_TRIM)
bp->bio_resid = 0;
else
bp->bio_resid = ataio->resid; bp->bio_resid = ataio->resid;
if (ataio->resid > 0) if (bp->bio_resid > 0)
bp->bio_flags |= BIO_ERROR; bp->bio_flags |= BIO_ERROR;
} }
softc->outstanding_cmds--; softc->outstanding_cmds--;
if (softc->outstanding_cmds == 0) if (softc->outstanding_cmds == 0)
softc->flags |= ADA_FLAG_WENT_IDLE; softc->flags |= ADA_FLAG_WENT_IDLE;
if ((ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) == if (state == ADA_CCB_TRIM) {
ADA_CCB_TRIM) {
struct trim_request *req = struct trim_request *req =
(struct trim_request *)ataio->data_ptr; (struct trim_request *)ataio->data_ptr;
int i; int i;
@ -1741,10 +1741,12 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) { for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) {
struct bio *bp1 = req->bps[i]; struct bio *bp1 = req->bps[i];
bp1->bio_resid = bp->bio_resid;
bp1->bio_error = bp->bio_error; bp1->bio_error = bp->bio_error;
if (bp->bio_flags & BIO_ERROR) if (bp->bio_flags & BIO_ERROR) {
bp1->bio_flags |= BIO_ERROR; bp1->bio_flags |= BIO_ERROR;
bp1->bio_resid = bp1->bio_bcount;
} else
bp1->bio_resid = 0;
biodone(bp1); biodone(bp1);
} }
softc->trim_running = 0; softc->trim_running = 0;

View File

@ -2921,6 +2921,9 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
bp->bio_flags |= BIO_ERROR; bp->bio_flags |= BIO_ERROR;
} }
} else if (bp != NULL) { } else if (bp != NULL) {
if (state == DA_CCB_DELETE)
bp->bio_resid = 0;
else
bp->bio_resid = csio->resid; bp->bio_resid = csio->resid;
bp->bio_error = 0; bp->bio_error = 0;
if (bp->bio_resid != 0) if (bp->bio_resid != 0)
@ -2935,6 +2938,9 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
} else if (bp != NULL) { } else if (bp != NULL) {
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
panic("REQ_CMP with QFRZN"); panic("REQ_CMP with QFRZN");
if (state == DA_CCB_DELETE)
bp->bio_resid = 0;
else
bp->bio_resid = csio->resid; bp->bio_resid = csio->resid;
if (csio->resid > 0) if (csio->resid > 0)
bp->bio_flags |= BIO_ERROR; bp->bio_flags |= BIO_ERROR;
@ -2944,7 +2950,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
bp->bio_flags |= BIO_ERROR; bp->bio_flags |= BIO_ERROR;
softc->error_inject = 0; softc->error_inject = 0;
} }
} }
/* /*
@ -2959,10 +2964,12 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
if (state == DA_CCB_DELETE) { if (state == DA_CCB_DELETE) {
while ((bp1 = bioq_takefirst(&softc->delete_run_queue)) while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
!= NULL) { != NULL) {
bp1->bio_resid = bp->bio_resid;
bp1->bio_error = bp->bio_error; bp1->bio_error = bp->bio_error;
if (bp->bio_flags & BIO_ERROR) if (bp->bio_flags & BIO_ERROR) {
bp1->bio_flags |= BIO_ERROR; bp1->bio_flags |= BIO_ERROR;
bp1->bio_resid = bp1->bio_bcount;
} else
bp1->bio_resid = 0;
biodone(bp1); biodone(bp1);
} }
softc->delete_running = 0; softc->delete_running = 0;