/* * If an asru has a unum string that is an hc path string then return * a new nvl (to be freed by the caller) that is a duplicate of the * original but with an additional member of a reconstituted hc fmri. */ int mem_unum_rewrite(nvlist_t *nvl, nvlist_t **rnvl) { int err; char *unumstr; nvlist_t *unum; struct topo_hdl *thp; if (nvlist_lookup_string(nvl, FM_FMRI_MEM_UNUM, &unumstr) != 0 || !ISHCUNUM(unumstr)) return (0); if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (EINVAL); if (topo_fmri_str2nvl(thp, unumstr, &unum, &err) != 0) { fmd_fmri_topo_rele(thp); return (EINVAL); } fmd_fmri_topo_rele(thp); if ((err = nvlist_dup(nvl, rnvl, 0)) != 0) { nvlist_free(unum); return (err); } err = nvlist_add_nvlist(*rnvl, FM_FMRI_MEM_UNUM "-fmri", unum); nvlist_free(unum); if (err != 0) nvlist_free(*rnvl); return (err); }
/* * Convert a shorthand svc FMRI into a full svc FMRI nvlist */ static nvlist_t * shortfmri_to_fmri(fmd_hdl_t *hdl, const char *shortfmristr) { nvlist_t *ret, *fmri; topo_hdl_t *thp; char *fmristr; int err; if ((fmristr = shortfmri_to_fmristr(hdl, shortfmristr)) == NULL) return (NULL); thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION); if (topo_fmri_str2nvl(thp, fmristr, &fmri, &err) != 0) { fmd_hdl_error(hdl, "failed to convert '%s' to nvlist\n", fmristr); fmd_hdl_strfree(hdl, fmristr); fmd_hdl_topo_rele(hdl, thp); return (NULL); } fmd_hdl_strfree(hdl, fmristr); if ((ret = fmd_nvl_dup(hdl, fmri, FMD_SLEEP)) == NULL) { fmd_hdl_error(hdl, "failed to dup fmri\n"); nvlist_free(fmri); fmd_hdl_topo_rele(hdl, thp); return (NULL); } nvlist_free(fmri); fmd_hdl_topo_rele(hdl, thp); return (ret); }
static void set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp) { int ret, err = 0; topo_type_t type; nvlist_t *nvl, *f = NULL; char *end; if (pp->prop == NULL || pp->type == NULL || pp->value == NULL) return; if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) { (void) fprintf(stderr, "%s: invalid property type %s for %s\n", g_pname, pp->type, pp->prop); return; } if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { (void) fprintf(stderr, "%s: nvlist allocation failed for " "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value); return; } ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop); ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type); if (ret != 0) { (void) fprintf(stderr, "%s: invalid property type %s for %s\n", g_pname, pp->type, pp->prop); nvlist_free(nvl); return; } errno = 0; switch (type) { case TOPO_TYPE_INT32: { int32_t val; val = strtol(pp->value, &end, 0); if (errno == ERANGE) { ret = -1; break; } ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val); break; } case TOPO_TYPE_UINT32: { uint32_t val; val = strtoul(pp->value, &end, 0); if (errno == ERANGE) { ret = -1; break; } ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val); break; } case TOPO_TYPE_INT64: { int64_t val; val = strtoll(pp->value, &end, 0); if (errno == ERANGE) { ret = -1; break; } ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val); break; } case TOPO_TYPE_UINT64: { uint64_t val; val = strtoull(pp->value, &end, 0); if (errno == ERANGE) { ret = -1; break; } ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val); break; } case TOPO_TYPE_STRING: { ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, pp->value); break; } case TOPO_TYPE_FMRI: { if ((ret = topo_fmri_str2nvl(thp, pp->value, &f, &err)) < 0) break; if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL, f)) != 0) err = ETOPO_PROP_NVL; break; } default: ret = -1; } if (ret != 0) { (void) fprintf(stderr, "%s: unable to set property value for " "%s: %s\n", g_pname, pp->prop, topo_strerror(err)); nvlist_free(nvl); return; } if (node != NULL) { if (topo_prop_setprop(node, pp->group, nvl, TOPO_PROP_MUTABLE, f, &ret) < 0) { (void) fprintf(stderr, "%s: unable to set property " "value for " "%s=%s:%s: %s\n", g_pname, pp->prop, pp->type, pp->value, topo_strerror(ret)); nvlist_free(nvl); nvlist_free(f); return; } } else { if (topo_fmri_setprop(thp, fmri, pp->group, nvl, TOPO_PROP_MUTABLE, f, &ret) < 0) { (void) fprintf(stderr, "%s: unable to set property " "value for " "%s=%s:%s: %s\n", g_pname, pp->prop, pp->type, pp->value, topo_strerror(ret)); nvlist_free(nvl); nvlist_free(f); return; } } nvlist_free(nvl); /* * Now, get the property back for printing */ if (node != NULL) { if (topo_prop_getprop(node, pp->group, pp->prop, f, &nvl, &err) < 0) { (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n", g_pname, pp->group, pp->prop, topo_strerror(err)); nvlist_free(f); return; } } else { if (topo_fmri_getprop(thp, fmri, pp->group, pp->prop, f, &nvl, &err) < 0) { (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n", g_pname, pp->group, pp->prop, topo_strerror(err)); nvlist_free(f); return; } } print_pgroup(thp, node, pp->group, NULL, NULL, 0); print_prop_nameval(thp, node, nvl); nvlist_free(nvl); nvlist_free(f); }
void print_fmri(topo_hdl_t *thp, char *uuid) { int ret, err; nvlist_t *nvl; char buf[32]; time_t tod = time(NULL); if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) { (void) fprintf(stderr, "%s: failed to convert %s to nvlist: " "%s\n", g_pname, g_fmri, topo_strerror(err)); return; } (void) printf("TIME UUID\n"); (void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod)); (void) printf("%-15s %-32s\n", buf, uuid); (void) printf("\n"); (void) printf("%s\n", (char *)g_fmri); if (opt_p && !(pcnt > 0 || opt_V || opt_all)) { char *aname = NULL, *fname = NULL, *lname = NULL; nvlist_t *asru = NULL; nvlist_t *fru = NULL; if (topo_fmri_asru(thp, nvl, &asru, &err) == 0) (void) topo_fmri_nvl2str(thp, asru, &aname, &err); if (topo_fmri_fru(thp, nvl, &fru, &err) == 0) (void) topo_fmri_nvl2str(thp, fru, &fname, &err); (void) topo_fmri_label(thp, nvl, &lname, &err); nvlist_free(fru); nvlist_free(asru); if (aname != NULL) { (void) printf("\tASRU: %s\n", aname); topo_hdl_strfree(thp, aname); } else { (void) printf("\tASRU: -\n"); } if (fname != NULL) { (void) printf("\tFRU: %s\n", fname); topo_hdl_strfree(thp, fname); } else { (void) printf("\tFRU: -\n"); } if (lname != NULL) { (void) printf("\tLabel: %s\n", lname); topo_hdl_strfree(thp, lname); } else { (void) printf("\tLabel: -\n"); } } if (opt_S) { if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) { (void) printf("\tPresent: -\n"); (void) printf("\tUnusable: -\n"); return; } if ((ret = topo_fmri_present(thp, nvl, &err)) < 0) (void) printf("\tPresent: -\n"); else (void) printf("\tPresent: %s\n", ret ? "true" : "false"); if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0) (void) printf("\tUnusable: -\n"); else (void) printf("\tUnusable: %s\n", ret ? "true" : "false"); nvlist_free(nvl); } if (pargs && pcnt > 0) print_fmri_props(thp, nvl); }
/* * Solve a given ZFS case. This first checks to make sure the diagnosis is * still valid, as well as cleaning up any pending timer associated with the * case. */ static void zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname, boolean_t checkunusable) { libzfs_handle_t *zhdl = fmd_hdl_getspecific(hdl); nvlist_t *detector, *fault; boolean_t serialize; nvlist_t *fmri, *fru; topo_hdl_t *thp; int err; /* * Construct the detector from the case data. The detector is in the * ZFS scheme, and is either the pool or the vdev, depending on whether * this is a vdev or pool fault. */ detector = fmd_nvl_alloc(hdl, FMD_SLEEP); (void) nvlist_add_uint8(detector, FM_VERSION, ZFS_SCHEME_VERSION0); (void) nvlist_add_string(detector, FM_FMRI_SCHEME, FM_FMRI_SCHEME_ZFS); (void) nvlist_add_uint64(detector, FM_FMRI_ZFS_POOL, zcp->zc_data.zc_pool_guid); if (zcp->zc_data.zc_vdev_guid != 0) { (void) nvlist_add_uint64(detector, FM_FMRI_ZFS_VDEV, zcp->zc_data.zc_vdev_guid); } /* * We also want to make sure that the detector (pool or vdev) properly * reflects the diagnosed state, when the fault corresponds to internal * ZFS state (i.e. not checksum or I/O error-induced). Otherwise, a * device which was unavailable early in boot (because the driver/file * wasn't available) and is now healthy will be mis-diagnosed. */ if (!fmd_nvl_fmri_present(hdl, detector) || (checkunusable && !fmd_nvl_fmri_unusable(hdl, detector))) { fmd_case_close(hdl, zcp->zc_case); nvlist_free(detector); return; } fru = NULL; if (zcp->zc_fru != NULL && (thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) != NULL) { /* * If the vdev had an associated FRU, then get the FRU nvlist * from the topo handle and use that in the suspect list. We * explicitly lookup the FRU because the fmri reported from the * kernel may not have up to date details about the disk itself * (serial, part, etc). */ if (topo_fmri_str2nvl(thp, zcp->zc_fru, &fmri, &err) == 0) { /* * If the disk is part of the system chassis, but the * FRU indicates a different chassis ID than our * current system, then ignore the error. This * indicates that the device was part of another * cluster head, and for obvious reasons cannot be * imported on this system. */ if (libzfs_fru_notself(zhdl, zcp->zc_fru)) { fmd_case_close(hdl, zcp->zc_case); nvlist_free(fmri); fmd_hdl_topo_rele(hdl, thp); nvlist_free(detector); return; } /* * If the device is no longer present on the system, or * topo_fmri_fru() fails for other reasons, then fall * back to the fmri specified in the vdev. */ if (topo_fmri_fru(thp, fmri, &fru, &err) != 0) fru = fmd_nvl_dup(hdl, fmri, FMD_SLEEP); nvlist_free(fmri); } fmd_hdl_topo_rele(hdl, thp); } fault = fmd_nvl_create_fault(hdl, faultname, 100, detector, fru, detector); fmd_case_add_suspect(hdl, zcp->zc_case, fault); nvlist_free(fru); fmd_case_solve(hdl, zcp->zc_case); serialize = B_FALSE; if (zcp->zc_data.zc_has_remove_timer) { fmd_timer_remove(hdl, zcp->zc_remove_timer); zcp->zc_data.zc_has_remove_timer = 0; serialize = B_TRUE; } if (serialize) zfs_case_serialize(hdl, zcp); nvlist_free(detector); }