/* * Encodes (packs) DFS information in 'info' into a flat * buffer in a name-value format. This function allocates a * buffer with appropriate size to contain all the information * so the caller MUST free the allocated memory by calling free(). */ static uint32_t dfs_root_encode(dfs_info_t *info, char **buf, size_t *bufsz) { dfs_target_t *t; nvlist_t *nvl; int rc; if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) return (ERROR_NOT_ENOUGH_MEMORY); rc = nvlist_add_string(nvl, "comment", info->i_comment); rc |= nvlist_add_string(nvl, "guid", info->i_guid); rc |= nvlist_add_uint32(nvl, "state", info->i_state); rc |= nvlist_add_uint32(nvl, "timeout", info->i_timeout); rc |= nvlist_add_uint32(nvl, "propflags", info->i_propflags); t = info->i_targets; rc |= nvlist_add_string(nvl, "t_server", t->t_server); rc |= nvlist_add_string(nvl, "t_share", t->t_share); rc |= nvlist_add_uint32(nvl, "t_state", t->t_state); rc |= nvlist_add_uint32(nvl, "t_priority_class", t->t_priority.p_class); rc |= nvlist_add_uint16(nvl, "t_priority_rank", t->t_priority.p_rank); if (rc == 0) rc = nvlist_pack(nvl, buf, bufsz, NV_ENCODE_NATIVE, 0); nvlist_free(nvl); return ((rc == 0) ? ERROR_SUCCESS : ERROR_INTERNAL_ERROR); }
static int logpage_selftest_analyze(ds_scsi_info_t *sip, scsi_log_parameter_header_t *lphp, int log_length) { int i, plen = 0; int entries = 0; ushort_t param_code; scsi_selftest_log_param_t *stp; nvlist_t *nvl; assert(sip->si_dsp->ds_testfail == NULL); if (nvlist_alloc(&sip->si_dsp->ds_testfail, NV_UNIQUE_NAME, 0) != 0) return (scsi_set_errno(sip, EDS_NOMEM)); nvl = sip->si_dsp->ds_testfail; for (i = 0; i < log_length; i += plen, entries++) { lphp = (scsi_log_parameter_header_t *)((char *)lphp + plen); param_code = BE_16(lphp->lph_param); stp = (scsi_selftest_log_param_t *)lphp; if (param_code >= LOGPAGE_SELFTEST_MIN_PARAM_CODE && param_code <= LOGPAGE_SELFTEST_MAX_PARAM_CODE && lphp->lph_length >= LOGPAGE_SELFTEST_PARAM_LEN) { /* * We always log the last result, or the result of the * last completed test. */ if ((param_code == 1 || SELFTEST_COMPLETE(stp->st_results))) { if (nvlist_add_uint8(nvl, FM_EREPORT_PAYLOAD_SCSI_RESULTCODE, stp->st_results) != 0 || nvlist_add_uint16(nvl, FM_EREPORT_PAYLOAD_SCSI_TIMESTAMP, BE_16(stp->st_timestamp)) != 0 || nvlist_add_uint8(nvl, FM_EREPORT_PAYLOAD_SCSI_SEGMENT, stp->st_number) != 0 || nvlist_add_uint64(nvl, FM_EREPORT_PAYLOAD_SCSI_ADDRESS, BE_64(stp->st_lba)) != 0) return (scsi_set_errno(sip, EDS_NOMEM)); if (SELFTEST_COMPLETE(stp->st_results)) { if (stp->st_results != SELFTEST_OK) sip->si_dsp->ds_faults |= DS_FAULT_TESTFAIL; return (0); } } } plen = lphp->lph_length + sizeof (scsi_log_parameter_header_t); } return (0); }
static int be_nvl_add_uint16(nvlist_t *nvl, const char *name, uint16_t val) { assert(nvl != NULL); if (nvlist_add_uint16(nvl, name, val) != 0) { (void) fprintf(stderr, _("nvlist_add_uint16 failed for " "%s (%hu).\n"), name, val); return (1); } return (0); }
/* * Verify a single logpage. This will do some generic validation and then call * the logpage-specific function for further verification. */ static int verify_logpage(ds_scsi_info_t *sip, logpage_validation_entry_t *lp) { scsi_log_header_t *lhp; struct scsi_extended_sense sense; int buflen; int log_length; int result = 0; uint_t kp, asc, ascq; nvlist_t *nvl; buflen = MAX_BUFLEN(scsi_log_header_t); if ((lhp = calloc(buflen, 1)) == NULL) return (scsi_set_errno(sip, EDS_NOMEM)); bzero(&sense, sizeof (struct scsi_extended_sense)); nvl = NULL; if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || nvlist_add_nvlist(sip->si_state_logpage, lp->ve_desc, nvl) != 0) { nvlist_free(nvl); free(lhp); return (scsi_set_errno(sip, EDS_NOMEM)); } nvlist_free(nvl); result = nvlist_lookup_nvlist(sip->si_state_logpage, lp->ve_desc, &nvl); assert(result == 0); result = scsi_log_sense(sip, lp->ve_code, PC_CUMULATIVE, (caddr_t)lhp, buflen, &kp, &asc, &ascq); if (result == 0) { log_length = BE_16(lhp->lh_length); if (nvlist_add_uint16(nvl, "length", log_length) != 0) { free(lhp); return (scsi_set_errno(sip, EDS_NOMEM)); } if (lp->ve_validate(sip, (scsi_log_parameter_header_t *) (((char *)lhp) + sizeof (scsi_log_header_t)), log_length, nvl) != 0) { free(lhp); return (-1); } } else { printf("failed to load %s log page (KEY=0x%x " "ASC=0x%x ASCQ=0x%x)\n", lp->ve_desc, kp, asc, ascq); } free(lhp); return (0); }
/* * Set the named uint16 in the given nvlist_t. * * @param attrs * the nvlist_t to search * * @param which * the string key for this element in the list * * @param val * the value to set * * @return 0 * if successful * * @return EINVAL * if there is an invalid argument * * @return ENOMEM * if there is insufficient memory */ int set_uint16( nvlist_t *attrs, char *which, uint16_t val) { int error = 0; if ((error = nvlist_add_uint16(attrs, which, val)) != 0) { volume_set_error( gettext("nvlist_add_int16(%s) failed: %d\n"), which, error); } return (error); }
/* * Verify the contents of the self test log page. The log supports a maximum of * 20 entries, where each entry's parameter code is its index in the log. We * check that the parameter codes fall within this range, and that the size of * each page is what we expect. It's perfectly acceptable for there to be no * entries in this log, so we must also be sure to validate the contents as part * of the analysis phase. */ static int logpage_selftest_verify(ds_scsi_info_t *sip, scsi_log_parameter_header_t *lphp, int log_length, nvlist_t *nvl) { int i, plen = 0; boolean_t bad = B_FALSE; int entries = 0; ushort_t param_code; for (i = 0; i < log_length; i += plen, entries++) { lphp = (scsi_log_parameter_header_t *)((char *)lphp + plen); param_code = BE_16(lphp->lph_param); if (param_code < LOGPAGE_SELFTEST_MIN_PARAM_CODE || param_code > LOGPAGE_SELFTEST_MAX_PARAM_CODE) { if (nvlist_add_uint16(nvl, "invalid-param-code", param_code) != 0) return (scsi_set_errno(sip, EDS_NOMEM)); bad = B_TRUE; break; } if (lphp->lph_length != LOGPAGE_SELFTEST_PARAM_LEN) { if (nvlist_add_uint8(nvl, "invalid-length", lphp->lph_length) != 0) return (scsi_set_errno(sip, EDS_NOMEM)); bad = B_TRUE; break; } plen = lphp->lph_length + sizeof (scsi_log_parameter_header_t); } if (bad) { sip->si_supp_log &= ~LOGPAGE_SUPP_SELFTEST; printf("selftest logpage validation failed\n"); } return (0); }
void fnvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val) { VERIFY0(nvlist_add_uint16(nvl, name, val)); }