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();