/** * Create a led objects * @param par pointer to an object, it will be the parent of the new led * @param copy pointer to a led object, if not NULL then the new object will be copied from it * @return pointer to the created led */ lv_obj_t * lv_led_create(lv_obj_t * par, lv_obj_t * copy) { /*Create the ancestor basic object*/ lv_obj_t * new_led = lv_obj_create(par, copy); dm_assert(new_led); /*Allocate the object type specific extended data*/ lv_led_ext_t * ext = lv_obj_alloc_ext(new_led, sizeof(lv_led_ext_t)); dm_assert(ext); ext->bright = LV_LED_BRIGHT_ON; if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_f(new_led); lv_obj_set_signal_f(new_led, lv_led_signal); lv_obj_set_design_f(new_led, lv_led_design); /*Init the new led object*/ if(copy == NULL) { lv_obj_set_style(new_led, lv_style_get(LV_STYLE_PRETTY_COLOR, NULL)); lv_obj_set_size(new_led, LV_LED_WIDTH_DEF, LV_LED_HEIGHT_DEF); } /*Copy an existing object*/ else { lv_led_ext_t * copy_ext = lv_obj_get_ext(copy); ext->bright = copy_ext->bright; /*Refresh the style with new signal function*/ lv_obj_refr_style(new_led); } return new_led; }
static dm_plugin_t * protocol_to_dm_plugin(const char *protocol) { dm_plugin_t *plugin; /* * Traversing the plugin list must be atomic with * respect to plugin loads */ dm_assert(pthread_mutex_lock(&plugin_list_mutex) == 0); plugin = plugin_list; while (plugin != NULL) { if (strcmp(plugin->protocol, protocol) == 0) { break; } plugin = plugin->next; } /* Wasn't found -- load, initialize, and return it */ plugin = (plugin == NULL) ? load_and_init_dm_plugin(protocol) : plugin; dm_assert(pthread_mutex_unlock(&plugin_list_mutex) == 0); return (plugin); }
/** * Create a template objects * @param par pointer to an object, it will be the parent of the new template * @param copy pointer to a template object, if not NULL then the new object will be copied from it * @return pointer to the created template */ lv_obj_t * lv_templ_create(lv_obj_t * par, lv_obj_t * copy) { /*Create the ancestor of template*/ /*TODO modify it to the ancestor create function */ lv_obj_t * new_templ = lv_ANCESTOR_create(par, copy); dm_assert(new_templ); /*Allocate the template type specific extended data*/ lv_templ_ext_t * ext = lv_obj_alloc_ext(new_templ, sizeof(lv_templ_ext_t)); dm_assert(ext); /*Initialize the allocated 'ext' */ ext->xyz = 0; /*The signal and design functions are not copied so set them here*/ lv_obj_set_signal_f(new_templ, lv_templ_signal); lv_obj_set_design_f(new_templ, lv_templ_design); /*Init the new template template*/ if(copy == NULL) { lv_obj_set_style(new_templ, lv_style_get(LV_STYLE_PRETTY, NULL)); } /*Copy an existing template*/ else { lv_templ_ext_t * copy_ext = lv_obj_get_ext(copy); /*Refresh the style with new signal function*/ lv_obj_refr_style(new_templ); } return new_templ; }
dm_plugin_error_t dm_pm_indicator_execute(const char *action) { dm_plugin_t *dmpip; char *protocol = extract_protocol(action); /* memory allocated here */ char *actionp = extract_action(action); dm_plugin_action_handle_impl_t *hip; dmpip = protocol_to_dm_plugin(protocol); dstrfree(protocol); if (dmpip != NULL) { if ((hip = lookup_handle_by_action(actionp)) == NULL) { if (bind_action_handle(dmpip, actionp, (dm_plugin_action_handle_t *)&hip) != DMPE_SUCCESS) return (DMPE_FAILURE); } dm_assert(dmpip->state == DMPS_INITED); if (dmpip->ops->indicator_execute) return (dmpip->ops->indicator_execute(hip->handle)); } return (DMPE_FAILURE); }
dm_plugin_error_t dm_pm_update_fru(const char *action, dm_fru_t *frup) { char *protocol = extract_protocol(action); /* mem alloced here */ char *actionp = extract_action(action); dm_plugin_t *dmpip; if (protocol == NULL) { log_warn("FRU update: Invalid protocol specified in action " "`%s'\n", action); return (DMPE_FAILURE); } dmpip = protocol_to_dm_plugin(protocol); dstrfree(protocol); if (dmpip != NULL) { dm_assert(dmpip->state == DMPS_INITED); if (dmpip->ops->indicator_fru_update) return (dmpip->ops->indicator_fru_update(actionp, frup)); } return (DMPE_FAILURE); }
static dm_plugin_t * load_dm_plugin(const char *protocol) { dm_plugin_t *dmpip = NULL; boolean_t plugin_loaded = B_FALSE; /* * Validate the protocol string -- if there are any non-alphanumeric * characters, it's not a valid protocol string. */ if (safe_protocol_string(protocol) == B_FALSE) { log_warn("Invalid characters in plugin protocol `%s'.\n", protocol); goto fpi_out; } dmpip = new_dm_plugin(protocol); plugin_loaded = do_load_dm_plugin(dmpip); fpi_out: if (plugin_loaded) { dm_assert(dmpip != NULL); dmpip->state = DMPS_LOADED; } else if (!plugin_loaded && dmpip != NULL) free_dm_plugin(&dmpip); return (dmpip); }
static nvlist_t * find_disk_monitor_private_pgroup(tnode_t *node) { int err; nvlist_t *list_of_lists, *nvlp, *dupnvlp; nvlist_t *disk_monitor_pgrp = NULL; nvpair_t *nvp = NULL; char *pgroup_name; /* * topo_prop_get_all() returns an nvlist that contains other * nvlists (some of which are property groups). Since the private * property group we need will be among the list of property * groups returned (hopefully), we need to walk the list of nvlists * in the topo node's properties to find the property groups, then * check inside each embedded nvlist to see if it's the pgroup we're * looking for. */ if ((list_of_lists = topo_prop_getprops(node, &err)) != NULL) { /* * Go through the list of nvlists, looking for the * property group we need. */ while ((nvp = nvlist_next_nvpair(list_of_lists, nvp)) != NULL) { if (nvpair_type(nvp) != DATA_TYPE_NVLIST || strcmp(nvpair_name(nvp), TOPO_PROP_GROUP) != 0 || nvpair_value_nvlist(nvp, &nvlp) != 0) continue; dm_assert(nvlp != NULL); pgroup_name = NULL; if (nonunique_nvlist_lookup_string(nvlp, TOPO_PROP_GROUP_NAME, &pgroup_name) != 0 || strcmp(pgroup_name, DISK_MONITOR_PROPERTIES) != 0) continue; else { /* * Duplicate the nvlist so that when the * master nvlist is freed (below), we will * still refer to allocated memory. */ if (nvlist_dup(nvlp, &dupnvlp, 0) == 0) disk_monitor_pgrp = dupnvlp; else disk_monitor_pgrp = NULL; break; } } nvlist_free(list_of_lists); } return (disk_monitor_pgrp); }
static dm_plugin_action_handle_impl_t * lookup_handle_by_action(const char *action) { dm_plugin_action_handle_impl_t *handle; dm_assert(pthread_mutex_lock(&handle_list_mutex) == 0); handle = handle_list; while (handle != NULL) { if (strcmp(handle->actionString, action) == 0) break; handle = handle->next; } dm_assert(pthread_mutex_unlock(&handle_list_mutex) == 0); return (handle); }
static dm_plugin_action_handle_impl_t * new_action_handle(const char *action, dm_plugin_t *pluginp) { dm_plugin_action_handle_impl_t *hip; hip = (dm_plugin_action_handle_impl_t *)dmalloc( sizeof (dm_plugin_action_handle_impl_t)); hip->actionString = dstrdup(action); hip->plugin = pluginp; hip->handle = (dm_plugin_action_handle_t)NULL; /* Add the handle to the global list */ dm_assert(pthread_mutex_lock(&handle_list_mutex) == 0); hip->next = handle_list; handle_list = hip; dm_assert(pthread_mutex_unlock(&handle_list_mutex) == 0); return (hip); }
static dm_plugin_error_t bind_action_handle(dm_plugin_t *dmpip, const char *action, dm_plugin_action_handle_t *hdlp) { dm_plugin_action_handle_impl_t *hip; hip = new_action_handle(action, dmpip); *hdlp = hip; dm_assert(dmpip->state == DMPS_INITED); if (dmpip->ops->indicator_bind_handle) return (dmpip->ops->indicator_bind_handle(action, &hip->handle)); return (DMPE_FAILURE); }
static int topo_add_bay(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp) { diskmon_t *target_diskp = wdp->target; nvlist_t *nvlp = find_disk_monitor_private_pgroup(node); nvlist_t *prop_nvlp; nvpair_t *nvp = NULL; char *prop_name, *prop_value; #define PNAME_MAX 128 char pname[PNAME_MAX]; char msgbuf[MAX_CONF_MSG_LEN]; char *indicator_name, *indicator_action; char *indrule_states, *indrule_actions; int err = 0, i; conf_err_t conferr; boolean_t conf_failure = B_FALSE; char *unadj_physid = NULL; char physid[MAXPATHLEN]; char *label; nvlist_t *diskprops = NULL; char *cstr = NULL; indicator_t *indp = NULL; indrule_t *indrp = NULL; void *p; diskmon_t *diskp; void *ptr; /* No private properties -- just ignore the port */ if (nvlp == NULL) return (0); /* * Look for a diskmon based on this node's FMRI string. * Once a diskmon has been created, it's not re-created. This is * essential for the times when the tree-walk is called after a * disk is inserted (or removed) -- in that case, the disk node * handler simply updates the FRU information in the diskmon. */ if ((p = fmri2ptr(thp, node, &cstr, &err)) != NULL) { diskp = (diskmon_t *)p; /* * Delete the FRU information from the diskmon. If a disk * is connected, its FRU information will be refreshed by * the disk node code. */ if (diskp->frup && (target_diskp == NULL || diskp == target_diskp)) { dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dmfru_free(diskp->frup); diskp->frup = NULL; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); } wdp->pfmri = cstr; nvlist_free(nvlp); return (0); } /* * Determine the physical path to the attachment point */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_AP_PATH, &unadj_physid, &err) == 0) { adjust_dynamic_ap(unadj_physid, physid); topo_hdl_strfree(thp, unadj_physid); } else { /* unadj_physid cannot have been allocated */ if (cstr) dstrfree(cstr); nvlist_free(nvlp); return (-1); } /* */ /* * Process the properties. If we encounter a property that * is not an indicator name, action, or rule, add it to the * disk's props list. */ /* Process indicators */ i = 0; indicator_name = NULL; indicator_action = NULL; do { if (indicator_name != NULL && indicator_action != NULL) { if (topoprop_indicator_add(&indp, indicator_name, indicator_action) != 0) { conf_failure = B_TRUE; } topo_hdl_strfree(thp, indicator_name); topo_hdl_strfree(thp, indicator_action); } (void) snprintf(pname, PNAME_MAX, BAY_IND_NAME "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indicator_name, &err) != 0) break; (void) snprintf(pname, PNAME_MAX, BAY_IND_ACTION "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indicator_action, &err) != 0) break; i++; } while (!conf_failure && indicator_name != NULL && indicator_action != NULL); if (!conf_failure && indp != NULL && (conferr = check_inds(indp)) != E_NO_ERROR) { conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, NULL); log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf); conf_failure = B_TRUE; } /* Process state rules and indicator actions */ i = 0; indrule_states = NULL; indrule_actions = NULL; do { if (indrule_states != NULL && indrule_actions != NULL) { if (topoprop_indrule_add(&indrp, indrule_states, indrule_actions) != 0) { conf_failure = B_TRUE; } topo_hdl_strfree(thp, indrule_states); topo_hdl_strfree(thp, indrule_actions); } (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_STATES "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indrule_states, &err) != 0) break; (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_ACTIONS "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indrule_actions, &err) != 0) break; i++; } while (!conf_failure && indrule_states != NULL && indrule_actions != NULL); if (!conf_failure && indrp != NULL && indp != NULL && ((conferr = check_indrules(indrp, (state_transition_t **)&ptr)) != E_NO_ERROR || (conferr = check_consistent_ind_indrules(indp, indrp, (ind_action_t **)&ptr)) != E_NO_ERROR)) { conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, ptr); log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf); conf_failure = B_TRUE; } /* * Now collect miscellaneous properties. * Each property is stored as an embedded nvlist named * TOPO_PROP_VAL. The property name is stored in the value for * key=TOPO_PROP_VAL_NAME and the property's value is * stored in the value for key=TOPO_PROP_VAL_VAL. This is all * necessary so we can subtractively decode the properties that * we do not directly handle (so that these properties are added to * the per-disk properties nvlist), increasing flexibility. */ (void) nvlist_alloc(&diskprops, NV_UNIQUE_NAME, 0); while ((nvp = nvlist_next_nvpair(nvlp, nvp)) != NULL) { /* Only care about embedded nvlists named TOPO_PROP_VAL */ if (nvpair_type(nvp) != DATA_TYPE_NVLIST || strcmp(nvpair_name(nvp), TOPO_PROP_VAL) != 0 || nvpair_value_nvlist(nvp, &prop_nvlp) != 0) continue; if (nonunique_nvlist_lookup_string(prop_nvlp, TOPO_PROP_VAL_NAME, &prop_name) != 0) continue; /* Filter out indicator properties */ if (strstr(prop_name, BAY_IND_NAME) != NULL || strstr(prop_name, BAY_IND_ACTION) != NULL || strstr(prop_name, BAY_INDRULE_STATES) != NULL || strstr(prop_name, BAY_INDRULE_ACTIONS) != NULL) continue; if (nonunique_nvlist_lookup_string(prop_nvlp, TOPO_PROP_VAL_VAL, &prop_value) != 0) continue; /* Add the property to the disk's prop list: */ if (nvlist_add_string(diskprops, prop_name, prop_value) != 0) log_msg(MM_TOPO, "Could not add disk property `%s' with " "value `%s'\n", prop_name, prop_value); } nvlist_free(nvlp); if (cstr != NULL) { namevalpr_t nvpr; nvlist_t *dmap_nvl; nvpr.name = DISK_AP_PROP_APID; nvpr.value = strncmp(physid, "/devices", 8) == 0 ? (physid + 8) : physid; /* * Set the diskmon's location to the value in this port's label. * If there's a disk plugged in, the location will be updated * to be the disk label (e.g. HD_ID_00). Until a disk is * inserted, though, there won't be a disk libtopo node * created. */ /* Pass physid without the leading "/devices": */ dmap_nvl = namevalpr_to_nvlist(&nvpr); diskp = new_diskmon(dmap_nvl, indp, indrp, diskprops); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); if (!conf_failure && diskp != NULL) { /* Add this diskmon to the disk list */ cfgdata_add_diskmon(config_data, diskp); if (nvlist_add_uint64(g_topo2diskmon, cstr, (uint64_t)(uintptr_t)diskp) != 0) { log_msg(MM_TOPO, "Could not add pointer to nvlist " "for `%s'!\n", cstr); } } else if (diskp != NULL) { diskmon_free(diskp); } else { if (dmap_nvl) nvlist_free(dmap_nvl); if (indp) ind_free(indp); if (indrp) indrule_free(indrp); if (diskprops) nvlist_free(diskprops); } wdp->pfmri = cstr; } return (0); }
static int topoprop_indrule_add(indrule_t **indrp, char *sts, char *acts) { ind_action_t *indactp = NULL; ind_state_t state; char *name, *lasts, *p; int stateslen = strlen(sts) + 1; int actionslen = strlen(acts) + 1; char *states = dstrdup(sts); char *actions = dstrdup(acts); state_transition_t strans; boolean_t failed = B_FALSE; conf_err_t err; char msgbuf[MAX_CONF_MSG_LEN]; /* The state string is of the form "{STATE}>{STATE}" */ p = strchr(states, '>'); dm_assert(p != NULL); *p = 0; strans.begin = str2dmstate(states); *p = '>'; strans.end = str2dmstate(p + 1); if (strans.begin == HPS_UNKNOWN || strans.end == HPS_UNKNOWN) { log_msg(MM_CONF, "Invalid states property `%s'\n", sts); failed = B_TRUE; } else if ((err = check_state_transition(strans.begin, strans.end)) != E_NO_ERROR) { conf_error_msg(err, msgbuf, MAX_CONF_MSG_LEN, &strans); log_msg(MM_CONF, "%s: Not adding disk to list!\n", msgbuf); failed = B_TRUE; } /* Actions are of the form "{ACTION}[&{ACTION}]" */ if (!failed && (p = strtok_r(actions, "&", &lasts)) != NULL) { /* At least 2 tokens */ do { if (indicator_breakup(p, &state, &name) != 0) { failed = B_TRUE; break; } link_indaction(&indactp, new_indaction(state, name)); } while ((p = strtok_r(NULL, "&", &lasts)) != NULL); } else if (!failed) { /* One token */ if (indicator_breakup(actions, &state, &name) != 0) return (-1); indactp = new_indaction(state, name); } dfree(states, stateslen); dfree(actions, actionslen); if (!failed && (err = check_indactions(indactp)) != E_NO_ERROR) { conf_error_msg(err, msgbuf, MAX_CONF_MSG_LEN, NULL); log_msg(MM_CONF, "%s: Not adding disk to list!\n", msgbuf); failed = B_TRUE; } if (failed) { indaction_free(indactp); return (-1); } else link_indrule(indrp, new_indrule(&strans, indactp)); return (0); }
static int topo_add_disk(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp) { diskmon_t *target_diskp = wdp->target; char *devpath = NULL; char *capacity = NULL; char *firmrev = NULL; char *serial = NULL; char *manuf = NULL; char *model = NULL; char *label; uint64_t ptr = 0; int err; dm_fru_t *frup; diskmon_t *diskp; if (wdp->pfmri == NULL) { log_msg(MM_TOPO, "No diskmon for parent of node %p.\n", node); return (0); } if (nvlist_lookup_uint64(g_topo2diskmon, wdp->pfmri, &ptr) != 0) { log_msg(MM_TOPO, "No diskmon for %s: parent of node %p.\n", wdp->pfmri, node); dstrfree(wdp->pfmri); /* Skip this disk: */ return (0); } dstrfree(wdp->pfmri); wdp->pfmri = NULL; diskp = (diskmon_t *)(uintptr_t)ptr; /* If we were called upon to update a particular disk, do it */ if (target_diskp != NULL && diskp != target_diskp) { return (0); } /* * Update the diskmon's location field with the disk's label */ if (diskp->location) dstrfree(diskp->location); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); /* * Check for a device path property (if the disk is configured, * it will be present) and add it to the diskmon's properties) */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH, &devpath, &err) == 0) { char devp[PATH_MAX]; /* * Consumers of the DISK_PROP_DEVPATH property expect a raw * minor device node */ (void) snprintf(devp, PATH_MAX, "%s:q,raw", devpath); (void) nvlist_add_string(diskp->props, DISK_PROP_DEVPATH, devp); topo_hdl_strfree(thp, devpath); } /* * Add the logical disk node, if it exists */ if (topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_LOGICAL_DISK_NAME, &devpath, &err) == 0) { (void) nvlist_add_string(diskp->props, DISK_PROP_LOGNAME, devpath); topo_hdl_strfree(thp, devpath); } /* * Add the FRU information (if present in the node) to the diskmon's * fru data structure: */ (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MODEL, &model, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MANUFACTURER, &manuf, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_SERIAL_NUM, &serial, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_FIRMWARE_REV, &firmrev, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_CAPACITY, &capacity, &err); frup = new_dmfru(manuf, model, firmrev, serial, capacity == NULL ? 0 : strtoull(capacity, 0, 0)); if (model) topo_hdl_strfree(thp, model); if (manuf) topo_hdl_strfree(thp, manuf); if (serial) topo_hdl_strfree(thp, serial); if (firmrev) topo_hdl_strfree(thp, firmrev); if (capacity) topo_hdl_strfree(thp, capacity); /* Add the fru information to the diskmon: */ dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dm_assert(diskp->frup == NULL); diskp->frup = frup; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); return (0); }
static int topo_add_disk(topo_hdl_t *thp, tnode_t *node, diskmon_t *target_diskp) { nvlist_t *fmri = NULL; nvlist_t *asru_fmri; nvlist_t *fru_fmri; char *devpath = NULL; char *capacity = NULL; char *firmrev = NULL; char *serial = NULL; char *manuf = NULL; char *model = NULL; char *cstr = NULL; char *buf; char *label; char *p; uint64_t ptr = 0; int buflen; int err; int orig_cstr_len; dm_fru_t *frup; diskmon_t *diskp; /* * Match this node to a disk in the configuration by looking at * our parent's fmri (and do that by getting our FMRI and chopping * off the last part). */ if (topo_node_resource(node, &fmri, &err) != 0) { log_msg(MM_TOPO, "topo_add_disk: Could not generate FMRI for " "node %p!\n", (void *)node); return (-1); } if (topo_fmri_nvl2str(thp, fmri, &cstr, &err) != 0) { log_msg(MM_TOPO, "topo_add_disk: Could not create string for " "node %p's FMRI!\n", (void *)node); nvlist_free(fmri); return (-1); } nvlist_free(fmri); /* * Chop off all but last path (since there's no way to get * the node's parent in the libtopo API). */ orig_cstr_len = strlen(cstr) + 1; p = strrchr(cstr, '/'); dm_assert(p != NULL); *p = 0; if (nvlist_lookup_uint64(g_topo2diskmon, cstr, &ptr) != 0) { log_msg(MM_TOPO, "No diskmon for parent of node %p.\n", node); topo_hdl_free(thp, cstr, orig_cstr_len); /* Skip this disk: */ return (0); } topo_hdl_free(thp, cstr, orig_cstr_len); diskp = (diskmon_t *)(uintptr_t)ptr; /* If we were called upon to update a particular disk, do it */ if (target_diskp != NULL && diskp != target_diskp) { return (0); } /* * Update the diskmon's ASRU and FRU with our information (this * information is cached in the diskmon so we don't have to do a * time-consuming topo traversal when we get an ereport). */ if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU, &asru_fmri, &err) == 0) { diskmon_add_asru(diskp, asru_fmri); nvlist_free(asru_fmri); } if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU, &fru_fmri, &err) == 0) { diskmon_add_fru(diskp, fru_fmri); nvlist_free(fru_fmri); } if (topo_node_resource(node, &fmri, &err) == 0) { diskmon_add_disk_fmri(diskp, fmri); nvlist_free(fmri); } /* * Update the diskmon's location field with the disk's label */ if (diskp->location) dstrfree(diskp->location); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); /* * Check for a device path property (if the disk is configured, * it will be present) and add it to the diskmon's properties) */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH, &devpath, &err) == 0) { char devp[PATH_MAX]; /* * Consumers of the DISK_PROP_DEVPATH property expect a raw * minor device node */ (void) snprintf(devp, PATH_MAX, "%s:q,raw", devpath); (void) nvlist_add_string(diskp->props, DISK_PROP_DEVPATH, devp); topo_hdl_strfree(thp, devpath); } /* * Add the logical disk node, if it exists */ if (topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_LOGICAL_DISK_NAME, &devpath, &err) == 0) { (void) nvlist_add_string(diskp->props, DISK_PROP_LOGNAME, devpath); topo_hdl_strfree(thp, devpath); } /* * Add the FRU information (if present in the node) to the diskmon's * fru data structure: */ (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MODEL, &model, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MANUFACTURER, &manuf, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_SERIAL_NUM, &serial, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_FIRMWARE_REV, &firmrev, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_CAPACITY, &capacity, &err); frup = new_dmfru(manuf, model, firmrev, serial, capacity == NULL ? 0 : strtoull(capacity, 0, 0)); /* * Update the disk's resource FMRI with the * SunService-required members: * FM_FMRI_HC_SERIAL_ID, FM_FMRI_HC_PART, and * FM_FMRI_HC_REVISION */ (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_SERIAL_ID, serial); transform_model_string(manuf, model, &buf, &buflen); (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_PART, buf); /* * Add the serial number to the ASRU so that when the resource * is marked faulty in the fmd resource cache, the hc scheme * plugin can detect when the disk is no longer installed (and so, * can clear the faulty state automatically across fmd restarts). * * The serial number is only updated when a disk comes online * because that's when the disk node exists in the topo tree. * It's ok to keep a stale value in the ASRU when the disk is removed * because it's only used as part of fault creation when the disk * is configured (online), at which point it will be updated with * the (current) serial number of the disk inserted. */ (void) nvlist_add_string(diskp->asru_fmri, FM_FMRI_HC_SERIAL_ID, serial); dfree(buf, buflen); (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_REVISION, firmrev); if (model) { topo_hdl_strfree(thp, model); } if (manuf) { topo_hdl_strfree(thp, manuf); } if (serial) { topo_hdl_strfree(thp, serial); } if (firmrev) { topo_hdl_strfree(thp, firmrev); } if (capacity) { topo_hdl_strfree(thp, capacity); } /* Add the fru information to the diskmon: */ dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dm_assert(diskp->frup == NULL); diskp->frup = frup; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); return (0); }
static void XMLCALL startElement(void *userData, const char *name, const char **atts) { const struct dm_element *kw = NULL; DM_VALUE *val = NULL; struct XMLstate **state = userData; const char *base = (*state)->base; int valid = ((*state)->flags & XML_VALID) == XML_VALID; int is_root = ((*state)->flags & XML_ROOT) == XML_ROOT; const struct dm_element *element = (*state)->element; DM_VALUE *value = (*state)->value; int xid = 0; int ntfy = 0; dm_id id; for (int i = 0; atts[i]; i += 2) { if (strcasecmp("instance", atts[i]) == 0) { xml_debug("%s: instance: %s\n", name, atts[i + 1]); xid = atoi(atts[i + 1]); break; } else if (strcasecmp("notify", atts[i]) == 0) { xml_debug("%s: notify: %s\n", name, atts[i + 1]); ntfy = dm_enum2int( ¬ify_attr, atts[i + 1]); } else if (strcasecmp("encoding", atts[i]) == 0) { xml_debug("%s: encoding: %s\n", name, atts[i + 1]); if (strcasecmp(atts[i+1], "escaped") == 0) (*state)->flags |= XML_ESCAPED; } else if (strcasecmp("version", atts[i]) == 0) { xml_debug("%s: config version: %s\n", name, atts[i + 1]); dm_set_cfg_version(atoi(atts[i + 1])); } } (*state)++; if (is_root) { if (flags & DS_VERSIONCHECK && dm_get_cfg_version() != CFG_VERSION) { (*state)->flags |= XML_UPGRADE; lua_pushinteger(lua_environment, CFG_VERSION); lua_pushinteger(lua_environment, dm_get_cfg_version()); if (fp_Lua_function("fncPreVersionCheck", 2)) debug("(): Error during Lua function execution"); } } else { memset(*state, 0, sizeof(struct XMLstate)); if (xid != 0) asprintf(&(*state)->base, "%s.%s.%d", base, name, xid); else asprintf(&(*state)->base, "%s.%s", base, name); if (valid) { const struct dm_table *table = element->u.t.table; id = dm_get_element_id_by_name(name, strlen(name), table); if (id != DM_ERR) { kw = &(table->table[id - 1]); val = dm_get_value_ref_by_id(DM_TABLE(*value), id); (*state)->flags |= XML_VALID; } else { printf("Element '%s' not found in table '%s'\n", name, element->key); valid = 0; } } if (!valid || !((*state)->flags & XML_VALID)) { debug("enter invalid: %s\n", (*state)->base); return; } xml_debug("enter: %s = %p, (%p, %p)\n", name, *state, kw, val); (*state)->element = kw; if (kw->type == T_OBJECT) { struct dm_instance *inst = DM_INSTANCE(*val); struct dm_instance_node *node = NULL; /** FIXME: this should be easier */ if (xid > 0) node = dm_get_instance_node_by_id(inst, xid); if (!node) { dm_selector basesel; dm_selcpy(basesel, DM_TABLE(*value)->id); dm_selcat(basesel, id); node = dm_add_instance(kw, inst, basesel, xid); dm_assert(node); if (flags & DS_USERCONFIG) { val->flags |= DV_UPDATED; DM_parity_update(*val); node->table.flags |= DV_UPDATED; DM_parity_update(node->table); } } val = &node->table; (*state)->inst = inst; (*state)->node = node; } else if (kw->type == T_TOKEN) { if (DM_TABLE(*val) == NULL) { set_DM_TABLE(*val, dm_alloc_table(kw->u.t.table, DM_TABLE(*value)->id, id)); if (flags & DS_USERCONFIG) val->flags |= DV_UPDATED; xml_debug("adding table for token \"%s\" with %d elements: %p\n", name, kw->u.t.table->size, DM_TABLE(*val)); DM_parity_update(*val); } } (*state)->value = val; if (ntfy >= 0) set_notify_single_slot_element(kw, (*state)->value, 0, ntfy); } }