Author: mav
Date: Sat Sep 14 09:42:01 2013
New Revision: 255555
URL: http://svnweb.freebsd.org/changeset/base/255555

Log:
  MFC r253752:
  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:
  stable/9/sys/cam/ata/ata_da.c
  stable/9/sys/cam/scsi/scsi_da.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/cam/ata/ata_da.c
==============================================================================
--- stable/9/sys/cam/ata/ata_da.c       Sat Sep 14 09:40:24 2013        
(r255554)
+++ stable/9/sys/cam/ata/ata_da.c       Sat Sep 14 09:42:01 2013        
(r255555)
@@ -1696,37 +1696,27 @@ adadone(struct cam_periph *periph, union
        struct ada_softc *softc;
        struct ccb_ataio *ataio;
        struct ccb_getdev *cgd;
+       int state;
 
        softc = (struct ada_softc *)periph->softc;
        ataio = &done_ccb->ataio;
 
        CAM_DEBUG(periph->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(done_ccb->ccb_h.path,
                                                 /*relsim_flags*/0,
@@ -1736,26 +1726,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: stable/9/sys/cam/scsi/scsi_da.c
==============================================================================
--- stable/9/sys/cam/scsi/scsi_da.c     Sat Sep 14 09:40:24 2013        
(r255554)
+++ stable/9/sys/cam/scsi/scsi_da.c     Sat Sep 14 09:42:01 2013        
(r255555)
@@ -2929,7 +2929,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;
@@ -2943,7 +2946,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) {
@@ -2952,7 +2958,6 @@ dadone(struct cam_periph *periph, union 
                                bp->bio_flags |= BIO_ERROR;
                                softc->error_inject = 0;
                        }
-
                }
 
                /*
@@ -2967,10 +2972,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;
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "[email protected]"

Reply via email to