Print this page
LOCAL: LDI -- make walks removal-safe

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/driver_lyr.c
          +++ new/usr/src/uts/common/os/driver_lyr.c
↓ open down ↓ 136 lines elided ↑ open up ↑
 137  137          uint_t ck_ctype;
 138  138  };
 139  139  
 140  140  static struct ldi_ev_cookie ldi_ev_cookies[] = {
 141  141          { LDI_EV_OFFLINE, 1, CT_DEV_EV_OFFLINE},
 142  142          { LDI_EV_DEGRADE, 0, CT_DEV_EV_DEGRADED},
 143  143          { LDI_EV_DEVICE_REMOVE, 0, 0},
 144  144          { NULL}                 /* must terminate list */
 145  145  };
 146  146  
      147 +static ldi_ev_callback_impl_t *walker_next = NULL;
      148 +static ldi_ev_callback_impl_t *walker_prev = NULL;
      149 +
 147  150  void
 148  151  ldi_init(void)
 149  152  {
 150  153          int i;
 151  154  
 152  155          ldi_handle_hash_count = 0;
 153  156          for (i = 0; i < LH_HASH_SZ; i++) {
 154  157                  mutex_init(&ldi_handle_hash_lock[i], NULL, MUTEX_DEFAULT, NULL);
 155  158                  ldi_handle_hash[i] = NULL;
 156  159          }
↓ open down ↓ 3165 lines elided ↑ open up ↑
3322 3325              (spec_type == S_IFCHR || spec_type == S_IFBLK));
3323 3326          ASSERT(event);
3324 3327          ASSERT(ldi_native_event(event));
3325 3328          ASSERT(ldi_ev_sync_event(event));
3326 3329  
3327 3330          LDI_EVDBG((CE_NOTE, "ldi_invoke_notify(): entered: dip=%p, ev=%s",
3328 3331              (void *)dip, event));
3329 3332  
3330 3333          ret = LDI_EV_NONE;
3331 3334          ldi_ev_lock();
     3335 +        VERIFY(walker_next == NULL);
