Author: trasz
Date: Wed Oct  9 20:09:58 2013
New Revision: 256238
URL: http://svnweb.freebsd.org/changeset/base/256238

Log:
  Properly handle residual count in Data-In PDUs with S bit set.
  
  Approved by:  re (gjb)
  Sponsored by: FreeBSD Foundation

Modified:
  head/sys/dev/iscsi/iscsi.c

Modified: head/sys/dev/iscsi/iscsi.c
==============================================================================
--- head/sys/dev/iscsi/iscsi.c  Wed Oct  9 20:00:04 2013        (r256237)
+++ head/sys/dev/iscsi/iscsi.c  Wed Oct  9 20:09:58 2013        (r256238)
@@ -966,22 +966,43 @@ iscsi_pdu_handle_data_in(struct icl_pdu 
         * XXX: Check DataSN.
         * XXX: Check F.
         */
-       if (bhsdi->bhsdi_flags & BHSDI_FLAGS_S) {
-               //ISCSI_SESSION_DEBUG(is, "got S flag; status 0x%x", 
bhsdi->bhsdi_status);
-               if (bhsdi->bhsdi_status == 0) {
-                       io->io_ccb->ccb_h.status = CAM_REQ_CMP;
-               } else {
-                       if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
-                               xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
-                               ISCSI_SESSION_DEBUG(is, "freezing devq");
+       if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) == 0) {
+               /*
+                * Nothing more to do.
+                */
+               icl_pdu_free(response);
+               return;
+       }
+
+       //ISCSI_SESSION_DEBUG(is, "got S flag; status 0x%x", 
bhsdi->bhsdi_status);
+       if (bhsdi->bhsdi_status == 0) {
+               io->io_ccb->ccb_h.status = CAM_REQ_CMP;
+       } else {
+               if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
+                       xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
+                       ISCSI_SESSION_DEBUG(is, "freezing devq");
+               }
+               io->io_ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | 
CAM_DEV_QFRZN;
+               csio->scsi_status = bhsdi->bhsdi_status;
+       }
+
+       if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+               KASSERT(io->io_received <= csio->dxfer_len,
+                   ("io->io_received > csio->dxfer_len"));
+               if (io->io_received < csio->dxfer_len) {
+                       csio->resid = ntohl(bhsdi->bhsdi_residual_count);
+                       if (csio->resid != csio->dxfer_len - io->io_received) {
+                               ISCSI_SESSION_WARN(is, "underflow mismatch: "
+                                   "target indicates %d, we calculated %zd",
+                                   csio->resid,
+                                   csio->dxfer_len - io->io_received);
                        }
-                       io->io_ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | 
CAM_DEV_QFRZN;
-                       csio->scsi_status = bhsdi->bhsdi_status;
+                       csio->resid = csio->dxfer_len - io->io_received;
                }
-               xpt_done(io->io_ccb);
-               iscsi_outstanding_remove(is, io);
        }
 
+       xpt_done(io->io_ccb);
+       iscsi_outstanding_remove(is, io);
        icl_pdu_free(response);
 }
 
_______________________________________________
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