diff options
author | mav <mav@FreeBSD.org> | 2009-11-01 11:31:06 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2009-11-01 11:31:06 +0000 |
commit | f730b0005e8be01d50ff4a09ad56e8156d154185 (patch) | |
tree | a839b18708c0447e20fde3a95bf180ebda2046e4 /sys/cam/scsi | |
parent | 29890cf9d2809593453bd452d4617e0ef072596c (diff) | |
download | FreeBSD-src-f730b0005e8be01d50ff4a09ad56e8156d154185.zip FreeBSD-src-f730b0005e8be01d50ff4a09ad56e8156d154185.tar.gz |
MFp4:
Fix reference counting bug, when device unreferenced before then
invalidated. To do it, do not handle validity flag as another
reference, but explicitly modify reference count each time flag is
modified.
Discovered by: thompsa
Diffstat (limited to 'sys/cam/scsi')
-rw-r--r-- | sys/cam/scsi/scsi_xpt.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index a240db8..d780f9a 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -1076,8 +1076,10 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) else PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0); - path->device->flags &= ~CAM_DEV_UNCONFIGURED; - + if (path->device->flags & CAM_DEV_UNCONFIGURED) { + path->device->flags &= ~CAM_DEV_UNCONFIGURED; + xpt_acquire_device(path->device); + } xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); return; @@ -1336,8 +1338,12 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Leave Domain Validation\n")); } + if (path->device->flags & CAM_DEV_UNCONFIGURED) { + path->device->flags &= ~CAM_DEV_UNCONFIGURED; + xpt_acquire_device(path->device); + } path->device->flags &= - ~(CAM_DEV_UNCONFIGURED|CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); + ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { /* Inform the XPT that a new device has been found */ done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; @@ -1387,8 +1393,12 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Leave Domain Validation Successfully\n")); } + if (path->device->flags & CAM_DEV_UNCONFIGURED) { + path->device->flags &= ~CAM_DEV_UNCONFIGURED; + xpt_acquire_device(path->device); + } path->device->flags &= - ~(CAM_DEV_UNCONFIGURED|CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); + ~(CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM); if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { /* Inform the XPT that a new device has been found */ done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; @@ -2375,8 +2385,10 @@ scsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, CAM_EXPECT_INQ_CHANGE, NULL); } xpt_release_path(&newpath); - } else if (async_code == AC_LOST_DEVICE) { + } else if (async_code == AC_LOST_DEVICE && + (device->flags & CAM_DEV_UNCONFIGURED) == 0) { device->flags |= CAM_DEV_UNCONFIGURED; + xpt_release_device(device); } else if (async_code == AC_TRANSFER_NEG) { struct ccb_trans_settings *settings; |