3332 3336          listp = &ldi_ev_callback_list.le_head;
3333      -        for (lecp = list_head(listp); lecp; lecp = list_next(listp, lecp)) {
     3337 +        for (lecp = list_head(listp); lecp; lecp = walker_next) {
     3338 +                walker_next = list_next(listp, lecp);
3334 3339  
3335 3340                  /* Check if matching device */
3336 3341                  if (!ldi_ev_device_match(lecp, dip, dev, spec_type))
3337 3342                          continue;
3338 3343  
3339 3344                  if (lecp->lec_lhp == NULL) {
3340 3345                          /*
3341 3346                           * Consumer has unregistered the handle and so
3342 3347                           * is no longer interested in notify events.
3343 3348                           */
↓ open down ↓ 35 lines elided ↑ open up ↑
3379 3384  
3380 3385          if (ret != LDI_EV_FAILURE)
3381 3386                  goto out;
3382 3387  
3383 3388          LDI_EVDBG((CE_NOTE, "ldi_invoke_notify(): undoing notify"));
3384 3389  
3385 3390          /*
3386 3391           * Undo notifies already sent
3387 3392           */
3388 3393          lecp = list_prev(listp, lecp);
3389      -        for (; lecp; lecp = list_prev(listp, lecp)) {
     3394 +        VERIFY(walker_prev == NULL);
     3395 +        for (; lecp; lecp = walker_prev) {
     3396 +                walker_prev = list_prev(listp, lecp);
3390 3397  
3391 3398                  /*
3392 3399                   * Check if matching device
3393 3400                   */
3394 3401                  if (!ldi_ev_device_match(lecp, dip, dev, spec_type))
3395 3402                          continue;
3396 3403  
3397 3404  
3398 3405                  if (lecp->lec_finalize == NULL) {
3399 3406                          LDI_EVDBG((CE_NOTE, "ldi_invoke_notify(): no finalize, "
↓ open down ↓ 30 lines elided ↑ open up ↑
3430 3437                  if (lecp->lec_lhp == NULL &&
3431 3438                      ldi_native_cookie(lecp->lec_cookie)) {
3432 3439                          LDI_EVDBG((CE_NOTE,
3433 3440                              "ldi_invoke_notify(): NULL-ing finalize after "
3434 3441                              "calling 1 finalize following ldi_close"));
3435 3442                          lecp->lec_finalize = NULL;
3436 3443                  }
3437 3444          }
3438 3445  
3439 3446  out:
     3447 +        walker_next = NULL;
     3448 +        walker_prev = NULL;
3440 3449          ldi_ev_unlock();
3441 3450  
3442 3451          if (ret == LDI_EV_NONE) {
3443 3452                  LDI_EVDBG((CE_NOTE, "ldi_invoke_notify(): no matching "
3444 3453                      "LDI callbacks"));
3445 3454          }
3446 3455  
3447 3456          return (ret);
3448 3457  }
3449 3458  
↓ open down ↓ 95 lines elided ↑ open up ↑
3545 3554          ASSERT((dev == DDI_DEV_T_ANY && spec_type == 0) ||
3546 3555              (spec_type == S_IFCHR || spec_type == S_IFBLK));
3547 3556          ASSERT(event);
3548 3557          ASSERT(ldi_native_event(event));
3549 3558          ASSERT(ldi_result == LDI_EV_SUCCESS || ldi_result == LDI_EV_FAILURE);
3550 3559  
3551 3560          LDI_EVDBG((CE_NOTE, "ldi_invoke_finalize(): entered: dip=%p, result=%d"
3552 3561              " event=%s", (void *)dip, ldi_result, event));
3553 3562  
3554 3563          ldi_ev_lock();
     3564 +        VERIFY(walker_next == NULL);
3555 3565          listp = &ldi_ev_callback_list.le_head;
3556      -        for (lecp = list_head(listp); lecp; lecp = list_next(listp, lecp)) {
     3566 +        for (lecp = list_head(listp); lecp; lecp = walker_next) {
     3567 +                walker_next = list_next(listp, lecp);
3557 3568  
3558 3569                  if (lecp->lec_finalize == NULL) {
3559 3570                          LDI_EVDBG((CE_NOTE, "ldi_invoke_finalize(): No "
3560 3571                              "finalize. Skipping"));
3561 3572                          continue;       /* Not interested in finalize */
3562 3573                  }
3563 3574  
3564 3575                  /*
3565 3576                   * Check if matching device
3566 3577                   */
↓ open down ↓ 30 lines elided ↑ open up ↑
3597 3608                   * already called the 1 finalize above allowed in this situation
3598 3609                   */
3599 3610                  if (lecp->lec_lhp == NULL &&
3600 3611                      ldi_native_cookie(lecp->lec_cookie)) {
3601 3612                          LDI_EVDBG((CE_NOTE,
3602 3613                              "ldi_invoke_finalize(): NULLing finalize after "
3603 3614                              "calling 1 finalize following ldi_close"));
3604 3615                          lecp->lec_finalize = NULL;
3605 3616                  }
3606 3617          }
     3618 +        walker_next = NULL;
3607 3619          ldi_ev_unlock();
3608 3620  
3609 3621          if (found)
3610 3622                  return;
3611 3623  
3612 3624          LDI_EVDBG((CE_NOTE, "ldi_invoke_finalize(): no matching callbacks"));
3613 3625  }
3614 3626  
3615 3627  /*
3616 3628   * Framework function to be called from a layered driver to propagate
↓ open down ↓ 61 lines elided ↑ open up ↑
3678 3690              (void *)id));
3679 3691  
3680 3692          ldi_ev_lock();
3681 3693  
3682 3694          listp = &ldi_ev_callback_list.le_head;
3683 3695          next = found = NULL;
3684 3696          for (lecp = list_head(listp); lecp; lecp = next) {
3685 3697                  next = list_next(listp, lecp);
3686 3698                  if (lecp->lec_id == id) {
3687 3699                          ASSERT(found == NULL);
     3700 +
     3701 +                        /* If there is a walk in progress, move it along... */
     3702 +                        if (walker_next == lecp)
     3703 +                                walker_next = next;
     3704 +                        if (walker_prev == lecp)
     3705 +                                walker_prev = list_prev(listp, walker_prev);
     3706 +
3688 3707                          list_remove(listp, lecp);
3689 3708                          found = lecp;
3690 3709                  }
3691 3710          }
3692 3711          ldi_ev_unlock();
3693 3712  
3694 3713          if (found == NULL) {
3695 3714                  cmn_err(CE_WARN, "No LDI event handler for id (%p)",
3696 3715                      (void *)id);
3697 3716                  return (LDI_EV_SUCCESS);
↓ open down ↓ 23 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX