Mercurial > illumos > illumos-gate
changeset 11068:9003c5184f28
6848196 unconfig takes longer than config
6899004 Reduce resource usage of dam address maps
6899010 Invoke deactivation callback when cancelling non-stabilized reports
author | John Danielson <John.Danielson@Sun.COM> |
---|---|
date | Mon, 16 Nov 2009 09:55:18 -0800 |
parents | 8db057af6c8d |
children | e4b1c921f2de |
files | usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c usr/src/uts/common/io/scsi/impl/scsi_hba.c usr/src/uts/common/os/damap.c usr/src/uts/common/os/sunddi.c usr/src/uts/common/sys/damap.h usr/src/uts/common/sys/damap_impl.h usr/src/uts/common/sys/ddi_impldefs.h usr/src/uts/common/sys/scsi/impl/transport.h usr/src/uts/common/sys/sunddi.h |
diffstat | 10 files changed, 1065 insertions(+), 894 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c Mon Nov 16 09:55:18 2009 -0800 @@ -982,7 +982,7 @@ /* * Create the iportmap for this HBA instance */ - if (scsi_hba_iportmap_create(dip, iportmap_usec, pwp->nphy, + if (scsi_hba_iportmap_create(dip, iportmap_usec, &pwp->hss_iportmap) != DDI_SUCCESS) { pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: pmcs%d iportmap_create failed", __func__, inst);
--- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c Mon Nov 16 09:55:18 2009 -0800 @@ -1897,7 +1897,7 @@ /* create target map */ if (scsi_hba_tgtmap_create(iport->dip, SCSI_TM_FULLSET, tgtmap_usec, - 2048, NULL, NULL, NULL, &iport->iss_tgtmap) != DDI_SUCCESS) { + NULL, NULL, NULL, &iport->iss_tgtmap) != DDI_SUCCESS) { pmcs_prt(iport->pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: failed to create tgtmap", __func__); return (B_FALSE);
--- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c Mon Nov 16 09:55:18 2009 -0800 @@ -6578,8 +6578,7 @@ h->h_thr_count++; mutex_exit(&h->h_lock); - mt |= scsi_hba_log_mt_disable; - if (mt & SCSI_ENUMERATION_MT_LUN_DISABLE) + if (mt & SCSI_ENUMERATION_MT_TARGET_DISABLE) callback((void *)td); else (void) thread_create(NULL, 0, callback, (void *)td, @@ -6946,8 +6945,7 @@ h->h_thr_count++; mutex_exit(&h->h_lock); - mt |= scsi_hba_log_mt_disable; - if (mt & SCSI_ENUMERATION_MT_TARGET_DISABLE) + if (mt & SCSI_ENUMERATION_MT_LUN_DISABLE) scsi_hba_enum_lsf_of_tgt_thr( (void *)ld); else @@ -7007,9 +7005,7 @@ mutex_enter(&h->h_lock); h->h_thr_count++; mutex_exit(&h->h_lock); - - mt |= scsi_hba_log_mt_disable; - if (mt & SCSI_ENUMERATION_MT_TARGET_DISABLE) + if (mt & SCSI_ENUMERATION_MT_LUN_DISABLE) scsi_hba_enum_lsf_of_tgt_thr( (void *)ld); else @@ -7056,9 +7052,7 @@ mutex_enter(&h->h_lock); h->h_thr_count++; mutex_exit(&h->h_lock); - - mt |= scsi_hba_log_mt_disable; - if (mt & SCSI_ENUMERATION_MT_TARGET_DISABLE) + if (mt & SCSI_ENUMERATION_MT_LUN_DISABLE) scsi_hba_enum_lsf_of_tgt_thr((void *)ld); else (void) thread_create(NULL, 0, @@ -7372,6 +7366,8 @@ mt = ddi_prop_get_int(DDI_DEV_T_ANY, self, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-enumeration", scsi_enumeration); + mt |= scsi_hba_log_mt_disable; + SCSI_HBA_LOG((_LOG(2), self, NULL, "%s@%s lun enumeration triggered", name, addr)); *lcp = '\0'; /* turn ',' into '\0' */ @@ -7507,6 +7503,8 @@ mt = ddi_prop_get_int(DDI_DEV_T_ANY, self, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-enumeration", scsi_enumeration); + mt |= scsi_hba_log_mt_disable; + if ((mt & SCSI_ENUMERATION_ENABLE) == 0) { /* * Static driver.conf file enumeration: @@ -7576,6 +7574,8 @@ mt = ddi_prop_get_int(DDI_DEV_T_ANY, self, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-enumeration", scsi_enumeration); + mt |= scsi_hba_log_mt_disable; + if ((mt & SCSI_ENUMERATION_ENABLE) == 0) return (ndi_busop_bus_unconfig(self, flags, op, arg)); @@ -7845,141 +7845,102 @@ return (ret); } -static void -scsi_tgtmap_scsi_config(void *arg, damap_t *mapp, damap_id_list_t id_list) +static int +scsi_tgtmap_scsi_config(void *arg, damap_t *mapp, damap_id_t tgtid) { scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg; dev_info_t *self = tran->tran_iport_dip; impl_scsi_tgtmap_t *tgtmap; - int mt; - damap_id_t tgtid; - int ntargets; - char **tgt_addrv; - char **tgt_addr; + char *tgtaddr; + int cfg_status, mt; tgtmap = (impl_scsi_tgtmap_t *)tran->tran_tgtmap; + tgtaddr = damap_id2addr(mapp, tgtid); + + if (scsi_lunmap_create(self, tgtmap, tgtaddr) != DDI_SUCCESS) { + SCSI_HBA_LOG((_LOG_NF(WARN), + "failed to create lunmap for %s", tgtaddr)); + } + mt = ddi_prop_get_int(DDI_DEV_T_ANY, self, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - "scsi-enumeration", scsi_enumeration); - - /* count the number of targets we need to config */ - for (ntargets = 0, - tgtid = damap_id_next(mapp, id_list, NODAM); - tgtid != NODAM; - tgtid = damap_id_next(mapp, id_list, tgtid)) - ntargets++; - - SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s %d target%s", - damap_name(mapp), ntargets, (ntargets == 1) ? "" : "s")); - if (ntargets == 0) - return; - - /* allocate and form vector of addresses */ - tgt_addrv = kmem_zalloc(sizeof (char *) * (ntargets + 1), KM_SLEEP); - for (tgt_addr = tgt_addrv, - tgtid = damap_id_next(mapp, id_list, NODAM); - tgtid != NODAM; - tgtid = damap_id_next(mapp, id_list, tgtid), - tgt_addr++) { - *tgt_addr = damap_id2addr(mapp, tgtid); - - if (scsi_lunmap_create(self, tgtmap, *tgt_addr) != DDI_SUCCESS) - SCSI_HBA_LOG((_LOG_NF(WARN), - "failed to create lunmap for %s", *tgt_addr)); - else - SCSI_HBA_LOG((_LOGTGT, self, NULL, - "%s @%s", damap_name(mapp), *tgt_addr)); - } - - /* null terminate vector */ - *tgt_addr = NULL; - - /* configure vector of addresses (with multi-threading) */ - scsi_hba_thread_taddrs(self, tgt_addrv, mt, SE_HP, - scsi_hba_taddr_config_thr); - - /* free vector */ - kmem_free(tgt_addrv, sizeof (char *) * (ntargets + 1)); -} - -static void -scsi_tgtmap_scsi_unconfig(void *arg, damap_t *mapp, damap_id_list_t id_list) + DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-enumeration", + scsi_enumeration); + mt |= scsi_hba_log_mt_disable; + + cfg_status = scsi_hba_bus_config_taddr(self, tgtaddr, mt, SE_HP); + if (cfg_status != NDI_SUCCESS) { + SCSI_HBA_LOG((_LOGCFG, self, NULL, "%s @%s config status %d", + damap_name(mapp), tgtaddr, cfg_status)); + return (DAM_FAILURE); + } + + return (DAM_SUCCESS); +} + + +static int +scsi_tgtmap_scsi_unconfig(void *arg, damap_t *mapp, damap_id_t tgtid) { scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg; dev_info_t *self = tran->tran_iport_dip; impl_scsi_tgtmap_t *tgtmap; - damap_id_t tgtid; char *tgt_addr; tgtmap = (impl_scsi_tgtmap_t *)tran->tran_tgtmap; - - for (tgtid = damap_id_next(mapp, id_list, NODAM); - tgtid != NODAM; - tgtid = damap_id_next(mapp, id_list, tgtid)) { - tgt_addr = damap_id2addr(mapp, tgtid); - - SCSI_HBA_LOG((_LOGTGT, self, NULL, - "%s @%s", damap_name(mapp), tgt_addr)); - scsi_lunmap_destroy(self, tgtmap, tgt_addr); - } -} - -static void -scsi_tgtmap_smp_config(void *arg, damap_t *mapp, damap_id_list_t id_list) + tgt_addr = damap_id2addr(mapp, tgtid); + + SCSI_HBA_LOG((_LOGUNCFG, self, NULL, "%s @%s", damap_name(mapp), + tgt_addr)); + scsi_lunmap_destroy(self, tgtmap, tgt_addr); + return (DAM_SUCCESS); +} + +static int +scsi_tgtmap_smp_config(void *arg, damap_t *mapp, damap_id_t tgtid) { scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg; dev_info_t *self = tran->tran_iport_dip; - damap_id_t tgtid; char *addr; - for (tgtid = damap_id_next(mapp, id_list, NODAM); - tgtid != NODAM; - tgtid = damap_id_next(mapp, id_list, tgtid)) { - addr = damap_id2addr(mapp, tgtid); - SCSI_HBA_LOG((_LOGTGT, self, NULL, - "%s @%s", damap_name(mapp), addr)); - - (void) smp_hba_bus_config_taddr(self, addr); - } -} - -static void -scsi_tgtmap_smp_unconfig(void *arg, damap_t *mapp, damap_id_list_t id_list) + addr = damap_id2addr(mapp, tgtid); + SCSI_HBA_LOG((_LOGCFG, self, NULL, "%s @%s", damap_name(mapp), addr)); + + return ((smp_hba_bus_config_taddr(self, addr) == NDI_SUCCESS) ? + DAM_SUCCESS : DAM_FAILURE); +} + +static int +scsi_tgtmap_smp_unconfig(void *arg, damap_t *mapp, damap_id_t tgtid) { scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg; dev_info_t *self = tran->tran_iport_dip; - damap_id_t tgtid; char *addr; dev_info_t *child; char nameaddr[SCSI_MAXNAMELEN]; int circ; - for (tgtid = damap_id_next(mapp, id_list, NODAM); - tgtid != NODAM; - tgtid = damap_id_next(mapp, id_list, tgtid)) { - addr = damap_id2addr(mapp, tgtid); - SCSI_HBA_LOG((_LOGTGT, self, NULL, - "%s @%s", damap_name(mapp), addr)); - - (void) snprintf(nameaddr, sizeof (nameaddr), "smp@%s", addr); - scsi_hba_devi_enter(self, &circ); - if ((child = ndi_devi_findchild(self, nameaddr)) == NULL) { - scsi_hba_devi_exit(self, circ); - continue; - } - - if (ndi_devi_offline(child, - NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) == DDI_SUCCESS) { - SCSI_HBA_LOG((_LOGUNCFG, self, NULL, - "devinfo smp@%s offlined and removed", addr)); - } else if (ndi_devi_device_remove(child)) { - /* Offline/remove failed, note new device_remove */ - SCSI_HBA_LOG((_LOGUNCFG, self, NULL, - "devinfo smp@%s offline failed, device_remove", - addr)); - } + addr = damap_id2addr(mapp, tgtid); + SCSI_HBA_LOG((_LOGUNCFG, self, NULL, "%s @%s", damap_name(mapp), addr)); + + (void) snprintf(nameaddr, sizeof (nameaddr), "smp@%s", addr); + scsi_hba_devi_enter(self, &circ); + if ((child = ndi_devi_findchild(self, nameaddr)) == NULL) { scsi_hba_devi_exit(self, circ); - } + return (DAM_SUCCESS); + } + + if (ndi_devi_offline(child, + NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) == DDI_SUCCESS) { + SCSI_HBA_LOG((_LOGUNCFG, self, NULL, + "devinfo smp@%s offlined and removed", addr)); + } else if (ndi_devi_device_remove(child)) { + /* Offline/remove failed, note new device_remove */ + SCSI_HBA_LOG((_LOGUNCFG, self, NULL, + "devinfo smp@%s offline failed, device_remove", + addr)); + } + scsi_hba_devi_exit(self, circ); + return (DAM_SUCCESS); } /* ARGSUSED1 */ @@ -8013,7 +7974,6 @@ damap_name(tgtmap->tgtmap_dam[SCSI_TGT_SMP_DEVICE]), tgt_addr)); - (*tgtmap->tgtmap_deactivate_cb)(tgtmap->tgtmap_mappriv, tgt_addr, SCSI_TGT_SMP_DEVICE, tgt_privp); } @@ -8059,10 +8019,8 @@ int scsi_hba_tgtmap_create(dev_info_t *self, scsi_tgtmap_mode_t mode, - clock_t settle, int n_entries, - void *tgtmap_priv, scsi_tgt_activate_cb_t activate_cb, - scsi_tgt_deactivate_cb_t deactivate_cb, - scsi_hba_tgtmap_t **handle) + clock_t settle, void *tgtmap_priv, scsi_tgt_activate_cb_t activate_cb, + scsi_tgt_deactivate_cb_t deactivate_cb, scsi_hba_tgtmap_t **handle) { scsi_hba_tran_t *tran; damap_t *mapp; @@ -8070,8 +8028,9 @@ impl_scsi_tgtmap_t *tgtmap; damap_rptmode_t rpt_style; char *scsi_binding_set; - - if (self == NULL || settle == 0 || n_entries == 0 || handle == NULL) + int optflags; + + if (self == NULL || settle == 0 || handle == NULL) return (DDI_FAILURE); *handle = NULL; @@ -8101,10 +8060,15 @@ tgtmap->tgtmap_deactivate_cb = deactivate_cb; tgtmap->tgtmap_mappriv = tgtmap_priv; + optflags = (ddi_prop_get_int(DDI_DEV_T_ANY, self, + DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-enumeration", + scsi_enumeration) & SCSI_ENUMERATION_MT_TARGET_DISABLE) ? + DAMAP_SERIALCONFIG : DAMAP_MTCONFIG; + (void) snprintf(context, sizeof (context), "%s%d.tgtmap.scsi", ddi_driver_name(self), ddi_get_instance(self)); SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s", context)); - if (damap_create(context, n_entries, rpt_style, settle, + if (damap_create(context, rpt_style, optflags, settle, tgtmap, scsi_tgtmap_scsi_activate, scsi_tgtmap_scsi_deactivate, tran, scsi_tgtmap_scsi_config, scsi_tgtmap_scsi_unconfig, &mapp) != DAM_SUCCESS) { @@ -8116,8 +8080,9 @@ (void) snprintf(context, sizeof (context), "%s%d.tgtmap.smp", ddi_driver_name(self), ddi_get_instance(self)); SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s", context)); - if (damap_create(context, n_entries, rpt_style, settle, - tgtmap, scsi_tgtmap_smp_activate, scsi_tgtmap_smp_deactivate, + if (damap_create(context, rpt_style, optflags, + settle, tgtmap, scsi_tgtmap_smp_activate, + scsi_tgtmap_smp_deactivate, tran, scsi_tgtmap_smp_config, scsi_tgtmap_smp_unconfig, &mapp) != DAM_SUCCESS) { damap_destroy(tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE]); @@ -8157,7 +8122,6 @@ if (tgtmap->tgtmap_dam[i]) { SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s", damap_name(tgtmap->tgtmap_dam[i]))); - damap_destroy(tgtmap->tgtmap_dam[i]); } } @@ -8266,7 +8230,6 @@ for (i = 0; i < SCSI_TGT_NTYPES; i++) { if (tgtmap->tgtmap_dam[i] == NULL) continue; - context = damap_name(tgtmap->tgtmap_dam[i]); if (damap_addrset_end( tgtmap->tgtmap_dam[i], 0) != DAM_SUCCESS) { @@ -8797,108 +8760,95 @@ damap_t *iportmap_dam; } impl_scsi_iportmap_t; -static void -scsi_iportmap_config(void *arg, damap_t *mapp, damap_id_list_t id_list) +static int +scsi_iportmap_config(void *arg, damap_t *mapp, damap_id_t tgtid) { dev_info_t *self = (dev_info_t *)arg; int circ; - damap_id_t tgtid; char nameaddr[SCSI_MAXNAMELEN]; char *iport_addr; + dev_info_t *childp; scsi_hba_devi_enter(self, &circ); - for (tgtid = damap_id_next(mapp, id_list, NODAM); - tgtid != NODAM; - tgtid = damap_id_next(mapp, id_list, tgtid)) { - iport_addr = damap_id2addr(mapp, tgtid); - SCSI_HBA_LOG((_LOGIPT, self, NULL, - "%s @%s", damap_name(mapp), iport_addr)); - - (void) snprintf(nameaddr, sizeof (nameaddr), - "iport@%s", iport_addr); - (void) scsi_hba_bus_config_port(self, nameaddr, SE_HP); - } - + iport_addr = damap_id2addr(mapp, tgtid); + SCSI_HBA_LOG((_LOGIPT, self, NULL, + "%s @%s", damap_name(mapp), iport_addr)); + + (void) snprintf(nameaddr, sizeof (nameaddr), "iport@%s", iport_addr); + childp = scsi_hba_bus_config_port(self, nameaddr, SE_HP); scsi_hba_devi_exit(self, circ); -} - -static void -scsi_iportmap_unconfig(void *arg, damap_t *mapp, damap_id_list_t id_list) + return (childp != NULL ? DAM_SUCCESS : DAM_FAILURE); +} + +static int +scsi_iportmap_unconfig(void *arg, damap_t *mapp, damap_id_t tgtid) { dev_info_t *self = arg; - dev_info_t *child; /* iport child of HBA node */ - int circ; - damap_id_t tgtid; + dev_info_t *childp; /* iport child of HBA node */ + int circ, empty; char *addr; char nameaddr[SCSI_MAXNAMELEN]; scsi_hba_tran_t *tran; - int empty; - - for (tgtid = damap_id_next(mapp, id_list, NODAM); - tgtid != NODAM; - tgtid = damap_id_next(mapp, id_list, tgtid)) { - addr = damap_id2addr(mapp, tgtid); - SCSI_HBA_LOG((_LOGIPT, self, NULL, - "%s @%s", damap_name(mapp), addr)); - - (void) snprintf(nameaddr, sizeof (nameaddr), "iport@%s", addr); - scsi_hba_devi_enter(self, &circ); - if ((child = ndi_devi_findchild(self, nameaddr)) == NULL) { - scsi_hba_devi_exit(self, circ); - continue; - } - - tran = ddi_get_driver_private(child); - ASSERT(tran); - - ndi_hold_devi(child); + + addr = damap_id2addr(mapp, tgtid); + SCSI_HBA_LOG((_LOGIPT, self, NULL, "%s @%s", damap_name(mapp), addr)); + + (void) snprintf(nameaddr, sizeof (nameaddr), "iport@%s", addr); + scsi_hba_devi_enter(self, &circ); + if ((childp = ndi_devi_findchild(self, nameaddr)) == NULL) { scsi_hba_devi_exit(self, circ); - - /* - * A begin/end (clear) against the iport's - * tgtmap will trigger unconfigure of all - * targets on the iport. - * - * Future: This bit of code only works if the - * target map reporting style is are full - * reports and not per-address. Maybe we - * should plan on handling this by - * auto-unconfiguration when destroying the - * target map(s). - */ - (void) scsi_hba_tgtmap_set_begin( - tran->tran_tgtmap); - (void) scsi_hba_tgtmap_set_end( - tran->tran_tgtmap, 0); - - /* wait for unconfigure */ - empty = scsi_tgtmap_sync(tran->tran_tgtmap); - - scsi_hba_devi_enter(self, &circ); - ndi_rele_devi(child); - - /* If begin/end/sync ends in empty map, offline/remove. */ - if (empty) { - if (ndi_devi_offline(child, - NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) == DDI_SUCCESS) { - SCSI_HBA_LOG((_LOGUNCFG, self, NULL, - "devinfo iport@%s offlined and removed", - addr)); - } else if (ndi_devi_device_remove(child)) { - /* Offline/rem failed, note new device_remove */ - SCSI_HBA_LOG((_LOGUNCFG, self, NULL, - "devinfo iport@%s offline failed, " - "device_remove", addr)); - } - } - scsi_hba_devi_exit(self, circ); - } - -} + return (DAM_FAILURE); + } + + tran = ddi_get_driver_private(childp); + ASSERT(tran); + + ndi_hold_devi(childp); + scsi_hba_devi_exit(self, circ); + + /* + * A begin/end (clear) against the iport's + * tgtmap will trigger unconfigure of all + * targets on the iport. + * + * Future: This bit of code only works if the + * target map reporting style is are full + * reports and not per-address. Maybe we + * should plan on handling this by + * auto-unconfiguration when destroying the + * target map(s). + */ + (void) scsi_hba_tgtmap_set_begin(tran->tran_tgtmap); + (void) scsi_hba_tgtmap_set_end(tran->tran_tgtmap, 0); + + /* wait for unconfigure */ + empty = scsi_tgtmap_sync(tran->tran_tgtmap); + + scsi_hba_devi_enter(self, &circ); + ndi_rele_devi(childp); + + /* If begin/end/sync ends in empty map, offline/remove. */ + if (empty) { + if (ndi_devi_offline(childp, + NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) == DDI_SUCCESS) { + SCSI_HBA_LOG((_LOGUNCFG, self, NULL, + "devinfo iport@%s offlined and removed", + addr)); + } else if (ndi_devi_device_remove(childp)) { + /* Offline/rem failed, note new device_remove */ + SCSI_HBA_LOG((_LOGUNCFG, self, NULL, + "devinfo iport@%s offline failed, " + "device_remove", addr)); + } + } + scsi_hba_devi_exit(self, circ); + return (empty ? DAM_SUCCESS : DAM_FAILURE); +} + int -scsi_hba_iportmap_create(dev_info_t *self, clock_t settle, int n_entries, +scsi_hba_iportmap_create(dev_info_t *self, clock_t settle, scsi_hba_iportmap_t **handle) { scsi_hba_tran_t *tran; @@ -8906,7 +8856,7 @@ char context[64]; impl_scsi_iportmap_t *iportmap; - if (self == NULL || settle == 0 || n_entries == 0 || handle == NULL) + if (self == NULL || settle == 0 || handle == NULL) return (DDI_FAILURE); *handle = NULL; @@ -8922,8 +8872,8 @@ (void) snprintf(context, sizeof (context), "%s%d.iportmap", ddi_driver_name(self), ddi_get_instance(self)); - if (damap_create(context, n_entries, DAMAP_REPORT_PERADDR, settle, - NULL, NULL, NULL, self, + if (damap_create(context, DAMAP_REPORT_PERADDR, DAMAP_SERIALCONFIG, + settle, NULL, NULL, NULL, self, scsi_iportmap_config, scsi_iportmap_unconfig, &mapp) != DAM_SUCCESS) { return (DDI_FAILURE); @@ -9003,45 +8953,38 @@ return (DDI_FAILURE); } -static void -scsi_lunmap_config(void *arg, damap_t *lundam, damap_id_list_t id_list) + +static int +scsi_lunmap_config(void *arg, damap_t *lundam, damap_id_t lunid) { impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)arg; scsi_hba_tran_t *tran = tgtmap->tgtmap_tran; dev_info_t *self = tran->tran_iport_dip; - damap_id_t lunid; char *addr; - /* iterate over the LUNS we need to config */ - for (lunid = damap_id_next(lundam, id_list, NODAM); - lunid != NODAM; - lunid = damap_id_next(lundam, id_list, lunid)) { - addr = damap_id2addr(lundam, lunid); - SCSI_HBA_LOG((_LOGLUN, self, NULL, - "%s @%s", damap_name(lundam), addr)); - - (void) scsi_hba_bus_configone_addr(self, addr, SE_HP); - } -} - -static void -scsi_lunmap_unconfig(void *arg, damap_t *lundam, damap_id_list_t id_list) + addr = damap_id2addr(lundam, lunid); + SCSI_HBA_LOG((_LOGLUN, self, NULL, + "%s @%s", damap_name(lundam), addr)); + if (scsi_hba_bus_configone_addr(self, addr, SE_HP) != NULL) + return (DAM_SUCCESS); + else + return (DAM_FAILURE); +} + +static int +scsi_lunmap_unconfig(void *arg, damap_t *lundam, damap_id_t lunid) { impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)arg; scsi_hba_tran_t *tran = tgtmap->tgtmap_tran; dev_info_t *self = tran->tran_iport_dip; - damap_id_t lunid; char *addr; - for (lunid = damap_id_next(lundam, id_list, NODAM); - lunid != NODAM; - lunid = damap_id_next(lundam, id_list, lunid)) { - addr = damap_id2addr(lundam, lunid); - SCSI_HBA_LOG((_LOGLUN, self, NULL, - "%s @%s", damap_name(lundam), addr)); - - scsi_hba_bus_unconfigone_addr(self, addr); - } + addr = damap_id2addr(lundam, lunid); + SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s @%s", damap_name(lundam), + addr)); + + scsi_hba_bus_unconfigone_addr(self, addr); + return (DAM_SUCCESS); } static int @@ -9051,6 +8994,7 @@ damap_t *tgtdam; damap_id_t tgtid; damap_t *lundam; + int optflags; (void) snprintf(context, sizeof (context), "%s%d.%s.lunmap", ddi_driver_name(self), ddi_get_instance(self), taddr); @@ -9071,14 +9015,19 @@ return (DDI_FAILURE); } + optflags = (ddi_prop_get_int(DDI_DEV_T_ANY, self, + DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-enumeration", + scsi_enumeration) & SCSI_ENUMERATION_MT_LUN_DISABLE) ? + DAMAP_SERIALCONFIG : DAMAP_MTCONFIG; + /* NOTE: expected ref at tgtid/taddr: 2: caller + lookup. */ + ASSERT(damap_id_ref(tgtdam, tgtid) == 2); SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s creat, id %d ref %d", context, tgtid, damap_id_ref(tgtdam, tgtid))); /* create lundam */ - if (damap_create(context, LUNMAPSIZE, DAMAP_REPORT_FULLSET, 1, - NULL, NULL, NULL, - tgtmap, scsi_lunmap_config, scsi_lunmap_unconfig, + if (damap_create(context, DAMAP_REPORT_FULLSET, optflags, 1, + NULL, NULL, NULL, tgtmap, scsi_lunmap_config, scsi_lunmap_unconfig, &lundam) != DAM_SUCCESS) { SCSI_HBA_LOG((_LOG(1), self, NULL, "%s create failed, id %d ref %d", @@ -9123,6 +9072,7 @@ } /* NOTE: expected ref at tgtid/taddr: 3: priv_set + caller + lookup. */ + ASSERT(damap_id_ref(tgtdam, tgtid) == 3); SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s, id %d ref %d", damap_name(lundam), tgtid, damap_id_ref(tgtdam, tgtid))); @@ -9294,13 +9244,11 @@ } } -static void -sas_phymap_config(void *arg, damap_t *phydam, damap_id_list_t dl) +static int +sas_phymap_config(void *arg, damap_t *phydam, damap_id_t phyid) { impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)arg; char *context = damap_name(phymap->phymap_dam); - int pairs; - damap_id_t phyid; char *damn; char *name; bitset_t *phys; @@ -9312,119 +9260,103 @@ mutex_enter(&phymap->phymap_lock); phymap->phymap_reports = phymap->phymap_phys_noisy = 0; - /* count the number of local,remove pairs we need to config */ - for (pairs = 0, phyid = damap_id_next(phydam, dl, NODAM); - phyid != NODAM; - phyid = damap_id_next(phydam, dl, phyid)) - pairs++; - SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: config %d local,remote pairs", context, pairs)); - - for (phyid = damap_id_next(phydam, dl, NODAM); - phyid != NODAM; - phyid = damap_id_next(phydam, dl, phyid)) { - /* Get the name ("local,remote" address string) from damap. */ - damn = damap_id2addr(phydam, phyid); - - /* Get the bitset of phys currently forming the port. */ - phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, damn); - if (phys == NULL) { - SCSI_HBA_LOG((_LOG_NF(WARN), - "%s: %s: no phys", context, damn)); - continue; - } - - /* allocate, get, and initialize name index of name2ua map */ - if (ddi_soft_state_bystr_zalloc( - phymap->phymap_name2ua, damn) != DDI_SUCCESS) { - SCSI_HBA_LOG((_LOG_NF(WARN), - "%s: %s: failed name2ua alloc", context, damn)); - continue; - } - ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, damn); - if (ua == NULL) { - SCSI_HBA_LOG((_LOG_NF(WARN), - "%s: %s: no name2ua", context, damn)); - continue; - } - sas_phymap_bitset2phymaskua(phys, ua); /* set ua */ - - /* see if phymask ua index already allocated in ua2name map */ + /* Get the name ("local,remote" address string) from damap. */ + damn = damap_id2addr(phydam, phyid); + + /* Get the bitset of phys currently forming the port. */ + phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, damn); + if (phys == NULL) { + SCSI_HBA_LOG((_LOG_NF(WARN), "%s: %s: no phys", + context, damn)); + mutex_exit(&phymap->phymap_lock); + return (DAM_FAILURE); + } + + /* allocate, get, and initialize name index of name2ua map */ + if (ddi_soft_state_bystr_zalloc(phymap->phymap_name2ua, damn) != + DDI_SUCCESS) { + SCSI_HBA_LOG((_LOG_NF(WARN), + "%s: %s: failed name2ua alloc", context, damn)); + mutex_exit(&phymap->phymap_lock); + return (DAM_FAILURE); + } + if (!(ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, damn))) { + SCSI_HBA_LOG((_LOG_NF(WARN), + "%s: %s: no name2ua", context, damn)); + mutex_exit(&phymap->phymap_lock); + return (DAM_FAILURE); + } + sas_phymap_bitset2phymaskua(phys, ua); /* set ua */ + + /* see if phymask ua index already allocated in ua2name map */ + if (name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua)) { + /* + * The 'phymask' sas_phymap_bitset2phymaskua ua is + * already in use. This means that original phys have + * formed into a new port, and that the original port + * still exists (it has migrated to some completely + * different set of phys). In this corner-case we use + * "local,remote" name as a 'temporary' unit address. + * Reset ua in name2ua map. + */ + (void) strlcpy(ua, damn, SAS_PHY_NAME_LEN); name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua); if (name) { - /* - * The 'phymask' sas_phymap_bitset2phymaskua ua is - * already in use. This means that original phys have - * formed into a new port, and that the original port - * still exists (it has migrated to some completely - * different set of phys). In this corner-case we use - * "local,remote" name as a 'temporary' unit address. - * Reset ua in name2ua map. - */ - (void) strlcpy(ua, damn, SAS_PHY_NAME_LEN); - - name = ddi_soft_state_bystr_get( - phymap->phymap_ua2name, ua); - if (name) { - /* The "local,remote" ua should be new... */ - SCSI_HBA_LOG((_LOG_NF(WARN), - "%s: %s ua already configured", - context, ua)); - continue; - } - } - - /* allocate, get, and init ua index of ua2name map */ - if (ddi_soft_state_bystr_zalloc( - phymap->phymap_ua2name, ua) != DDI_SUCCESS) { - ddi_soft_state_bystr_free( - phymap->phymap_name2ua, damn); + /* The "local,remote" ua should be new... */ SCSI_HBA_LOG((_LOG_NF(WARN), - "%s: %s: failed ua2name alloc", - context, damn)); - continue; - } - name = ddi_soft_state_bystr_get( - phymap->phymap_ua2name, ua); - if (name == NULL) { - ddi_soft_state_bystr_free( - phymap->phymap_name2ua, damn); - SCSI_HBA_LOG((_LOG_NF(WARN), - "%s: %s: no ua2name", context, ua)); - continue; - } - - /* set name in ua2name map */ - (void) strlcpy(name, damn, SAS_PHY_NAME_LEN); - - SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: %s: ua %s: activate", context, damn, ua)); - if (phymap->phymap_acp) { + "%s: %s ua already configured", + context, ua)); mutex_exit(&phymap->phymap_lock); - ua_priv = NULL; - (phymap->phymap_acp)(phymap->phymap_private, - ua, &ua_priv); - mutex_enter(&phymap->phymap_lock); - - damap_id_priv_set(phydam, phyid, ua_priv); - } - SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: %s: ua %s: activate complete", context, damn, ua)); - } + return (DAM_SUCCESS); + } + } + + /* allocate, get, and init ua index of ua2name map */ + if (ddi_soft_state_bystr_zalloc(phymap->phymap_ua2name, ua) != + DDI_SUCCESS) { + ddi_soft_state_bystr_free(phymap->phymap_name2ua, damn); + SCSI_HBA_LOG((_LOG_NF(WARN), "%s: %s: failed ua2name alloc", + context, damn)); + mutex_exit(&phymap->phymap_lock); + return (DAM_FAILURE); + } + name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua); + if (name == NULL) { + ddi_soft_state_bystr_free(phymap->phymap_name2ua, damn); + SCSI_HBA_LOG((_LOG_NF(WARN), + "%s: %s: no ua2name", context, ua)); + mutex_exit(&phymap->phymap_lock); + return (DAM_FAILURE); + } + + /* set name in ua2name map */ + (void) strlcpy(name, damn, SAS_PHY_NAME_LEN); SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: config complete", context)); + "%s: %s: ua %s: activate", context, damn, ua)); + + if (phymap->phymap_acp) { + /* + * drop our lock and invoke the activation callback + */ + mutex_exit(&phymap->phymap_lock); + ua_priv = NULL; + (phymap->phymap_acp)(phymap->phymap_private, ua, &ua_priv); + mutex_enter(&phymap->phymap_lock); + damap_id_priv_set(phydam, phyid, ua_priv); + } + SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, + "%s: %s: ua %s: activate complete", context, damn, ua)); mutex_exit(&phymap->phymap_lock); + return (DAM_SUCCESS); } /*ARGSUSED*/ -static void -sas_phymap_unconfig(void *arg, damap_t *phydam, damap_id_list_t dl) +static int +sas_phymap_unconfig(void *arg, damap_t *phydam, damap_id_t phyid) { impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)arg; char *context = damap_name(phymap->phymap_dam); - int pairs; - damap_id_t phyid; char *damn; char *ua; void *ua_priv; @@ -9434,47 +9366,32 @@ mutex_enter(&phymap->phymap_lock); phymap->phymap_reports = phymap->phymap_phys_noisy = 0; - /* count the number of local,remove pairs we need to unconfig */ - for (pairs = 0, phyid = damap_id_next(phydam, dl, NODAM); - phyid != NODAM; - phyid = damap_id_next(phydam, dl, phyid)) - pairs++; - SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: unconfig %d local,remote pairs", context, pairs)); - - for (phyid = damap_id_next(phydam, dl, NODAM); - phyid != NODAM; - phyid = damap_id_next(phydam, dl, phyid)) { - /* Get the name ("local,remote" address string) from damap. */ - damn = damap_id2addr(phydam, phyid); - - ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, damn); - if (ua == NULL) { - SCSI_HBA_LOG((_LOG_NF(WARN), - "%s: %s: no name2ua", context, damn)); - continue; - } - - SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: %s: ua %s: deactivate", context, damn, ua)); - if (phymap->phymap_dcp) { - ua_priv = damap_id_priv_get(phydam, phyid); - mutex_exit(&phymap->phymap_lock); - (phymap->phymap_dcp)(phymap->phymap_private, - ua, ua_priv); - mutex_enter(&phymap->phymap_lock); - } - SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: %s: ua %s: deactivate complete", context, damn, ua)); - - /* delete ua<->name mappings */ - ddi_soft_state_bystr_free(phymap->phymap_ua2name, ua); - ddi_soft_state_bystr_free(phymap->phymap_name2ua, damn); + /* Get the name ("local,remote" address string) from damap. */ + damn = damap_id2addr(phydam, phyid); + + if (!(ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, damn))) { + SCSI_HBA_LOG((_LOG_NF(WARN), + "%s: %s: no name2ua", context, damn)); + mutex_exit(&phymap->phymap_lock); + return (DAM_FAILURE); } SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, - "%s: unconfig complete", context)); + "%s: %s: ua %s: deactivate", context, damn, ua)); + if (phymap->phymap_dcp) { + ua_priv = damap_id_priv_get(phydam, phyid); + mutex_exit(&phymap->phymap_lock); + (phymap->phymap_dcp)(phymap->phymap_private, ua, ua_priv); + mutex_enter(&phymap->phymap_lock); + } + SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, + "%s: %s: ua %s: deactivate complete", context, damn, ua)); + + /* delete ua<->name mappings */ + ddi_soft_state_bystr_free(phymap->phymap_ua2name, ua); + ddi_soft_state_bystr_free(phymap->phymap_name2ua, damn); mutex_exit(&phymap->phymap_lock); + return (DAM_SUCCESS); } int @@ -9506,8 +9423,8 @@ ddi_driver_name(self), ddi_get_instance(self)); SCSI_HBA_LOG((_LOGPHY, self, NULL, "%s", context)); - if (damap_create(context, SAS_PHY_NPHY, DAMAP_REPORT_PERADDR, settle, - NULL, NULL, NULL, + if (damap_create(context, DAMAP_REPORT_PERADDR, DAMAP_SERIALCONFIG, + settle, NULL, NULL, NULL, phymap, sas_phymap_config, sas_phymap_unconfig, &phymap->phymap_dam) != DAM_SUCCESS) goto fail;
--- a/usr/src/uts/common/os/damap.c Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/os/damap.c Mon Nov 16 09:55:18 2009 -0800 @@ -49,19 +49,21 @@ static int damap_debug = 0; #endif /* DEBUG */ +extern taskq_t *system_taskq; + static void dam_addrset_activate(dam_t *, bitset_t *); -static void dam_addrset_release(dam_t *, bitset_t *); -static void dam_activate_taskq(void *); +static void dam_addrset_deactivate(dam_t *, bitset_t *); +static void dam_stabilize_map(void *); static void dam_addr_stable_cb(void *); -static void dam_set_stable_cb(void *); +static void dam_addrset_stable_cb(void *); static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)()); -static void dam_add_report(dam_t *, dam_da_t *, id_t, int); -static void dam_release(dam_t *, id_t); -static void dam_release_report(dam_t *, id_t); -static void dam_deactivate_addr(dam_t *, id_t); +static void dam_addr_report(dam_t *, dam_da_t *, id_t, int); +static void dam_addr_release(dam_t *, id_t); +static void dam_addr_report_release(dam_t *, id_t); +static void dam_addr_deactivate(dam_t *, id_t); static id_t dam_get_addrid(dam_t *, char *); static int dam_kstat_create(dam_t *); -static void dam_kstat_destroy(dam_t *); +static int dam_map_alloc(dam_t *); #define DAM_INCR_STAT(mapp, stat) \ if ((mapp)->dam_kstatsp) { \ @@ -75,12 +77,28 @@ stp->stat.value.ui32 = (val); \ } + +/* + * increase damap size by 64 entries at a time + */ +#define DAM_SIZE_BUMP 64 + +/* + * config/unconfig taskq data + */ +typedef struct { + dam_t *tqd_mapp; + id_t tqd_id; +} cfg_tqd_t; + +extern pri_t maxclsyspri; + /* * Create new device address map * - * ident: map name (kstat) + * name: map name (kstat unique) * size: max # of map entries - * rptmode: type or mode of reporting + * mode: style of address reports: per-address or fullset * stable_usec: # of quiescent microseconds before report/map is stable * * activate_arg: address provider activation-callout private @@ -98,71 +116,89 @@ * DAM_FAILURE General failure */ int -damap_create(char *ident, size_t size, damap_rptmode_t rptmode, - clock_t stable_usec, - void *activate_arg, damap_activate_cb_t activate_cb, +damap_create(char *name, damap_rptmode_t mode, int map_opts, + clock_t stable_usec, void *activate_arg, damap_activate_cb_t activate_cb, damap_deactivate_cb_t deactivate_cb, void *config_arg, damap_configure_cb_t configure_cb, damap_unconfig_cb_t unconfig_cb, damap_t **damapp) { dam_t *mapp; - void *softstate_p; - DTRACE_PROBE1(damap__create__entry, char *, ident); - if ((configure_cb == NULL) || (unconfig_cb == NULL)) + if (configure_cb == NULL || unconfig_cb == NULL || name == NULL) return (DAM_EINVAL); - if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), size) != - DDI_SUCCESS) - return (DAM_FAILURE); + DTRACE_PROBE3(damap__create, char *, name, + damap_rptmode_t, mode, clock_t, stable_usec); mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP); - if (ddi_strid_init(&mapp->dam_addr_hash, size) != DDI_SUCCESS) { - ddi_soft_state_fini(&softstate_p); - kmem_free(mapp, sizeof (*mapp)); - return (DAM_FAILURE); - } - - mapp->dam_da = softstate_p; + mapp->dam_options = map_opts; mapp->dam_stabletmo = drv_usectohz(stable_usec); - mapp->dam_size = size; - mapp->dam_high = 1; - mapp->dam_rptmode = rptmode; - + mapp->dam_size = 0; + mapp->dam_rptmode = mode; mapp->dam_activate_arg = activate_arg; mapp->dam_activate_cb = (activate_cb_t)activate_cb; mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb; - mapp->dam_config_arg = config_arg; mapp->dam_configure_cb = (configure_cb_t)configure_cb; mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb; - - if (ident) - mapp->dam_name = i_ddi_strdup(ident, KM_SLEEP); - - bitset_init(&mapp->dam_active_set); - bitset_resize(&mapp->dam_active_set, size); - bitset_init(&mapp->dam_stable_set); - bitset_resize(&mapp->dam_stable_set, size); - bitset_init(&mapp->dam_report_set); - bitset_resize(&mapp->dam_report_set, size); + mapp->dam_name = i_ddi_strdup(name, KM_SLEEP); mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL); cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL); - mapp->dam_taskqp = ddi_taskq_create(NULL, ident, 1, TASKQ_DEFAULTPRI, - 0); + bitset_init(&mapp->dam_active_set); + bitset_init(&mapp->dam_stable_set); + bitset_init(&mapp->dam_report_set); *damapp = (damap_t *)mapp; - if (dam_kstat_create(mapp) != DDI_SUCCESS) { - damap_destroy((damap_t *)mapp); - return (DAM_FAILURE); - } - - DTRACE_PROBE1(damap__create__exit, dam_t *, mapp); return (DAM_SUCCESS); } /* - * Destroy device address map + * Allocate backing resources + * + * DAMs are lightly backed on create - major allocations occur + * at the time a report is made to the map, and are extended on + * a demand basis. + */ +static int +dam_map_alloc(dam_t *mapp) +{ + void *softstate_p; + + ASSERT(mutex_owned(&mapp->dam_lock)); + if (mapp->dam_flags & DAM_DESTROYPEND) + return (DAM_FAILURE); + + /* + * dam_high > 0 signals map allocation complete + */ + if (mapp->dam_high) + return (DAM_SUCCESS); + + mapp->dam_size = DAM_SIZE_BUMP; + if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), + mapp->dam_size) != DDI_SUCCESS) + return (DAM_FAILURE); + + if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) != + DDI_SUCCESS) { + ddi_soft_state_fini(softstate_p); + return (DAM_FAILURE); + } + if (dam_kstat_create(mapp) != DDI_SUCCESS) { + ddi_soft_state_fini(softstate_p); + ddi_strid_fini(&mapp->dam_addr_hash); + return (DAM_FAILURE); + } + mapp->dam_da = softstate_p; + mapp->dam_high = 1; + bitset_resize(&mapp->dam_active_set, mapp->dam_size); + bitset_resize(&mapp->dam_stable_set, mapp->dam_size); + bitset_resize(&mapp->dam_report_set, mapp->dam_size); + return (DAM_SUCCESS); +} + +/* + * Destroy address map * * damapp: address map * @@ -178,41 +214,56 @@ ASSERT(mapp); - DTRACE_PROBE2(damap__destroy__entry, dam_t *, mapp, char *, - mapp->dam_name); + DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name); - DAM_FLAG_SET(mapp, DAM_DESTROYPEND); - (void) damap_sync(damapp); + mutex_enter(&mapp->dam_lock); /* - * cancel pending timeouts and kill off the taskq + * prevent new reports from being added to the map */ - dam_sched_tmo(mapp, 0, NULL); - ddi_taskq_wait(mapp->dam_taskqp); - ddi_taskq_destroy(mapp->dam_taskqp); + mapp->dam_flags |= DAM_DESTROYPEND; + + if (mapp->dam_high) { + mutex_exit(&mapp->dam_lock); + /* + * wait for outstanding reports to stabilize and cancel + * the timer for this map + */ + (void) damap_sync(damapp); + mutex_enter(&mapp->dam_lock); + dam_sched_tmo(mapp, 0, NULL); - for (i = 1; i < mapp->dam_high; i++) { - if (ddi_get_soft_state(mapp->dam_da, i) == NULL) - continue; - if (DAM_IN_REPORT(mapp, i)) - dam_release_report(mapp, i); - if (DAM_IS_STABLE(mapp, i)) - dam_deactivate_addr(mapp, i); - ddi_strid_free(mapp->dam_addr_hash, i); - ddi_soft_state_free(mapp->dam_da, i); + /* + * map is at full stop + * release the contents of the map, invoking the + * detactivation protocol as addresses are released + */ + mutex_exit(&mapp->dam_lock); + for (i = 1; i < mapp->dam_high; i++) { + if (ddi_get_soft_state(mapp->dam_da, i) == NULL) + continue; + + ASSERT(DAM_IN_REPORT(mapp, i) == 0); + + if (DAM_IS_STABLE(mapp, i)) { + dam_addr_deactivate(mapp, i); + } else { + ddi_strid_free(mapp->dam_addr_hash, i); + ddi_soft_state_free(mapp->dam_da, i); + } + } + ddi_strid_fini(&mapp->dam_addr_hash); + ddi_soft_state_fini(&mapp->dam_da); + kstat_delete(mapp->dam_kstatsp); } - ddi_strid_fini(&mapp->dam_addr_hash); - ddi_soft_state_fini(&mapp->dam_da); bitset_fini(&mapp->dam_active_set); bitset_fini(&mapp->dam_stable_set); bitset_fini(&mapp->dam_report_set); - dam_kstat_destroy(mapp); mutex_destroy(&mapp->dam_lock); cv_destroy(&mapp->dam_cv); if (mapp->dam_name) kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1); kmem_free(mapp, sizeof (*mapp)); - DTRACE_PROBE(damap__destroy__exit); } /* @@ -223,26 +274,35 @@ int damap_sync(damap_t *damapp) { - -#define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND | MAP_LOCK) +#define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND) dam_t *mapp = (dam_t *)damapp; int none_active; ASSERT(mapp); - DTRACE_PROBE1(damap__sync__entry, dam_t *, mapp); + DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name, + dam_t *, mapp); + /* + * block where waiting for + * a) stabilization pending or a fullset update pending + * b) any scheduled timeouts to fire + * c) the report set to finalize (bitset is null) + */ mutex_enter(&mapp->dam_lock); while ((mapp->dam_flags & WAITFOR_FLAGS) || (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) { + DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name, + dam_t *, mapp); cv_wait(&mapp->dam_cv, &mapp->dam_lock); } none_active = bitset_is_null(&mapp->dam_active_set); mutex_exit(&mapp->dam_lock); - DTRACE_PROBE2(damap__sync__exit, dam_t *, mapp, int, none_active); + DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name, int, + none_active, dam_t *, mapp); return (none_active); } @@ -267,7 +327,7 @@ * * damapp: address map handle * address: address in ascii string representation - * rindx: index if address stabilizes + * addridp: address ID * nvl: optional nvlist of configuration-private data * addr_priv: optional provider-private (passed to activate/deactivate cb) * @@ -276,22 +336,23 @@ * DAM_MAPFULL address map exhausted */ int -damap_addr_add(damap_t *damapp, char *address, damap_id_t *ridx, nvlist_t *nvl, - void *addr_priv) +damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp, + nvlist_t *nvl, void *addr_priv) { dam_t *mapp = (dam_t *)damapp; id_t addrid; dam_da_t *passp; - DTRACE_PROBE2(damap__addr__add__entry, dam_t *, mapp, - char *, address); - if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || - (mapp->dam_flags & DAM_DESTROYPEND)) + if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR)) return (DAM_EINVAL); - DAM_LOCK(mapp, ADDR_LOCK); - if ((addrid = dam_get_addrid(mapp, address)) == 0) { - DAM_UNLOCK(mapp, ADDR_LOCK); + DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name, + char *, address, dam_t *, mapp); + + mutex_enter(&mapp->dam_lock); + if ((dam_map_alloc(mapp) != DAM_SUCCESS) || + ((addrid = dam_get_addrid(mapp, address)) == 0)) { + mutex_exit(&mapp->dam_lock); return (DAM_MAPFULL); } @@ -303,20 +364,20 @@ * the existing report */ if (DAM_IN_REPORT(mapp, addrid)) { - DAM_INCR_STAT(mapp, dam_rereport); - dam_release_report(mapp, addrid); + DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name, + char *, address, dam_t *, mapp); + DAM_INCR_STAT(mapp, dam_jitter); + dam_addr_report_release(mapp, addrid); passp->da_jitter++; } passp->da_ppriv_rpt = addr_priv; if (nvl) (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); - dam_add_report(mapp, passp, addrid, RPT_ADDR_ADD); - if (ridx != NULL) - *ridx = (damap_id_t)addrid; - DAM_UNLOCK(mapp, ADDR_LOCK); - DTRACE_PROBE3(damap__addr__add__exit, dam_t *, mapp, char *, - address, int, addrid); + dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD); + if (addridp != NULL) + *addridp = (damap_id_t)addrid; + mutex_exit(&mapp->dam_lock); return (DAM_SUCCESS); } @@ -337,28 +398,36 @@ id_t addrid; dam_da_t *passp; - DTRACE_PROBE2(damap__addr__del__entry, dam_t *, mapp, - char *, address); - if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || - (mapp->dam_flags & DAM_DESTROYPEND)) + if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR)) return (DAM_EINVAL); - DAM_LOCK(mapp, ADDR_LOCK); + DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name, + char *, address, dam_t *, mapp); + mutex_enter(&mapp->dam_lock); + if (dam_map_alloc(mapp) != DAM_SUCCESS) { + mutex_exit(&mapp->dam_lock); + return (DAM_MAPFULL); + } + + /* + * if reporting the removal of an address which is not in the map + * return success + */ if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) { - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); return (DAM_SUCCESS); } passp = ddi_get_soft_state(mapp->dam_da, addrid); ASSERT(passp); if (DAM_IN_REPORT(mapp, addrid)) { - DAM_INCR_STAT(mapp, dam_rereport); - dam_release_report(mapp, addrid); + DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name, + char *, address, dam_t *, mapp); + DAM_INCR_STAT(mapp, dam_jitter); + dam_addr_report_release(mapp, addrid); passp->da_jitter++; } - dam_add_report(mapp, passp, addrid, RPT_ADDR_DEL); - DAM_UNLOCK(mapp, ADDR_LOCK); - DTRACE_PROBE3(damap__addr__del__exit, dam_t *, mapp, - char *, address, int, addrid); + dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL); + mutex_exit(&mapp->dam_lock); return (DAM_SUCCESS); } @@ -376,35 +445,36 @@ dam_t *mapp = (dam_t *)damapp; int i; - DTRACE_PROBE1(damap__addrset__begin__entry, dam_t *, mapp); - - if ((mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || - (mapp->dam_flags & DAM_DESTROYPEND)) + if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) return (DAM_EINVAL); - DAM_LOCK(mapp, MAP_LOCK); - /* - * reset any pending reports - */ + DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *, + mapp); + mutex_enter(&mapp->dam_lock); + if (dam_map_alloc(mapp) != DAM_SUCCESS) { + mutex_exit(&mapp->dam_lock); + return (DAM_MAPFULL); + } if (mapp->dam_flags & DAM_SETADD) { + DTRACE_PROBE2(damap__addrset__begin__reset, char *, + mapp->dam_name, dam_t *, mapp); /* * cancel stabilization timeout */ dam_sched_tmo(mapp, 0, NULL); - DAM_INCR_STAT(mapp, dam_rereport); - DAM_UNLOCK(mapp, MAP_LOCK); - DAM_LOCK(mapp, ADDR_LOCK); + DAM_INCR_STAT(mapp, dam_jitter); + + /* + * clear pending reports + */ for (i = 1; i < mapp->dam_high; i++) { if (DAM_IN_REPORT(mapp, i)) - dam_release_report(mapp, i); + dam_addr_report_release(mapp, i); } - DAM_UNLOCK(mapp, ADDR_LOCK); - DAM_LOCK(mapp, MAP_LOCK); } - DAM_FLAG_SET(mapp, DAM_SETADD); bitset_zero(&mapp->dam_report_set); - DAM_UNLOCK(mapp, MAP_LOCK); - DTRACE_PROBE(damap__addrset__begin__exit); + mapp->dam_flags |= DAM_SETADD; + mutex_exit(&mapp->dam_lock); return (DAM_SUCCESS); } @@ -430,39 +500,38 @@ id_t addrid; dam_da_t *passp; - DTRACE_PROBE2(damap__addrset__add__entry, dam_t *, mapp, - char *, address); - - if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || - (mapp->dam_flags & DAM_DESTROYPEND)) + if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) return (DAM_EINVAL); - if (!(mapp->dam_flags & DAM_SETADD)) - return (DAM_FAILURE); + DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name, + char *, address, dam_t *, mapp); - DAM_LOCK(mapp, ADDR_LOCK); + mutex_enter(&mapp->dam_lock); + if (!(mapp->dam_flags & DAM_SETADD)) { + mutex_exit(&mapp->dam_lock); + return (DAM_FAILURE); + } + if ((addrid = dam_get_addrid(mapp, address)) == 0) { - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); return (DAM_MAPFULL); } passp = ddi_get_soft_state(mapp->dam_da, addrid); ASSERT(passp); if (DAM_IN_REPORT(mapp, addrid)) { - dam_release_report(mapp, addrid); + DTRACE_PROBE3(damap__addrset__add__jitter, char *, + mapp->dam_name, char *, address, dam_t *, mapp); + dam_addr_report_release(mapp, addrid); passp->da_jitter++; } passp->da_ppriv_rpt = addr_priv; if (nvl) (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); - DAM_LOCK(mapp, MAP_LOCK); bitset_add(&mapp->dam_report_set, addrid); - DAM_UNLOCK(mapp, MAP_LOCK); if (ridx) *ridx = (damap_id_t)addrid; - DAM_UNLOCK(mapp, ADDR_LOCK); - DTRACE_PROBE3(damap__addr__addset__exit, dam_t *, mapp, char *, - address, int, addrid); + mutex_exit(&mapp->dam_lock); return (DAM_SUCCESS); } @@ -482,31 +551,30 @@ dam_t *mapp = (dam_t *)damapp; int i; - DTRACE_PROBE1(damap__addrset__end__entry, dam_t *, mapp); - - if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || - (mapp->dam_flags & DAM_DESTROYPEND)) + if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) return (DAM_EINVAL); - if (!(mapp->dam_flags & DAM_SETADD)) - return (DAM_FAILURE); + DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name, + dam_t *, mapp); - if (flags & DAMAP_RESET) { - DAM_LOCK(mapp, MAP_LOCK); + mutex_enter(&mapp->dam_lock); + if (!(mapp->dam_flags & DAM_SETADD)) { + mutex_exit(&mapp->dam_lock); + return (DAM_FAILURE); + } + + if (flags & DAMAP_END_RESET) { + DTRACE_PROBE2(damap__addrset__end__reset, char *, + mapp->dam_name, dam_t *, mapp); dam_sched_tmo(mapp, 0, NULL); - DAM_UNLOCK(mapp, MAP_LOCK); - DAM_LOCK(mapp, ADDR_LOCK); for (i = 1; i < mapp->dam_high; i++) if (DAM_IN_REPORT(mapp, i)) - dam_release_report(mapp, i); - DAM_UNLOCK(mapp, ADDR_LOCK); + dam_addr_report_release(mapp, i); } else { mapp->dam_last_update = gethrtime(); - DAM_LOCK(mapp, MAP_LOCK); - dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); - DAM_UNLOCK(mapp, MAP_LOCK); + dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb); } - DTRACE_PROBE(damap__addrset__end__exit); + mutex_exit(&mapp->dam_lock); return (DAM_SUCCESS); } @@ -514,7 +582,7 @@ * Return nvlist registered with reported address * * damapp: address map handle - * aid: address ID + * addrid: address ID * * Returns: nvlist_t * provider supplied via damap_addr{set}_add()) * NULL @@ -523,11 +591,10 @@ damap_id2nvlist(damap_t *damapp, damap_id_t addrid) { dam_t *mapp = (dam_t *)damapp; - id_t aid = (id_t)addrid; dam_da_t *pass; - if (ddi_strid_id2str(mapp->dam_addr_hash, aid)) { - if (pass = ddi_get_soft_state(mapp->dam_da, aid)) + if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) { + if (pass = ddi_get_soft_state(mapp->dam_da, addrid)) return (pass->da_nvl); } return (NULL); @@ -537,83 +604,73 @@ * Return address string * * damapp: address map handle - * aid: address ID + * addrid: address ID * * Returns: char * Address string * NULL */ char * -damap_id2addr(damap_t *damapp, damap_id_t aid) +damap_id2addr(damap_t *damapp, damap_id_t addrid) { dam_t *mapp = (dam_t *)damapp; - return (ddi_strid_id2str(mapp->dam_addr_hash, (id_t)aid)); -} - -/* - * Hold address reference in map - * - * damapp: address map handle - * aid: address ID - * - * Returns: DAM_SUCCESS - * DAM_FAILURE - */ -int -damap_id_hold(damap_t *damapp, damap_id_t aid) -{ - dam_t *mapp = (dam_t *)damapp; - dam_da_t *passp; - - - DAM_LOCK(mapp, ADDR_LOCK); - passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); - if (!passp) { - DAM_UNLOCK(mapp, ADDR_LOCK); - return (DAM_FAILURE); - } - passp->da_ref++; - DAM_UNLOCK(mapp, ADDR_LOCK); - return (DAM_SUCCESS); + if (mapp->dam_high) + return (ddi_strid_id2str(mapp->dam_addr_hash, addrid)); + else + return (NULL); } /* * Release address reference in map * * damapp: address map handle - * aid: address ID + * addrid: address ID */ void damap_id_rele(damap_t *damapp, damap_id_t addrid) { dam_t *mapp = (dam_t *)damapp; + dam_da_t *passp; + char *addr; - DAM_LOCK(mapp, ADDR_LOCK); - dam_release(mapp, (id_t)addrid); - DAM_UNLOCK(mapp, ADDR_LOCK); + passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); + ASSERT(passp); + + addr = damap_id2addr(damapp, addrid); + DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr, + dam_t *, mapp, int, passp->da_ref); + + mutex_enter(&mapp->dam_lock); + + /* + * teardown address if last outstanding reference + */ + if (--passp->da_ref == 0) + dam_addr_release(mapp, (id_t)addrid); + + mutex_exit(&mapp->dam_lock); } /* * Return current reference count on address reference in map * * damapp: address map handle - * aid: address ID + * addrid: address ID * * Returns: DAM_SUCCESS * DAM_FAILURE */ int -damap_id_ref(damap_t *damapp, damap_id_t aid) +damap_id_ref(damap_t *damapp, damap_id_t addrid) { dam_t *mapp = (dam_t *)damapp; dam_da_t *passp; int ref = -1; - DAM_LOCK(mapp, ADDR_LOCK); - passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); + passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); if (passp) ref = passp->da_ref; - DAM_UNLOCK(mapp, ADDR_LOCK); + return (ref); } @@ -639,9 +696,11 @@ return ((damap_id_t)0); start = (int)last + 1; - for (i = start; i < mapp->dam_high; i++) - if (bitset_in_set(dam_list, i)) + for (i = start; i < mapp->dam_high; i++) { + if (bitset_in_set(dam_list, i)) { return ((damap_id_t)i); + } + } return ((damap_id_t)0); } @@ -649,51 +708,49 @@ * Set config private data * * damapp: address map handle - * aid: address ID + * addrid: address ID * cfg_priv: configuration private data * */ void -damap_id_priv_set(damap_t *damapp, damap_id_t aid, void *cfg_priv) +damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv) { dam_t *mapp = (dam_t *)damapp; dam_da_t *passp; - - DAM_LOCK(mapp, ADDR_LOCK); - passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); + mutex_enter(&mapp->dam_lock); + passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); if (!passp) { - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); return; } passp->da_cfg_priv = cfg_priv; - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); } /* * Get config private data * * damapp: address map handle - * aid: address ID + * addrid: address ID * * Returns: configuration private data */ void * -damap_id_priv_get(damap_t *damapp, damap_id_t aid) +damap_id_priv_get(damap_t *damapp, damap_id_t addrid) { dam_t *mapp = (dam_t *)damapp; dam_da_t *passp; void *rv; - - DAM_LOCK(mapp, ADDR_LOCK); - passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); + mutex_enter(&mapp->dam_lock); + passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); if (!passp) { - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); return (NULL); } rv = passp->da_cfg_priv; - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); return (rv); } @@ -715,10 +772,14 @@ id_t addrid = 0; dam_da_t *passp = NULL; - DAM_LOCK(mapp, ADDR_LOCK); - addrid = ddi_strid_str2id(mapp->dam_addr_hash, address); + DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name, + char *, address, dam_t *, mapp); + mutex_enter(&mapp->dam_lock); + if (!mapp->dam_high) + addrid = 0; + else + addrid = ddi_strid_str2id(mapp->dam_addr_hash, address); if (addrid) { - DAM_LOCK(mapp, MAP_LOCK); if (DAM_IS_STABLE(mapp, addrid)) { passp = ddi_get_soft_state(mapp->dam_da, addrid); ASSERT(passp); @@ -730,9 +791,10 @@ } else { addrid = 0; } - DAM_UNLOCK(mapp, MAP_LOCK); } - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); + DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name, + char *, address, dam_t *, mapp, int, addrid); return ((damap_id_t)addrid); } @@ -752,33 +814,46 @@ int mapsz = mapp->dam_size; int n_ids, i; bitset_t *bsp; + char *addrp; dam_da_t *passp; + DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name, + dam_t *, mapp); + mutex_enter(&mapp->dam_lock); + if (!mapp->dam_high) { + *id_listp = (damap_id_list_t)NULL; + mutex_exit(&mapp->dam_lock); + DTRACE_PROBE3(damap__lookup__all__nomap, char *, + mapp->dam_name, dam_t *, mapp, int, 0); + return (0); + } bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP); bitset_init(bsp); bitset_resize(bsp, mapsz); - DAM_LOCK(mapp, MAP_LOCK); bitset_copy(&mapp->dam_active_set, bsp); - DAM_UNLOCK(mapp, MAP_LOCK); - DAM_LOCK(mapp, ADDR_LOCK); for (n_ids = 0, i = 1; i < mapsz; i++) { if (bitset_in_set(bsp, i)) { passp = ddi_get_soft_state(mapp->dam_da, i); ASSERT(passp); if (passp) { + addrp = damap_id2addr(damapp, i); + DTRACE_PROBE3(damap__lookup__all__item, char *, + mapp->dam_name, char *, addrp, dam_t *, + mapp); passp->da_ref++; n_ids++; } } } - DAM_UNLOCK(mapp, ADDR_LOCK); if (n_ids) { *id_listp = (damap_id_list_t)bsp; + mutex_exit(&mapp->dam_lock); return (n_ids); } else { *id_listp = (damap_id_list_t)NULL; bitset_fini(bsp); kmem_free(bsp, sizeof (*bsp)); + mutex_exit(&mapp->dam_lock); return (0); } } @@ -798,111 +873,267 @@ if (id_list == NULL) return; - DAM_LOCK(mapp, ADDR_LOCK); + mutex_enter(&mapp->dam_lock); for (i = 1; i < mapp->dam_high; i++) { if (bitset_in_set((bitset_t *)id_list, i)) - (void) dam_release(mapp, i); + (void) dam_addr_release(mapp, i); } - DAM_UNLOCK(mapp, ADDR_LOCK); + mutex_exit(&mapp->dam_lock); bitset_fini((bitset_t *)id_list); kmem_free((void *)id_list, sizeof (bitset_t)); } /* + * activate an address that has passed the stabilization interval + */ +static void +dam_addr_activate(dam_t *mapp, id_t addrid) +{ + dam_da_t *passp; + int config_rv; + char *addrstr; + + mutex_enter(&mapp->dam_lock); + bitset_add(&mapp->dam_active_set, addrid); + passp = ddi_get_soft_state(mapp->dam_da, addrid); + ASSERT(passp); + + /* + * copy the reported nvlist and provider private data + */ + addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); + DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name, + char *, addrstr, dam_t *, mapp); + passp->da_nvl = passp->da_nvl_rpt; + passp->da_ppriv = passp->da_ppriv_rpt; + passp->da_ppriv_rpt = NULL; + passp->da_nvl_rpt = NULL; + passp->da_last_stable = gethrtime(); + passp->da_stable_cnt++; + mutex_exit(&mapp->dam_lock); + if (mapp->dam_activate_cb) { + (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr, + addrid, &passp->da_ppriv_rpt); + } + + /* + * call the address-specific configuration action as part of + * activation. + */ + config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, + addrid); + if (config_rv != DAM_SUCCESS) { + mutex_enter(&mapp->dam_lock); + passp->da_flags |= DA_FAILED_CONFIG; + mutex_exit(&mapp->dam_lock); + DTRACE_PROBE3(damap__addr__activate__config__failure, + char *, mapp->dam_name, char *, addrstr, dam_t *, mapp); + } + DTRACE_PROBE3(damap__addr__activate__end, char *, mapp->dam_name, + char *, addrstr, dam_t *, mapp); +} + +/* + * deactivate a previously stable address + */ +static void +dam_addr_deactivate(dam_t *mapp, id_t addrid) +{ + dam_da_t *passp; + char *addrstr; + + addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); + DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name, + char *, addrstr, dam_t *, mapp); + + /* + * call the unconfiguration callback + */ + (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid); + passp = ddi_get_soft_state(mapp->dam_da, addrid); + ASSERT(passp); + if (mapp->dam_deactivate_cb) + (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg, + ddi_strid_id2str(mapp->dam_addr_hash, addrid), + addrid, passp->da_ppriv); + + /* + * clear the active bit and free the backing info for + * this address + */ + mutex_enter(&mapp->dam_lock); + bitset_del(&mapp->dam_active_set, addrid); + passp->da_ppriv = NULL; + if (passp->da_nvl) + nvlist_free(passp->da_nvl); + passp->da_nvl = NULL; + passp->da_ppriv_rpt = NULL; + if (passp->da_nvl_rpt) + nvlist_free(passp->da_nvl_rpt); + passp->da_nvl_rpt = NULL; + + DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name, + char *, addrstr, dam_t *, mapp); + + (void) dam_addr_release(mapp, addrid); + mutex_exit(&mapp->dam_lock); +} + +/* + * taskq callback for multi-thread activation + */ +static void +dam_tq_config(void *arg) +{ + cfg_tqd_t *tqd = (cfg_tqd_t *)arg; + + dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id); + kmem_free(tqd, sizeof (*tqd)); +} + +/* + * taskq callback for multi-thread deactivation + */ +static void +dam_tq_unconfig(void *arg) +{ + cfg_tqd_t *tqd = (cfg_tqd_t *)arg; + + dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id); + kmem_free(tqd, sizeof (*tqd)); +} + +/* * Activate a set of stabilized addresses */ static void -dam_addrset_activate(dam_t *mapp, bitset_t *active_set) +dam_addrset_activate(dam_t *mapp, bitset_t *activate) { - dam_da_t *passp; - char *addrstr; - int i; - uint32_t n_active = 0; + + int i, nset; + taskq_t *tqp = NULL; + cfg_tqd_t *tqd = NULL; + char tqn[TASKQ_NAMELEN]; + extern pri_t maxclsyspri; + if (mapp->dam_options & DAMAP_MTCONFIG) { + /* + * calculate the # of taskq threads to create + */ + for (i = 1, nset = 0; i < mapp->dam_high; i++) + if (bitset_in_set(activate, i)) + nset++; + ASSERT(nset); + (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name); + tqp = taskq_create(tqn, nset, maxclsyspri, 1, + INT_MAX, TASKQ_PREPOPULATE); + } for (i = 1; i < mapp->dam_high; i++) { - if (bitset_in_set(&mapp->dam_active_set, i)) - n_active++; - if (!bitset_in_set(active_set, i)) - continue; - n_active++; - passp = ddi_get_soft_state(mapp->dam_da, i); - ASSERT(passp); - if (mapp->dam_activate_cb) { - addrstr = ddi_strid_id2str(mapp->dam_addr_hash, i); - (*mapp->dam_activate_cb)( - mapp->dam_activate_arg, addrstr, i, - &passp->da_ppriv_rpt); + if (bitset_in_set(activate, i)) { + if (!tqp) + dam_addr_activate(mapp, i); + else { + /* + * multi-threaded activation + */ + tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP); + tqd->tqd_mapp = mapp; + tqd->tqd_id = i; + (void) taskq_dispatch(tqp, dam_tq_config, + tqd, KM_SLEEP); + } } - DTRACE_PROBE2(damap__addrset__activate, dam_t *, mapp, int, i); - DAM_LOCK(mapp, MAP_LOCK); - bitset_add(&mapp->dam_active_set, i); - /* - * copy the reported nvlist and provider private data - */ - passp->da_nvl = passp->da_nvl_rpt; - passp->da_ppriv = passp->da_ppriv_rpt; - passp->da_ppriv_rpt = NULL; - passp->da_nvl_rpt = NULL; - passp->da_last_stable = gethrtime(); - passp->da_stable_cnt++; - DAM_UNLOCK(mapp, MAP_LOCK); - DAM_SET_STAT(mapp, dam_numstable, n_active); + } + if (tqp) { + taskq_wait(tqp); + taskq_destroy(tqp); } } /* - * Release a set of stabilized addresses + * Deactivate a set of stabilized addresses */ static void -dam_addrset_release(dam_t *mapp, bitset_t *release_set) +dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate) { - int i; + int i, nset; + taskq_t *tqp = NULL; + cfg_tqd_t *tqd = NULL; + char tqn[TASKQ_NAMELEN]; + + DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name, + dam_t *, mapp); - DAM_LOCK(mapp, ADDR_LOCK); + if (mapp->dam_options & DAMAP_MTCONFIG) { + /* + * compute the # of taskq threads to dispatch + */ + for (i = 1, nset = 0; i < mapp->dam_high; i++) + if (bitset_in_set(deactivate, i)) + nset++; + (void) snprintf(tqn, sizeof (tqn), "deactv-%s", + mapp->dam_name); + tqp = taskq_create(tqn, nset, maxclsyspri, 1, + INT_MAX, TASKQ_PREPOPULATE); + } for (i = 1; i < mapp->dam_high; i++) { - if (bitset_in_set(release_set, i)) { - DTRACE_PROBE2(damap__addrset__release, dam_t *, mapp, - int, i); - DAM_LOCK(mapp, MAP_LOCK); - bitset_del(&mapp->dam_active_set, i); - DAM_UNLOCK(mapp, MAP_LOCK); - (void) dam_release(mapp, i); + if (bitset_in_set(deactivate, i)) { + if (!tqp) { + dam_addr_deactivate(mapp, i); + } else { + tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP); + tqd->tqd_mapp = mapp; + tqd->tqd_id = i; + (void) taskq_dispatch(tqp, + dam_tq_unconfig, tqd, KM_SLEEP); + } } } - DAM_UNLOCK(mapp, ADDR_LOCK); + + if (tqp) { + taskq_wait(tqp); + taskq_destroy(tqp); + } } /* - * release a previously activated address + * Release a previously activated address */ static void -dam_release(dam_t *mapp, id_t addrid) +dam_addr_release(dam_t *mapp, id_t addrid) { dam_da_t *passp; + char *addrstr; - DAM_ASSERT_LOCKED(mapp, ADDR_LOCK); + + ASSERT(mutex_owned(&mapp->dam_lock)); passp = ddi_get_soft_state(mapp->dam_da, addrid); ASSERT(passp); - /* - * invoke the deactivation callback to notify - * this address is no longer active - */ - dam_deactivate_addr(mapp, addrid); + addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); + DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name, + char *, addrstr, dam_t *, mapp); /* - * allow pending reports for this address to stabilize + * defer releasing the address until outstanding references + * are released */ - if (DAM_IN_REPORT(mapp, addrid)) + if (passp->da_ref > 1) { + DTRACE_PROBE4(damap__addr__release__outstanding__refs, + char *, mapp->dam_name, char *, addrstr, dam_t *, mapp, + int, passp->da_ref); return; + } /* - * defer teardown until outstanding references are released + * allow pending reports to stabilize */ - if (--passp->da_ref) { - passp->da_flags |= DA_RELE; + if (DAM_IN_REPORT(mapp, addrid)) { + DTRACE_PROBE3(damap__addr__release__report__pending, + char *, mapp->dam_name, char *, addrstr, dam_t *, mapp); return; } + ddi_strid_free(mapp->dam_addr_hash, addrid); ddi_soft_state_free(mapp->dam_da, addrid); } @@ -911,13 +1142,17 @@ * process stabilized address reports */ static void -dam_activate_taskq(void *arg) +dam_stabilize_map(void *arg) { dam_t *mapp = (dam_t *)arg; bitset_t delta; bitset_t cfg; bitset_t uncfg; int has_cfg, has_uncfg; + uint32_t i, n_active; + + DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name, + dam_t *, mapp); bitset_init(&delta); bitset_resize(&delta, mapp->dam_size); @@ -926,40 +1161,81 @@ bitset_init(&uncfg); bitset_resize(&uncfg, mapp->dam_size); - DTRACE_PROBE1(damap__activate__taskq__entry, dam_t, mapp); - DAM_LOCK(mapp, MAP_LOCK); + /* + * determine which addresses have changed during + * this stabilization cycle + */ + mutex_enter(&mapp->dam_lock); + ASSERT(mapp->dam_flags & DAM_SPEND); if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set, &delta)) { + /* + * no difference + */ bitset_zero(&mapp->dam_stable_set); - DAM_FLAG_CLR(mapp, DAM_SPEND); - DAM_UNLOCK(mapp, MAP_LOCK); + mapp->dam_flags &= ~DAM_SPEND; + cv_signal(&mapp->dam_cv); + mutex_exit(&mapp->dam_lock); bitset_fini(&uncfg); bitset_fini(&cfg); bitset_fini(&delta); + DTRACE_PROBE2(damap__stabilize__map__nochange, char *, + mapp->dam_name, dam_t *, mapp); return; } + + /* + * compute the sets of addresses to be activated and deactivated + */ has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg); has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg); - DAM_UNLOCK(mapp, MAP_LOCK); - if (has_cfg) { + + /* + * drop map lock while invoking callouts + */ + mutex_exit(&mapp->dam_lock); + + /* + * activate all newly stable addresss + */ + if (has_cfg) dam_addrset_activate(mapp, &cfg); - (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, &cfg); - } - if (has_uncfg) { - (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, &uncfg); - dam_addrset_release(mapp, &uncfg); - } - DAM_LOCK(mapp, MAP_LOCK); + + /* + * deactivate addresss which are no longer in the map + */ + if (has_uncfg) + dam_addrset_deactivate(mapp, &uncfg); + + + /* + * timestamp the last stable time and increment the kstat keeping + * the # of of stable cycles for the map + */ + mutex_enter(&mapp->dam_lock); bitset_zero(&mapp->dam_stable_set); - DAM_FLAG_CLR(mapp, DAM_SPEND); mapp->dam_last_stable = gethrtime(); mapp->dam_stable_cnt++; - DAM_INCR_STAT(mapp, dam_stable); - DAM_UNLOCK(mapp, MAP_LOCK); + DAM_INCR_STAT(mapp, dam_cycles); + + /* + * determine the number of stable addresses + * and update the n_active kstat for this map + */ + for (i = 1, n_active = 0; i < mapp->dam_high; i++) + if (bitset_in_set(&mapp->dam_active_set, i)) + n_active++; + DAM_SET_STAT(mapp, dam_active, n_active); + + DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name, + dam_t *, mapp, int, n_active); + + mapp->dam_flags &= ~DAM_SPEND; + cv_signal(&mapp->dam_cv); + mutex_exit(&mapp->dam_lock); bitset_fini(&uncfg); bitset_fini(&cfg); bitset_fini(&delta); - DTRACE_PROBE1(damap__activate__taskq__exit, dam_t, mapp); } /* @@ -977,61 +1253,59 @@ int64_t tmo_delta; int64_t ts = ddi_get_lbolt64(); - DTRACE_PROBE1(damap__addr__stable__cb__entry, dam_t *, mapp); - DAM_LOCK(mapp, MAP_LOCK); + mutex_enter(&mapp->dam_lock); if (mapp->dam_tid == 0) { - DAM_UNLOCK(mapp, MAP_LOCK); + DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *, + mapp->dam_name, dam_t *, mapp); + mutex_exit(&mapp->dam_lock); return; } mapp->dam_tid = 0; + /* * If still under stabilization, reschedule timeout, - * else dispatch the task to activate & deactivate the stable - * set. + * otherwise dispatch the task to activate and deactivate the + * new stable address */ if (mapp->dam_flags & DAM_SPEND) { - DAM_INCR_STAT(mapp, dam_stable_blocked); + DAM_INCR_STAT(mapp, dam_overrun); mapp->dam_stable_overrun++; dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); - DAM_UNLOCK(mapp, MAP_LOCK); - DTRACE_PROBE1(damap__addr__stable__cb__overrun, - dam_t *, mapp); + DTRACE_PROBE2(damap__map__addr__stable__overrun, char *, + mapp->dam_name, dam_t *, mapp); + mutex_exit(&mapp->dam_lock); return; } + DAM_SET_STAT(mapp, dam_overrun, 0); + mapp->dam_stable_overrun = 0; + + /* + * copy the current active set to the stable map + * for each address being reported, decrement its + * stabilize deadline, and if stable, add or remove the + * address from the stable set + */ bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set); for (i = 1; i < mapp->dam_high; i++) { if (!bitset_in_set(&mapp->dam_report_set, i)) continue; - /* - * Stabilize each address - */ passp = ddi_get_soft_state(mapp->dam_da, i); ASSERT(passp); - if (!passp) { - cmn_err(CE_WARN, "Clearing report no softstate %d", i); - bitset_del(&mapp->dam_report_set, i); - continue; - } /* report has stabilized */ if (passp->da_deadline <= ts) { bitset_del(&mapp->dam_report_set, i); - if (passp->da_flags & DA_RELE) { - DTRACE_PROBE2(damap__addr__stable__del, - dam_t *, mapp, int, i); + if (passp->da_flags & DA_RELE) bitset_del(&mapp->dam_stable_set, i); - } else { - DTRACE_PROBE2(damap__addr__stable__add, - dam_t *, mapp, int, i); + else bitset_add(&mapp->dam_stable_set, i); - } spend++; continue; } /* - * not stabilized, determine next (future) map timeout + * not stabilized, determine next map timeout */ tpend++; tmo_delta = passp->da_deadline - ts; @@ -1040,149 +1314,155 @@ } /* - * schedule taskq activation of stabilized reports + * schedule system_taskq activation of stabilized reports */ if (spend) { - if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, - mapp, DDI_NOSLEEP) == DDI_SUCCESS) { - DAM_FLAG_SET(mapp, DAM_SPEND); - } else + if (taskq_dispatch(system_taskq, dam_stabilize_map, + mapp, TQ_NOSLEEP)) { + mapp->dam_flags |= DAM_SPEND; + DTRACE_PROBE2(damap__map__addr__stable__start, char *, + mapp->dam_name, dam_t *, mapp); + } else { tpend++; + } } /* - * schedule timeout to handle future stabalization of active reports + * reschedule the stabilization timer if there are reports + * still pending */ if (tpend) dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb); - DAM_UNLOCK(mapp, MAP_LOCK); - DTRACE_PROBE1(damap__addr__stable__cb__exit, dam_t *, mapp); + + mutex_exit(&mapp->dam_lock); } /* - * fullset stabilization timeout + * fullset stabilization timeout callback */ static void -dam_set_stable_cb(void *arg) +dam_addrset_stable_cb(void *arg) { dam_t *mapp = (dam_t *)arg; - DTRACE_PROBE1(damap__set__stable__cb__enter, dam_t *, mapp); - - DAM_LOCK(mapp, MAP_LOCK); + mutex_enter(&mapp->dam_lock); if (mapp->dam_tid == 0) { - DAM_UNLOCK(mapp, MAP_LOCK); + mutex_exit(&mapp->dam_lock); + DTRACE_PROBE2(damap__map__addrset__stable__cancelled, + char *, mapp->dam_name, dam_t *, mapp); return; } mapp->dam_tid = 0; /* - * If still under stabilization, reschedule timeout, - * else dispatch the task to activate & deactivate the stable - * set. + * If map still underoing stabilization reschedule timeout, + * else dispatch the task to configure the new stable set of + * addresses. */ - if (mapp->dam_flags & DAM_SPEND) { - DAM_INCR_STAT(mapp, dam_stable_blocked); + if ((mapp->dam_flags & DAM_SPEND) || (taskq_dispatch(system_taskq, + dam_stabilize_map, mapp, TQ_NOSLEEP) == NULL)) { + DAM_INCR_STAT(mapp, dam_overrun); mapp->dam_stable_overrun++; - dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); - DTRACE_PROBE1(damap__set__stable__cb__overrun, - dam_t *, mapp); - } else if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, - mapp, DDI_NOSLEEP) == DDI_FAILURE) { - dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); - } else { - bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set); - bitset_zero(&mapp->dam_report_set); - DAM_FLAG_CLR(mapp, DAM_SETADD); - DAM_FLAG_SET(mapp, DAM_SPEND); + dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb); + DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *, + mapp->dam_name, dam_t *, mapp); + mutex_exit(&mapp->dam_lock); + return; } - DAM_UNLOCK(mapp, MAP_LOCK); - DTRACE_PROBE1(damap__set__stable__cb__exit, dam_t *, mapp); + + DAM_SET_STAT(mapp, dam_overrun, 0); + mapp->dam_stable_overrun = 0; + bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set); + bitset_zero(&mapp->dam_report_set); + mapp->dam_flags |= DAM_SPEND; + mapp->dam_flags &= ~DAM_SETADD; + DTRACE_PROBE2(damap__map__addrset__stable__start, char *, + mapp->dam_name, dam_t *, mapp); + mutex_exit(&mapp->dam_lock); } /* - * reschedule map timeout 'tmo_ms' ticks + * schedule map timeout 'tmo_ms' ticks + * if map timer is currently running, cancel if tmo_ms == 0 */ static void dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)()) { timeout_id_t tid; + DTRACE_PROBE3(damap__sched__tmo, char *, mapp->dam_name, dam_t *, mapp, + clock_t, tmo_ms); + + ASSERT(mutex_owned(&mapp->dam_lock)); if ((tid = mapp->dam_tid) != 0) { - mapp->dam_tid = 0; - DAM_UNLOCK(mapp, MAP_LOCK); - (void) untimeout(tid); - DAM_LOCK(mapp, MAP_LOCK); + if (tmo_ms == 0) { + mapp->dam_tid = 0; + mutex_exit(&mapp->dam_lock); + (void) untimeout(tid); + mutex_enter(&mapp->dam_lock); + } + } else { + if (tmo_cb && (tmo_ms != 0)) + mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms); } - - if (tmo_cb && (tmo_ms != 0)) - mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms); } /* - * record report addition or removal of an address + * report addition or removal of an address */ static void -dam_add_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int report) +dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type) { + char *addrstr = damap_id2addr((damap_t *)mapp, addrid); + + DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name, + char *, addrstr, dam_t *, mapp, int, rpt_type); + + ASSERT(mutex_owned(&mapp->dam_lock)); ASSERT(!DAM_IN_REPORT(mapp, addrid)); passp->da_last_report = gethrtime(); mapp->dam_last_update = gethrtime(); passp->da_report_cnt++; passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo; - if (report == RPT_ADDR_DEL) + if (rpt_type == RPT_ADDR_DEL) passp->da_flags |= DA_RELE; - else if (report == RPT_ADDR_ADD) + else if (rpt_type == RPT_ADDR_ADD) passp->da_flags &= ~DA_RELE; - DAM_LOCK(mapp, MAP_LOCK); bitset_add(&mapp->dam_report_set, addrid); dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); - DAM_UNLOCK(mapp, MAP_LOCK); - } /* * release an address report */ static void -dam_release_report(dam_t *mapp, id_t addrid) +dam_addr_report_release(dam_t *mapp, id_t addrid) { dam_da_t *passp; + char *addrstr = damap_id2addr((damap_t *)mapp, addrid); + DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name, + char *, addrstr, dam_t *, mapp); + + ASSERT(mutex_owned(&mapp->dam_lock)); passp = ddi_get_soft_state(mapp->dam_da, addrid); ASSERT(passp); + /* + * clear the report bit + * if the address has a registered deactivation handler and + * the address has not stabilized, deactivate the address + */ + bitset_del(&mapp->dam_report_set, addrid); + if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb) { + mutex_exit(&mapp->dam_lock); + (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg, + ddi_strid_id2str(mapp->dam_addr_hash, addrid), + addrid, passp->da_ppriv_rpt); + mutex_enter(&mapp->dam_lock); + } passp->da_ppriv_rpt = NULL; if (passp->da_nvl_rpt) nvlist_free(passp->da_nvl_rpt); - passp->da_nvl_rpt = NULL; - DAM_LOCK(mapp, MAP_LOCK); - bitset_del(&mapp->dam_report_set, addrid); - DAM_UNLOCK(mapp, MAP_LOCK); -} - -/* - * deactivate a previously stable address - */ -static void -dam_deactivate_addr(dam_t *mapp, id_t addrid) -{ - dam_da_t *passp; - - passp = ddi_get_soft_state(mapp->dam_da, addrid); - ASSERT(passp); - if (passp == NULL) - return; - DAM_UNLOCK(mapp, ADDR_LOCK); - if (mapp->dam_deactivate_cb) - (*mapp->dam_deactivate_cb)( - mapp->dam_activate_arg, - ddi_strid_id2str(mapp->dam_addr_hash, - addrid), addrid, passp->da_ppriv); - DAM_LOCK(mapp, ADDR_LOCK); - passp->da_ppriv = NULL; - if (passp->da_nvl) - nvlist_free(passp->da_nvl); - passp->da_nvl = NULL; } /* @@ -1194,8 +1474,9 @@ damap_id_t addrid; dam_da_t *passp; + ASSERT(mutex_owned(&mapp->dam_lock)); if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) { - if ((addrid = ddi_strid_fixed_alloc(mapp->dam_addr_hash, + if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash, address)) == (damap_id_t)0) { return (0); } @@ -1204,16 +1485,25 @@ ddi_strid_free(mapp->dam_addr_hash, addrid); return (0); } + if (addrid >= mapp->dam_high) mapp->dam_high = addrid + 1; + + /* + * expand bitmaps if ID has outgrown old map size + */ + if (mapp->dam_high > mapp->dam_size) { + mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP; + bitset_resize(&mapp->dam_active_set, mapp->dam_size); + bitset_resize(&mapp->dam_stable_set, mapp->dam_size); + bitset_resize(&mapp->dam_report_set, mapp->dam_size); + } + + passp = ddi_get_soft_state(mapp->dam_da, addrid); + passp->da_ref = 1; + passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash, + addrid); /* for mdb */ } - passp = ddi_get_soft_state(mapp->dam_da, addrid); - if (passp == NULL) - return (0); - passp->da_ref++; - if (passp->da_addr == NULL) - passp->da_addr = ddi_strid_id2str( - mapp->dam_addr_hash, addrid); /* for mdb */ return (addrid); } @@ -1229,30 +1519,16 @@ mapsp = kstat_create("dam", 0, mapp->dam_name, "damap", KSTAT_TYPE_NAMED, sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0); - if (mapsp == NULL) { + + if (mapsp == NULL) return (DDI_FAILURE); - } statsp = (struct dam_kstats *)mapsp->ks_data; - kstat_named_init(&statsp->dam_stable, "stable cycles", - KSTAT_DATA_UINT32); - kstat_named_init(&statsp->dam_stable_blocked, - "stable cycle overrun", KSTAT_DATA_UINT32); - kstat_named_init(&statsp->dam_rereport, - "restarted reports", KSTAT_DATA_UINT32); - kstat_named_init(&statsp->dam_numstable, - "# of stable map entries", KSTAT_DATA_UINT32); + kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32); + kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32); + kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32); + kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32); kstat_install(mapsp); mapp->dam_kstatsp = mapsp; return (DDI_SUCCESS); } - -/* - * destroy map stats - */ -static void -dam_kstat_destroy(dam_t *mapp) -{ - - kstat_delete(mapp->dam_kstatsp); -}
--- a/usr/src/uts/common/os/sunddi.c Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/os/sunddi.c Mon Nov 16 09:55:18 2009 -0800 @@ -6679,6 +6679,8 @@ hash_sz = SS_MAX_HASH_SZ; ss = kmem_alloc(sizeof (*ss), KM_SLEEP); + ss->strid_chunksz = n_items; + ss->strid_spacesz = n_items; ss->strid_space = id_space_create("strid", 1, n_items); ss->strid_bystr = mod_hash_create_strhash("strid_bystr", hash_sz, mod_hash_null_valdtor); @@ -6688,11 +6690,9 @@ return (DDI_SUCCESS); } -#define ID_FIXED_SIZE 0x1 - /* allocate an id mapping within the specified set for str, return id */ static id_t -i_ddi_strid_alloc(ddi_strid *strid, char *str, int flags) +i_ddi_strid_alloc(ddi_strid *strid, char *str) { i_ddi_strid *ss = (i_ddi_strid *)strid; id_t id; @@ -6708,15 +6708,16 @@ * the amount of space used when the id is used as a ddi_soft_state * index by the caller. * - * If ID_FIXED_SIZE, use the _nosleep variant to fail rather - * than sleep in id_allocff() - */ - if (flags & ID_FIXED_SIZE) { - id = id_allocff_nosleep(ss->strid_space); - if (id == (id_t)-1) + * If the id list is exhausted, increase the size of the list + * by the chuck size specified in ddi_strid_init and reattempt + * the allocation + */ + if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1) { + id_space_extend(ss->strid_space, ss->strid_spacesz, + ss->strid_spacesz + ss->strid_chunksz); + ss->strid_spacesz += ss->strid_chunksz; + if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1) return (0); - } else { - id = id_allocff(ss->strid_space); } /* @@ -6744,14 +6745,7 @@ id_t ddi_strid_alloc(ddi_strid *strid, char *str) { - return (i_ddi_strid_alloc(strid, str, 0)); -} - -/* allocate an id mapping within the specified set for str, return id */ -id_t -ddi_strid_fixed_alloc(ddi_strid *strid, char *str) -{ - return (i_ddi_strid_alloc(strid, str, ID_FIXED_SIZE)); + return (i_ddi_strid_alloc(strid, str)); } /* return the id within the specified strid given the str */
--- a/usr/src/uts/common/sys/damap.h Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/sys/damap.h Mon Nov 16 09:55:18 2009 -0800 @@ -84,11 +84,15 @@ /* * damap_t: Handle to a delta address map * damap_id_t: Handle to an entry of damap_t - * damap_id_list_t: List of damap_id_handles */ typedef struct __damap_dm *damap_t; +typedef id_t damap_id_t; + +/* + * damap_id_list_t: List of damap_id_handles + * NB. Not Used + */ typedef struct __damap_id_list *damap_id_list_t; -typedef id_t damap_id_t; #define NODAM (damap_id_t)0 @@ -102,17 +106,23 @@ typedef void (*damap_activate_cb_t)(void *, char *, int, void **); typedef void (*damap_deactivate_cb_t)(void *, char *, int, void *); -typedef void (*damap_configure_cb_t)(void *, damap_t *, damap_id_list_t); -typedef void (*damap_unconfig_cb_t)(void *, damap_t *, damap_id_list_t); +typedef int (*damap_configure_cb_t)(void *, damap_t *, damap_id_t); +typedef int (*damap_unconfig_cb_t)(void *, damap_t *, damap_id_t); /* * Map reporting mode */ typedef enum {DAMAP_REPORT_PERADDR, DAMAP_REPORT_FULLSET} damap_rptmode_t; -#define DAMAP_RESET 1 /* flag to damap_addrset_end */ +/* + * Map create options flags + * DAMAP_SERIALCONFIG - serialize activate/deactivate operations + * DAMAP_MTCONFIG - multithread config/unconfg operations + */ +#define DAMAP_SERIALCONFIG 0 +#define DAMAP_MTCONFIG 1 -int damap_create(char *, size_t, damap_rptmode_t, clock_t, +int damap_create(char *, damap_rptmode_t, int, clock_t, void *, damap_activate_cb_t, damap_deactivate_cb_t, void *, damap_configure_cb_t, damap_unconfig_cb_t, damap_t **); @@ -125,11 +135,17 @@ int damap_addr_del(damap_t *, char *); int damap_addrid_del(damap_t *, int); -int damap_addrset_begin(damap_t *); -int damap_addrset_add(damap_t *, char *, damap_id_t *, nvlist_t *, void *); -int damap_addrset_end(damap_t *, int); -int damap_addrset_reset(damap_t *, int); +/* + * modifiers to damap_addrset_end() + */ +#define DAMAP_END_RESET 1 +#define DAMAP_END_ABORT 2 +int damap_addrset_begin(damap_t *); +int damap_addrset_add(damap_t *, char *, damap_id_t *, + nvlist_t *, void *); +int damap_addrset_end(damap_t *, int); +int damap_addrset_reset(damap_t *, int); damap_id_t damap_id_next(damap_t *, damap_id_list_t, damap_id_t); char *damap_id2addr(damap_t *, damap_id_t); nvlist_t *damap_id2nvlist(damap_t *, damap_id_t);
--- a/usr/src/uts/common/sys/damap_impl.h Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/sys/damap_impl.h Mon Nov 16 09:55:18 2009 -0800 @@ -57,13 +57,14 @@ typedef void (*activate_cb_t)(void *, char *addr, int idx, void **privp); typedef void (*deactivate_cb_t)(void *, char *addr, int idx, void *priv); -typedef void (*configure_cb_t)(void *, dam_t *mapp, bitset_t *config_ids); -typedef void (*unconfig_cb_t)(void *, dam_t *mapp, bitset_t *unconfig_ids); +typedef int (*configure_cb_t)(void *, dam_t *mapp, id_t map_id); +typedef int (*unconfig_cb_t)(void *, dam_t *mapp, id_t map_id); + struct dam { char *dam_name; - int dam_flags; /* state and locks */ - int dam_options; /* options at map creation */ + int dam_flags; /* map state and cv flags */ + int dam_options; /* map options */ int dam_rptmode; /* report mode */ clock_t dam_stabletmo; /* stabilization (ticks) */ uint_t dam_size; /* max index for addr hash */ @@ -83,7 +84,6 @@ bitset_t dam_stable_set; /* stable address set */ bitset_t dam_report_set; /* reported address set */ void *dam_da; /* per-address soft state */ - ddi_taskq_t *dam_taskqp; /* taskq for map activation */ hrtime_t dam_last_update; /* last map update */ hrtime_t dam_last_stable; /* last map stable */ int dam_stable_cnt; /* # of times map stabilized */ @@ -93,46 +93,16 @@ kstat_t *dam_kstatsp; }; -/* - * damap.dam_flags - */ -#define ADDR_LOCK 0x1000 /* per-addr lock */ -#define MAP_LOCK 0x2000 /* global map lock */ -#define DAM_LOCK(m, l) { \ - mutex_enter(&(m)->dam_lock); \ - while ((m)->dam_flags & (l)) \ - cv_wait(&(m)->dam_cv, &(m)->dam_lock); \ - (m)->dam_flags |= (l); \ - mutex_exit(&(m)->dam_lock); \ -} -#define DAM_UNLOCK(m, l) { \ - mutex_enter(&(m)->dam_lock); \ - (m)->dam_flags &= ~(l); \ - cv_signal(&(m)->dam_cv); \ - mutex_exit(&(m)->dam_lock); \ -} -#define DAM_ASSERT_LOCKED(m, l) ASSERT((m)->dam_flags & (l)) - #define DAM_SPEND 0x10 /* stable pending */ #define DAM_DESTROYPEND 0x20 /* in process of being destroyed */ #define DAM_SETADD 0x100 /* fullset update pending */ -#define DAM_FLAG_SET(m, f) { \ - mutex_enter(&(m)->dam_lock); \ - (m)->dam_flags |= f; \ - mutex_exit(&(m)->dam_lock); \ -} -#define DAM_FLAG_CLR(m, f) { \ - mutex_enter(&(m)->dam_lock); \ - (m)->dam_flags &= ~f; \ - mutex_exit(&(m)->dam_lock); \ -} /* * per address softstate stucture */ typedef struct { uint_t da_flags; /* flags */ - int da_jitter; /* address report count */ + int da_jitter; /* address re-report count */ int da_ref; /* refcount on address */ void *da_ppriv; /* stable provider private */ void *da_cfg_priv; /* config/unconfig private */ @@ -151,7 +121,7 @@ * dam_da_t.da_flags */ #define DA_INIT 0x1 /* address initizized */ -#define DA_ACTIVE 0x2 /* address stable */ +#define DA_FAILED_CONFIG 0x2 /* address failed configure */ #define DA_RELE 0x4 /* adddress released */ @@ -168,10 +138,10 @@ * DAM statistics */ struct dam_kstats { - struct kstat_named dam_stable; - struct kstat_named dam_stable_blocked; - struct kstat_named dam_rereport; - struct kstat_named dam_numstable; + struct kstat_named dam_cycles; + struct kstat_named dam_overrun; + struct kstat_named dam_jitter; + struct kstat_named dam_active; }; #ifdef __cplusplus
--- a/usr/src/uts/common/sys/ddi_impldefs.h Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/sys/ddi_impldefs.h Mon Nov 16 09:55:18 2009 -0800 @@ -778,6 +778,8 @@ * This data structure is private to the ddi_strid_* implementation */ typedef struct i_ddi_strid { + size_t strid_chunksz; + size_t strid_spacesz; id_space_t *strid_space; mod_hash_t *strid_byid; mod_hash_t *strid_bystr;
--- a/usr/src/uts/common/sys/scsi/impl/transport.h Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/sys/scsi/impl/transport.h Mon Nov 16 09:55:18 2009 -0800 @@ -578,7 +578,6 @@ int scsi_hba_iportmap_create( dev_info_t *hba_dip, clock_t stable_ms, - int n_entries, scsi_hba_iportmap_t **iportmapp); int scsi_hba_iportmap_iport_add( @@ -614,7 +613,6 @@ dev_info_t *iport_dip, scsi_tgtmap_mode_t rpt_mode, clock_t stable_ms, - int n_entries, void *tgtmap_priv, scsi_tgt_activate_cb_t activate_cb, scsi_tgt_deactivate_cb_t deactivate_cb,
--- a/usr/src/uts/common/sys/sunddi.h Mon Nov 16 05:29:23 2009 -0800 +++ b/usr/src/uts/common/sys/sunddi.h Mon Nov 16 09:55:18 2009 -0800 @@ -1623,8 +1623,6 @@ id_t ddi_strid_alloc(ddi_strid *strid, char *str); id_t -ddi_strid_fixed_alloc(ddi_strid *strid, char *str); -id_t ddi_strid_str2id(ddi_strid *strid, char *str); char * ddi_strid_id2str(ddi_strid *strid, id_t id);