Author: mav
Date: Sun Jul 28 19:56:08 2013
New Revision: 253752
URL: http://svnweb.freebsd.org/changeset/base/253752

Log:
  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.

Modified:
  head/sys/cam/ata/ata_da.c
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c   Sun Jul 28 19:49:39 2013        (r253751)
+++ head/sys/cam/ata/ata_da.c   Sun Jul 28 19:56:08 2013        (r253752)
@@ -1684,6 +1684,7 @@ adadone(struct cam_periph *periph, union
        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
 
        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
                } 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;

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c Sun Jul 28 19:49:39 2013        (r253751)
+++ head/sys/cam/scsi/scsi_da.c Sun Jul 28 19:56:08 2013        (r253752)
@@ -2921,7 +2921,10 @@ dadone(struct cam_periph *periph, union 
                                        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 
                } 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 
                                bp->bio_flags |= BIO_ERROR;
                                softc->error_inject = 0;
                        }
-
                }
 
                /*
@@ -2959,10 +2964,12 @@ dadone(struct cam_periph *periph, union 
                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;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to