aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2022-04-28 01:39:50 +0000
committerAlexander Motin <mav@FreeBSD.org>2022-04-28 01:39:50 +0000
commit404f001161b975164d8b52d9f404d07ac7584027 (patch)
tree64e9eaffece56ce3fad8636f09e04ef506f73a40
parent6fe78ad434557a713ebf5159ac6ac4052ef3da1c (diff)
downloadsrc-404f001161b975164d8b52d9f404d07ac7584027.tar.gz
src-404f001161b975164d8b52d9f404d07ac7584027.zip
CAM: Keep periph_links when restoring CCB in camperiphdone().
While recovery command executed, some other commands from the periph may complete, that may affect periph_links of this CCB. So restoring original CCB we must keep current periph_links as more up to date. I've found this triggering assertions with debug kernel and suspect some memory corruptions otherwise when spun down disk receives two or sometimes more concurrent requests. MFC after: 1 week Sponsored by: iXsystems, Inc.
-rw-r--r--sys/cam/cam_periph.c6
1 files changed, 1 insertions, 5 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 869691f59a72..7f8f0036f10b 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1435,11 +1435,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
* blocking by that also any new recovery attempts for this CCB,
* and the result will be the final one returned to the CCB owher.
*/
-
- /*
- * Copy the CCB back, preserving the alloc_flags field. Things
- * will crash horribly if the CCBs are not of the same size.
- */
saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
KASSERT(saved_ccb->ccb_h.func_code == XPT_SCSI_IO,
("%s: saved_ccb func_code %#x != XPT_SCSI_IO",
@@ -1447,6 +1442,7 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
KASSERT(done_ccb->ccb_h.func_code == XPT_SCSI_IO,
("%s: done_ccb func_code %#x != XPT_SCSI_IO",
__func__, done_ccb->ccb_h.func_code));
+ saved_ccb->ccb_h.periph_links = done_ccb->ccb_h.periph_links;
done_flags = done_ccb->ccb_h.alloc_flags;
bcopy(saved_ccb, done_ccb, sizeof(struct ccb_scsiio));
done_ccb->ccb_h.alloc_flags = done_flags;