FreeBSD Bugzilla – Attachment 162793 Details for
Bug 204298
xpt_release_device() panic: mutex CAM queue lock not owned
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
cam_xpt.c device callout patch
xpt-callout.patch (text/plain), 4.24 KB, created by
Scott M. Ferris
on 2015-11-05 00:34:15 UTC
(
hide
)
Description:
cam_xpt.c device callout patch
Filename:
MIME Type:
Creator:
Scott M. Ferris
Created:
2015-11-05 00:34:15 UTC
Size:
4.24 KB
patch
obsolete
>diff --git i/sys/cam/cam_xpt.c w/sys/cam/cam_xpt.c >index fb5d041..cda56e7 100644 >--- i/sys/cam/cam_xpt.c >+++ w/sys/cam/cam_xpt.c >@@ -2901,7 +2901,24 @@ call_sim: > */ > start_ccb->ccb_h.flags &= ~CAM_DEV_QFREEZE; > callout_stop(&dev->callout); >+ /* >+ * If CAM_DEV_REL_TIMEOUT_PENDING is still >+ * set, then the callout is still >+ * cancelable, since we hold the callout >+ * mutex and the callout function clears the >+ * flag before it ever unlocks/relocks the >+ * mutex. Since we already acquired a >+ * device ref for the callout we just >+ * stopped, we don't need another ref. >+ */ > } else { >+ /* >+ * Since the callout gets a pointer to the >+ * device, acquire a reference to make sure >+ * the device can't go away until the >+ * callout finishes or is stopped. >+ */ >+ xpt_acquire_device(dev); > > start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; > } >@@ -4355,7 +4372,20 @@ xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue) > * to release this queue. > */ > if ((dev->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) { >- callout_stop(&dev->callout); >+ /* >+ * If CAM_DEV_REL_TIMEOUT_PENDING is still set, >+ * either the callout is still cancelable, or the >+ * callout function (xpt_release_devq_timeout) is >+ * our caller. It's too early for the callout >+ * itself to release its ref, so only release the >+ * device ref if we stop the callout. If we >+ * can't stop the callout, it will release >+ * its ref when it finishes. >+ */ >+ if (callout_stop(&dev->callout) != 0) { >+ /* Release the callout's device reference */ >+ xpt_release_device(dev); >+ } > dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING; > } > /* >@@ -4646,6 +4676,38 @@ static void > xpt_destroy_device(void *context, int pending) > { > struct cam_ed *device = context; >+ struct cam_eb *bus = device->target->bus; >+ struct cam_devq *devq; >+ >+ callout_drain(&device->callout); >+ >+ /* Release our slot in the devq */ >+ devq = bus->sim->devq; >+ mtx_lock(&devq->send_mtx); >+ KASSERT((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) == 0, >+ ("device %p has timeout pending", device)); >+ cam_devq_resize(devq, devq->send_queue.array_size - 1); >+ mtx_unlock(&devq->send_mtx); >+ >+ KASSERT(SLIST_EMPTY(&device->periphs), >+ ("destroying device, but periphs list is not empty")); >+ KASSERT(device->devq_entry.index == CAM_UNQUEUED_INDEX, >+ ("destroying device while still queued for ccbs")); >+ >+ xpt_release_target(device->target); >+ >+ cam_ccbq_fini(&device->ccbq); >+ /* >+ * Free allocated memory. free(9) does nothing if the >+ * supplied pointer is NULL, so it is safe to call without >+ * checking. >+ */ >+ free(device->supported_vpds, M_CAMXPT); >+ free(device->device_id, M_CAMXPT); >+ free(device->ext_inq, M_CAMXPT); >+ free(device->physpath, M_CAMXPT); >+ free(device->rcap_buf, M_CAMXPT); >+ free(device->serial_num, M_CAMXPT); > > mtx_lock(&device->device_mtx); > mtx_destroy(&device->device_mtx); >@@ -4723,7 +4785,6 @@ void > xpt_release_device(struct cam_ed *device) > { > struct cam_eb *bus = device->target->bus; >- struct cam_devq *devq; > > mtx_lock(&bus->eb_mtx); > if (--device->refcount > 0) { >@@ -4735,34 +4796,6 @@ xpt_release_device(struct cam_ed *device) > device->target->generation++; > mtx_unlock(&bus->eb_mtx); > >- /* Release our slot in the devq */ >- devq = bus->sim->devq; >- mtx_lock(&devq->send_mtx); >- cam_devq_resize(devq, devq->send_queue.array_size - 1); >- mtx_unlock(&devq->send_mtx); >- >- KASSERT(SLIST_EMPTY(&device->periphs), >- ("destroying device, but periphs list is not empty")); >- KASSERT(device->devq_entry.index == CAM_UNQUEUED_INDEX, >- ("destroying device while still queued for ccbs")); >- >- if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) >- callout_stop(&device->callout); >- >- xpt_release_target(device->target); >- >- cam_ccbq_fini(&device->ccbq); >- /* >- * Free allocated memory. free(9) does nothing if the >- * supplied pointer is NULL, so it is safe to call without >- * checking. >- */ >- free(device->supported_vpds, M_CAMXPT); >- free(device->device_id, M_CAMXPT); >- free(device->ext_inq, M_CAMXPT); >- free(device->physpath, M_CAMXPT); >- free(device->rcap_buf, M_CAMXPT); >- free(device->serial_num, M_CAMXPT); > taskqueue_enqueue(xsoftc.xpt_taskq, &device->device_destroy_task); > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 204298
:
162793
|
162814
|
162840