summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-07-28 19:56:08 +0000
committermav <mav@FreeBSD.org>2013-07-28 19:56:08 +0000
commit5ee60ee6123584d26a9f56c43a68cb069b3b1cd5 (patch)
tree977d022a241919fabe9edbac6e5a9d66ec88fe12 /sys/cam
parentee26f7a25613614a6cad69f72a63b62a890a63c8 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/cam/ata/ata_da.c44
-rw-r--r--sys/cam/scsi/scsi_da.c17
2 files changed, 35 insertions, 26 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;
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 8d0f35e..fb950e4 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -2921,7 +2921,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
bp->bio_flags |= BIO_ERROR;
}
} else if (bp != NULL) {
- bp->bio_resid = csio->resid;
+ if (state == DA_CCB_DELETE)
+ bp->bio_resid = 0;
+ else
+ bp->bio_resid = csio->resid;
bp->bio_error = 0;
if (bp->bio_resid != 0)
bp->bio_flags |= BIO_ERROR;
@@ -2935,7 +2938,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
} else if (bp != NULL) {
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
panic("REQ_CMP with QFRZN");
- bp->bio_resid = csio->resid;
+ if (state == DA_CCB_DELETE)
+ bp->bio_resid = 0;
+ else
+ bp->bio_resid = csio->resid;
if (csio->resid > 0)
bp->bio_flags |= BIO_ERROR;
if (softc->error_inject != 0) {
@@ -2944,7 +2950,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
bp->bio_flags |= BIO_ERROR;
softc->error_inject = 0;
}
-
}
/*
@@ -2959,10 +2964,12 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
if (state == DA_CCB_DELETE) {
while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
!= NULL) {
- 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->delete_running = 0;
OpenPOWER on IntegriCloud