diff options
author | mav <mav@FreeBSD.org> | 2013-07-28 19:56:08 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2013-07-28 19:56:08 +0000 |
commit | 5ee60ee6123584d26a9f56c43a68cb069b3b1cd5 (patch) | |
tree | 977d022a241919fabe9edbac6e5a9d66ec88fe12 /sys/cam/ata | |
parent | ee26f7a25613614a6cad69f72a63b62a890a63c8 (diff) | |
download | FreeBSD-src-5ee60ee6123584d26a9f56c43a68cb069b3b1cd5.zip FreeBSD-src-5ee60ee6123584d26a9f56c43a68cb069b3b1cd5.tar.gz |
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.
Diffstat (limited to 'sys/cam/ata')
-rw-r--r-- | sys/cam/ata/ata_da.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index 3dac0ac..f201231 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -1684,6 +1684,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) struct ccb_ataio *ataio; struct ccb_getdev *cgd; struct cam_path *path; + int state; softc = (struct ada_softc *)periph->softc; 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")); - 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_TRIM: { struct bio *bp; + int error; - bp = (struct bio *)done_ccb->ccb_h.ccb_bp; if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - int error; - error = adaerror(done_ccb, 0, 0); if (error == ERESTART) { /* A retry was scheduled, so just 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) cam_release_devq(path, /*relsim_flags*/0, @@ -1725,26 +1715,38 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) } else { if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) panic("REQ_CMP with QFRZN"); - bp->bio_resid = ataio->resid; - if (ataio->resid > 0) + 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; + if (bp->bio_resid > 0) bp->bio_flags |= BIO_ERROR; } softc->outstanding_cmds--; if (softc->outstanding_cmds == 0) softc->flags |= ADA_FLAG_WENT_IDLE; - if ((ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) == - ADA_CCB_TRIM) { + if (state == ADA_CCB_TRIM) { struct trim_request *req = (struct trim_request *)ataio->data_ptr; int i; for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) { struct bio *bp1 = req->bps[i]; - - bp1->bio_resid = bp->bio_resid; + 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_resid = bp1->bio_bcount; + } else + bp1->bio_resid = 0; biodone(bp1); } softc->trim_running = 0; |