Print this page
LOCAL: LDI -- make walks removal-safe
*** 142,151 ****
--- 142,154 ----
{ LDI_EV_DEGRADE, 0, CT_DEV_EV_DEGRADED},
{ LDI_EV_DEVICE_REMOVE, 0, 0},
{ NULL} /* must terminate list */
};
+ static ldi_ev_callback_impl_t *walker_next = NULL;
+ static ldi_ev_callback_impl_t *walker_prev = NULL;
+
void
ldi_init(void)
{
int i;
*** 3327,3338 ****
LDI_EVDBG((CE_NOTE, "ldi_invoke_notify(): entered: dip=%p, ev=%s",
(void *)dip, event));
ret = LDI_EV_NONE;
ldi_ev_lock();
listp = &ldi_ev_callback_list.le_head;
! for (lecp = list_head(listp); lecp; lecp = list_next(listp, lecp)) {
/* Check if matching device */
if (!ldi_ev_device_match(lecp, dip, dev, spec_type))
continue;
--- 3330,3343 ----
LDI_EVDBG((CE_NOTE, "ldi_invoke_notify(): entered: dip=%p, ev=%s",
(void *)dip, event));
ret = LDI_EV_NONE;
ldi_ev_lock();
+ VERIFY(walker_next == NULL);
listp = &ldi_ev_callback_list.le_head;
! for (lecp = list_head(listp); lecp; lecp = walker_next) {
! walker_next = list_next(listp, lecp);
/* Check if matching device */
if (!ldi_ev_device_match(lecp, dip, dev, spec_type))
continue;
*** 3384,3394 ****
/*
* Undo notifies already sent
*/
lecp = list_prev(listp, lecp);
! for (; lecp; lecp = list_prev(listp, lecp)) {
/*
* Check if matching device
*/
if (!ldi_ev_device_match(lecp, dip, dev, spec_type))
--- 3389,3401 ----
/*
* Undo notifies already sent
*/
lecp = list_prev(listp, lecp);
! VERIFY(walker_prev == NULL);
! for (; lecp; lecp = walker_prev) {
! walker_prev = list_prev(listp, lecp);
/*
* Check if matching device
*/
if (!ldi_ev_device_match(lecp, dip, dev, spec_type))
*** 3435,3444 ****
--- 3442,3453 ----
lecp->lec_finalize = NULL;
}
}
out:
+ walker_next = NULL;
+ walker_prev = NULL;
ldi_ev_unlock();
if (ret == LDI_EV_NONE) {
LDI_EVDBG((CE_NOTE, "ldi_invoke_notify(): no matching "
"LDI callbacks"));
*** 3550,3561 ****
LDI_EVDBG((CE_NOTE, "ldi_invoke_finalize(): entered: dip=%p, result=%d"
" event=%s", (void *)dip, ldi_result, event));
ldi_ev_lock();
listp = &ldi_ev_callback_list.le_head;
! for (lecp = list_head(listp); lecp; lecp = list_next(listp, lecp)) {
if (lecp->lec_finalize == NULL) {
LDI_EVDBG((CE_NOTE, "ldi_invoke_finalize(): No "
"finalize. Skipping"));
continue; /* Not interested in finalize */
--- 3559,3572 ----
LDI_EVDBG((CE_NOTE, "ldi_invoke_finalize(): entered: dip=%p, result=%d"
" event=%s", (void *)dip, ldi_result, event));
ldi_ev_lock();
+ VERIFY(walker_next == NULL);
listp = &ldi_ev_callback_list.le_head;
! for (lecp = list_head(listp); lecp; lecp = walker_next) {
! walker_next = list_next(listp, lecp);
if (lecp->lec_finalize == NULL) {
LDI_EVDBG((CE_NOTE, "ldi_invoke_finalize(): No "
"finalize. Skipping"));
continue; /* Not interested in finalize */
*** 3602,3611 ****
--- 3613,3623 ----
"ldi_invoke_finalize(): NULLing finalize after "
"calling 1 finalize following ldi_close"));
lecp->lec_finalize = NULL;
}
}
+ walker_next = NULL;
ldi_ev_unlock();
if (found)
return;
*** 3683,3692 ****
--- 3695,3711 ----
next = found = NULL;
for (lecp = list_head(listp); lecp; lecp = next) {
next = list_next(listp, lecp);
if (lecp->lec_id == id) {
ASSERT(found == NULL);
+
+ /* If there is a walk in progress, move it along... */
+ if (walker_next == lecp)
+ walker_next = next;
+ if (walker_prev == lecp)
+ walker_prev = list_prev(listp, walker_prev);
+
list_remove(listp, lecp);
found = lecp;
}
}
ldi_ev_unlock();