Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*


 500                 dumpvp_write(&ed, sizeof (ed));
 501                 dumpvp_write(buf, len);
 502         }
 503 
 504         sysevent_evc_walk_fini(chq);
 505 }
 506 
 507 /*
 508  * Post an error report (ereport) to the sysevent error channel.  The error
 509  * channel must be established with a prior call to sysevent_evc_create()
 510  * before publication may occur.
 511  */
 512 void
 513 fm_ereport_post(nvlist_t *ereport, int evc_flag)
 514 {
 515         size_t nvl_size = 0;
 516         evchan_t *error_chan;
 517 
 518         (void) nvlist_size(ereport, &nvl_size, NV_ENCODE_NATIVE);
 519         if (nvl_size > ERPT_DATA_SZ || nvl_size == 0) {
 520                 atomic_add_64(&erpt_kstat_data.erpt_dropped.value.ui64, 1);
 521                 return;
 522         }
 523 
 524         if (sysevent_evc_bind(FM_ERROR_CHAN, &error_chan,
 525             EVCH_CREAT|EVCH_HOLD_PEND) != 0) {
 526                 atomic_add_64(&erpt_kstat_data.erpt_dropped.value.ui64, 1);
 527                 return;
 528         }
 529 
 530         if (sysevent_evc_publish(error_chan, EC_FM, ESC_FM_ERROR,
 531             SUNW_VENDOR, FM_PUB, ereport, evc_flag) != 0) {
 532                 atomic_add_64(&erpt_kstat_data.erpt_dropped.value.ui64, 1);
 533                 (void) sysevent_evc_unbind(error_chan);
 534                 return;
 535         }
 536         (void) sysevent_evc_unbind(error_chan);
 537 }
 538 
 539 /*
 540  * Wrapppers for FM nvlist allocators
 541  */
 542 /* ARGSUSED */
 543 static void *
 544 i_fm_alloc(nv_alloc_t *nva, size_t size)
 545 {
 546         return (kmem_zalloc(size, KM_SLEEP));
 547 }
 548 
 549 /* ARGSUSED */
 550 static void
 551 i_fm_free(nv_alloc_t *nva, void *buf, size_t size)
 552 {


 774                 }
 775 
 776                 name = va_arg(ap, char *);
 777         }
 778         return (ret);
 779 }
 780 
 781 void
 782 fm_payload_set(nvlist_t *payload, ...)
 783 {
 784         int ret;
 785         const char *name;
 786         va_list ap;
 787 
 788         va_start(ap, payload);
 789         name = va_arg(ap, char *);
 790         ret = i_fm_payload_set(payload, name, ap);
 791         va_end(ap);
 792 
 793         if (ret)
 794                 atomic_add_64(
 795                     &erpt_kstat_data.payload_set_failed.value.ui64, 1);
 796 }
 797 
 798 /*
 799  * Set-up and validate the members of an ereport event according to:
 800  *
 801  *      Member name             Type            Value
 802  *      ====================================================
 803  *      class                   string          ereport
 804  *      version                 uint8_t         0
 805  *      ena                     uint64_t        <ena>
 806  *      detector                nvlist_t        <detector>
 807  *      ereport-payload         nvlist_t        <var args>
 808  *
 809  * We don't actually add a 'version' member to the payload.  Really,
 810  * the version quoted to us by our caller is that of the category 1
 811  * "ereport" event class (and we require FM_EREPORT_VERS0) but
 812  * the payload version of the actual leaf class event under construction
 813  * may be something else.  Callers should supply a version in the varargs,
 814  * or (better) we could take two version arguments - one for the
 815  * ereport category 1 classification (expect FM_EREPORT_VERS0) and one
 816  * for the leaf class.
 817  */
 818 void
 819 fm_ereport_set(nvlist_t *ereport, int version, const char *erpt_class,
 820     uint64_t ena, const nvlist_t *detector, ...)
 821 {
 822         char ereport_class[FM_MAX_CLASS];
 823         const char *name;
 824         va_list ap;
 825         int ret;
 826 
 827         if (version != FM_EREPORT_VERS0) {
 828                 atomic_add_64(&erpt_kstat_data.erpt_set_failed.value.ui64, 1);
 829                 return;
 830         }
 831 
 832         (void) snprintf(ereport_class, FM_MAX_CLASS, "%s.%s",
 833             FM_EREPORT_CLASS, erpt_class);
 834         if (nvlist_add_string(ereport, FM_CLASS, ereport_class) != 0) {
 835                 atomic_add_64(&erpt_kstat_data.erpt_set_failed.value.ui64, 1);
 836                 return;
 837         }
 838 
 839         if (nvlist_add_uint64(ereport, FM_EREPORT_ENA, ena)) {
 840                 atomic_add_64(&erpt_kstat_data.erpt_set_failed.value.ui64, 1);
 841         }
 842 
 843         if (nvlist_add_nvlist(ereport, FM_EREPORT_DETECTOR,
 844             (nvlist_t *)detector) != 0) {
 845                 atomic_add_64(&erpt_kstat_data.erpt_set_failed.value.ui64, 1);
 846         }
 847 
 848         va_start(ap, detector);
 849         name = va_arg(ap, const char *);
 850         ret = i_fm_payload_set(ereport, name, ap);
 851         va_end(ap);
 852 
 853         if (ret)
 854                 atomic_add_64(&erpt_kstat_data.erpt_set_failed.value.ui64, 1);
 855 }
 856 
 857 /*
 858  * Set-up and validate the members of an hc fmri according to;
 859  *
 860  *      Member name             Type            Value
 861  *      ===================================================
 862  *      version                 uint8_t         0
 863  *      auth                    nvlist_t        <auth>
 864  *      hc-name                 string          <name>
 865  *      hc-id                   string          <id>
 866  *
 867  * Note that auth and hc-id are optional members.
 868  */
 869 
 870 #define HC_MAXPAIRS     20
 871 #define HC_MAXNAMELEN   50
 872 
 873 static int
 874 fm_fmri_hc_set_common(nvlist_t *fmri, int version, const nvlist_t *auth)
 875 {
 876         if (version != FM_HC_SCHEME_VERSION) {
 877                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 878                 return (0);
 879         }
 880 
 881         if (nvlist_add_uint8(fmri, FM_VERSION, version) != 0 ||
 882             nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC) != 0) {
 883                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 884                 return (0);
 885         }
 886 
 887         if (auth != NULL && nvlist_add_nvlist(fmri, FM_FMRI_AUTHORITY,
 888             (nvlist_t *)auth) != 0) {
 889                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 890                 return (0);
 891         }
 892 
 893         return (1);
 894 }
 895 
 896 void
 897 fm_fmri_hc_set(nvlist_t *fmri, int version, const nvlist_t *auth,
 898     nvlist_t *snvl, int npairs, ...)
 899 {
 900         nv_alloc_t *nva = nvlist_lookup_nv_alloc(fmri);
 901         nvlist_t *pairs[HC_MAXPAIRS];
 902         va_list ap;
 903         int i;
 904 
 905         if (!fm_fmri_hc_set_common(fmri, version, auth))
 906                 return;
 907 
 908         npairs = MIN(npairs, HC_MAXPAIRS);
 909 
 910         va_start(ap, npairs);
 911         for (i = 0; i < npairs; i++) {
 912                 const char *name = va_arg(ap, const char *);
 913                 uint32_t id = va_arg(ap, uint32_t);
 914                 char idstr[11];
 915 
 916                 (void) snprintf(idstr, sizeof (idstr), "%u", id);
 917 
 918                 pairs[i] = fm_nvlist_create(nva);
 919                 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
 920                     nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0) {
 921                         atomic_add_64(
 922                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 923                 }
 924         }
 925         va_end(ap);
 926 
 927         if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, pairs, npairs) != 0)
 928                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 929 
 930         for (i = 0; i < npairs; i++)
 931                 fm_nvlist_destroy(pairs[i], FM_NVA_RETAIN);
 932 
 933         if (snvl != NULL) {
 934                 if (nvlist_add_nvlist(fmri, FM_FMRI_HC_SPECIFIC, snvl) != 0) {
 935                         atomic_add_64(
 936                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 937                 }
 938         }
 939 }
 940 
 941 /*
 942  * Set-up and validate the members of an dev fmri according to:
 943  *
 944  *      Member name             Type            Value
 945  *      ====================================================
 946  *      version                 uint8_t         0
 947  *      auth                    nvlist_t        <auth>
 948  *      devpath                 string          <devpath>
 949  *      [devid]                 string          <devid>
 950  *      [target-port-l0id]      string          <target-port-lun0-id>
 951  *
 952  * Note that auth and devid are optional members.
 953  */
 954 void
 955 fm_fmri_dev_set(nvlist_t *fmri_dev, int version, const nvlist_t *auth,
 956     const char *devpath, const char *devid, const char *tpl0)
 957 {
 958         int err = 0;
 959 
 960         if (version != DEV_SCHEME_VERSION0) {
 961                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 962                 return;
 963         }
 964 
 965         err |= nvlist_add_uint8(fmri_dev, FM_VERSION, version);
 966         err |= nvlist_add_string(fmri_dev, FM_FMRI_SCHEME, FM_FMRI_SCHEME_DEV);
 967 
 968         if (auth != NULL) {
 969                 err |= nvlist_add_nvlist(fmri_dev, FM_FMRI_AUTHORITY,
 970                     (nvlist_t *)auth);
 971         }
 972 
 973         err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_PATH, devpath);
 974 
 975         if (devid != NULL)
 976                 err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_ID, devid);
 977 
 978         if (tpl0 != NULL)
 979                 err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_TGTPTLUN0, tpl0);
 980 
 981         if (err)
 982                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
 983 
 984 }
 985 
 986 /*
 987  * Set-up and validate the members of an cpu fmri according to:
 988  *
 989  *      Member name             Type            Value
 990  *      ====================================================
 991  *      version                 uint8_t         0
 992  *      auth                    nvlist_t        <auth>
 993  *      cpuid                   uint32_t        <cpu_id>
 994  *      cpumask                 uint8_t         <cpu_mask>
 995  *      serial                  uint64_t        <serial_id>
 996  *
 997  * Note that auth, cpumask, serial are optional members.
 998  *
 999  */
1000 void
1001 fm_fmri_cpu_set(nvlist_t *fmri_cpu, int version, const nvlist_t *auth,
1002     uint32_t cpu_id, uint8_t *cpu_maskp, const char *serial_idp)
1003 {
1004         uint64_t *failedp = &erpt_kstat_data.fmri_set_failed.value.ui64;
1005 
1006         if (version < CPU_SCHEME_VERSION1) {
1007                 atomic_add_64(failedp, 1);
1008                 return;
1009         }
1010 
1011         if (nvlist_add_uint8(fmri_cpu, FM_VERSION, version) != 0) {
1012                 atomic_add_64(failedp, 1);
1013                 return;
1014         }
1015 
1016         if (nvlist_add_string(fmri_cpu, FM_FMRI_SCHEME,
1017             FM_FMRI_SCHEME_CPU) != 0) {
1018                 atomic_add_64(failedp, 1);
1019                 return;
1020         }
1021 
1022         if (auth != NULL && nvlist_add_nvlist(fmri_cpu, FM_FMRI_AUTHORITY,
1023             (nvlist_t *)auth) != 0)
1024                 atomic_add_64(failedp, 1);
1025 
1026         if (nvlist_add_uint32(fmri_cpu, FM_FMRI_CPU_ID, cpu_id) != 0)
1027                 atomic_add_64(failedp, 1);
1028 
1029         if (cpu_maskp != NULL && nvlist_add_uint8(fmri_cpu, FM_FMRI_CPU_MASK,
1030             *cpu_maskp) != 0)
1031                 atomic_add_64(failedp, 1);
1032 
1033         if (serial_idp == NULL || nvlist_add_string(fmri_cpu,
1034             FM_FMRI_CPU_SERIAL_ID, (char *)serial_idp) != 0)
1035                         atomic_add_64(failedp, 1);
1036 }
1037 
1038 /*
1039  * Set-up and validate the members of a mem according to:
1040  *
1041  *      Member name             Type            Value
1042  *      ====================================================
1043  *      version                 uint8_t         0
1044  *      auth                    nvlist_t        <auth>            [optional]
1045  *      unum                    string          <unum>
1046  *      serial                  string          <serial>  [optional*]
1047  *      offset                  uint64_t        <offset>  [optional]
1048  *
1049  *      * serial is required if offset is present
1050  */
1051 void
1052 fm_fmri_mem_set(nvlist_t *fmri, int version, const nvlist_t *auth,
1053     const char *unum, const char *serial, uint64_t offset)
1054 {
1055         if (version != MEM_SCHEME_VERSION0) {
1056                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1057                 return;
1058         }
1059 
1060         if (!serial && (offset != (uint64_t)-1)) {
1061                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1062                 return;
1063         }
1064 
1065         if (nvlist_add_uint8(fmri, FM_VERSION, version) != 0) {
1066                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1067                 return;
1068         }
1069 
1070         if (nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM) != 0) {
1071                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1072                 return;
1073         }
1074 
1075         if (auth != NULL) {
1076                 if (nvlist_add_nvlist(fmri, FM_FMRI_AUTHORITY,
1077                     (nvlist_t *)auth) != 0) {
1078                         atomic_add_64(
1079                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1080                 }
1081         }
1082 
1083         if (nvlist_add_string(fmri, FM_FMRI_MEM_UNUM, unum) != 0) {
1084                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1085         }
1086 
1087         if (serial != NULL) {
1088                 if (nvlist_add_string_array(fmri, FM_FMRI_MEM_SERIAL_ID,
1089                     (char **)&serial, 1) != 0) {
1090                         atomic_add_64(
1091                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1092                 }
1093                 if (offset != (uint64_t)-1) {
1094                         if (nvlist_add_uint64(fmri, FM_FMRI_MEM_OFFSET,
1095                             offset) != 0) {
1096                                 atomic_add_64(&erpt_kstat_data.
1097                                     fmri_set_failed.value.ui64, 1);
1098                         }




1099                 }
1100         }
1101 }
1102 
1103 void
1104 fm_fmri_zfs_set(nvlist_t *fmri, int version, uint64_t pool_guid,
1105     uint64_t vdev_guid)
1106 {
1107         if (version != ZFS_SCHEME_VERSION0) {
1108                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1109                 return;
1110         }
1111 
1112         if (nvlist_add_uint8(fmri, FM_VERSION, version) != 0) {
1113                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1114                 return;
1115         }
1116 
1117         if (nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_ZFS) != 0) {
1118                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1119                 return;
1120         }
1121 
1122         if (nvlist_add_uint64(fmri, FM_FMRI_ZFS_POOL, pool_guid) != 0) {
1123                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1124         }
1125 
1126         if (vdev_guid != 0) {
1127                 if (nvlist_add_uint64(fmri, FM_FMRI_ZFS_VDEV, vdev_guid) != 0) {
1128                         atomic_add_64(
1129                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1130                 }
1131         }
1132 }
1133 
1134 uint64_t
1135 fm_ena_increment(uint64_t ena)
1136 {
1137         uint64_t new_ena;
1138 
1139         switch (ENA_FORMAT(ena)) {
1140         case FM_ENA_FMT1:
1141                 new_ena = ena + (1 << ENA_FMT1_GEN_SHFT);
1142                 break;
1143         case FM_ENA_FMT2:
1144                 new_ena = ena + (1 << ENA_FMT2_GEN_SHFT);
1145                 break;
1146         default:
1147                 new_ena = 0;
1148         }
1149 


1289 void
1290 fm_fmri_hc_create(nvlist_t *fmri, int version, const nvlist_t *auth,
1291     nvlist_t *snvl, nvlist_t *bboard, int npairs, ...)
1292 {
1293         nv_alloc_t *nva = nvlist_lookup_nv_alloc(fmri);
1294         nvlist_t *pairs[HC_MAXPAIRS];
1295         nvlist_t **hcl;
1296         uint_t n;
1297         int i, j;
1298         va_list ap;
1299         char *hcname, *hcid;
1300 
1301         if (!fm_fmri_hc_set_common(fmri, version, auth))
1302                 return;
1303 
1304         /*
1305          * copy the bboard nvpairs to the pairs array
1306          */
1307         if (nvlist_lookup_nvlist_array(bboard, FM_FMRI_HC_LIST, &hcl, &n)
1308             != 0) {
1309                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1310                 return;
1311         }
1312 
1313         for (i = 0; i < n; i++) {
1314                 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME,
1315                     &hcname) != 0) {
1316                         atomic_add_64(
1317                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1318                         return;
1319                 }
1320                 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &hcid) != 0) {
1321                         atomic_add_64(
1322                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1323                         return;
1324                 }
1325 
1326                 pairs[i] = fm_nvlist_create(nva);
1327                 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, hcname) != 0 ||
1328                     nvlist_add_string(pairs[i], FM_FMRI_HC_ID, hcid) != 0) {
1329                         for (j = 0; j <= i; j++) {
1330                                 if (pairs[j] != NULL)
1331                                         fm_nvlist_destroy(pairs[j],
1332                                             FM_NVA_RETAIN);
1333                         }
1334                         atomic_add_64(
1335                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1336                         return;
1337                 }
1338         }
1339 
1340         /*
1341          * create the pairs from passed in pairs
1342          */
1343         npairs = MIN(npairs, HC_MAXPAIRS);
1344 
1345         va_start(ap, npairs);
1346         for (i = n; i < npairs + n; i++) {
1347                 const char *name = va_arg(ap, const char *);
1348                 uint32_t id = va_arg(ap, uint32_t);
1349                 char idstr[11];
1350                 (void) snprintf(idstr, sizeof (idstr), "%u", id);
1351                 pairs[i] = fm_nvlist_create(nva);
1352                 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
1353                     nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0) {
1354                         for (j = 0; j <= i; j++) {
1355                                 if (pairs[j] != NULL)
1356                                         fm_nvlist_destroy(pairs[j],
1357                                             FM_NVA_RETAIN);
1358                         }
1359                         atomic_add_64(
1360                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1361                         return;
1362                 }
1363         }
1364         va_end(ap);
1365 
1366         /*
1367          * Create the fmri hc list
1368          */
1369         if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, pairs,
1370             npairs + n) != 0) {
1371                 atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1372                 return;
1373         }
1374 
1375         for (i = 0; i < npairs + n; i++) {
1376                         fm_nvlist_destroy(pairs[i], FM_NVA_RETAIN);
1377         }
1378 
1379         if (snvl != NULL) {
1380                 if (nvlist_add_nvlist(fmri, FM_FMRI_HC_SPECIFIC, snvl) != 0) {
1381                         atomic_add_64(
1382                             &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
1383                         return;
1384                 }
1385         }
1386 }


 500                 dumpvp_write(&ed, sizeof (ed));
 501                 dumpvp_write(buf, len);
 502         }
 503 
 504         sysevent_evc_walk_fini(chq);
 505 }
 506 
 507 /*
 508  * Post an error report (ereport) to the sysevent error channel.  The error
 509  * channel must be established with a prior call to sysevent_evc_create()
 510  * before publication may occur.
 511  */
 512 void
 513 fm_ereport_post(nvlist_t *ereport, int evc_flag)
 514 {
 515         size_t nvl_size = 0;
 516         evchan_t *error_chan;
 517 
 518         (void) nvlist_size(ereport, &nvl_size, NV_ENCODE_NATIVE);
 519         if (nvl_size > ERPT_DATA_SZ || nvl_size == 0) {
 520                 atomic_inc_64(&erpt_kstat_data.erpt_dropped.value.ui64);
 521                 return;
 522         }
 523 
 524         if (sysevent_evc_bind(FM_ERROR_CHAN, &error_chan,
 525             EVCH_CREAT|EVCH_HOLD_PEND) != 0) {
 526                 atomic_inc_64(&erpt_kstat_data.erpt_dropped.value.ui64);
 527                 return;
 528         }
 529 
 530         if (sysevent_evc_publish(error_chan, EC_FM, ESC_FM_ERROR,
 531             SUNW_VENDOR, FM_PUB, ereport, evc_flag) != 0) {
 532                 atomic_inc_64(&erpt_kstat_data.erpt_dropped.value.ui64);
 533                 (void) sysevent_evc_unbind(error_chan);
 534                 return;
 535         }
 536         (void) sysevent_evc_unbind(error_chan);
 537 }
 538 
 539 /*
 540  * Wrapppers for FM nvlist allocators
 541  */
 542 /* ARGSUSED */
 543 static void *
 544 i_fm_alloc(nv_alloc_t *nva, size_t size)
 545 {
 546         return (kmem_zalloc(size, KM_SLEEP));
 547 }
 548 
 549 /* ARGSUSED */
 550 static void
 551 i_fm_free(nv_alloc_t *nva, void *buf, size_t size)
 552 {


 774                 }
 775 
 776                 name = va_arg(ap, char *);
 777         }
 778         return (ret);
 779 }
 780 
 781 void
 782 fm_payload_set(nvlist_t *payload, ...)
 783 {
 784         int ret;
 785         const char *name;
 786         va_list ap;
 787 
 788         va_start(ap, payload);
 789         name = va_arg(ap, char *);
 790         ret = i_fm_payload_set(payload, name, ap);
 791         va_end(ap);
 792 
 793         if (ret)
 794                 atomic_inc_64(&erpt_kstat_data.payload_set_failed.value.ui64);

 795 }
 796 
 797 /*
 798  * Set-up and validate the members of an ereport event according to:
 799  *
 800  *      Member name             Type            Value
 801  *      ====================================================
 802  *      class                   string          ereport
 803  *      version                 uint8_t         0
 804  *      ena                     uint64_t        <ena>
 805  *      detector                nvlist_t        <detector>
 806  *      ereport-payload         nvlist_t        <var args>
 807  *
 808  * We don't actually add a 'version' member to the payload.  Really,
 809  * the version quoted to us by our caller is that of the category 1
 810  * "ereport" event class (and we require FM_EREPORT_VERS0) but
 811  * the payload version of the actual leaf class event under construction
 812  * may be something else.  Callers should supply a version in the varargs,
 813  * or (better) we could take two version arguments - one for the
 814  * ereport category 1 classification (expect FM_EREPORT_VERS0) and one
 815  * for the leaf class.
 816  */
 817 void
 818 fm_ereport_set(nvlist_t *ereport, int version, const char *erpt_class,
 819     uint64_t ena, const nvlist_t *detector, ...)
 820 {
 821         char ereport_class[FM_MAX_CLASS];
 822         const char *name;
 823         va_list ap;
 824         int ret;
 825 
 826         if (version != FM_EREPORT_VERS0) {
 827                 atomic_inc_64(&erpt_kstat_data.erpt_set_failed.value.ui64);
 828                 return;
 829         }
 830 
 831         (void) snprintf(ereport_class, FM_MAX_CLASS, "%s.%s",
 832             FM_EREPORT_CLASS, erpt_class);
 833         if (nvlist_add_string(ereport, FM_CLASS, ereport_class) != 0) {
 834                 atomic_inc_64(&erpt_kstat_data.erpt_set_failed.value.ui64);
 835                 return;
 836         }
 837 
 838         if (nvlist_add_uint64(ereport, FM_EREPORT_ENA, ena)) {
 839                 atomic_inc_64(&erpt_kstat_data.erpt_set_failed.value.ui64);
 840         }
 841 
 842         if (nvlist_add_nvlist(ereport, FM_EREPORT_DETECTOR,
 843             (nvlist_t *)detector) != 0) {
 844                 atomic_inc_64(&erpt_kstat_data.erpt_set_failed.value.ui64);
 845         }
 846 
 847         va_start(ap, detector);
 848         name = va_arg(ap, const char *);
 849         ret = i_fm_payload_set(ereport, name, ap);
 850         va_end(ap);
 851 
 852         if (ret)
 853                 atomic_inc_64(&erpt_kstat_data.erpt_set_failed.value.ui64);
 854 }
 855 
 856 /*
 857  * Set-up and validate the members of an hc fmri according to;
 858  *
 859  *      Member name             Type            Value
 860  *      ===================================================
 861  *      version                 uint8_t         0
 862  *      auth                    nvlist_t        <auth>
 863  *      hc-name                 string          <name>
 864  *      hc-id                   string          <id>
 865  *
 866  * Note that auth and hc-id are optional members.
 867  */
 868 
 869 #define HC_MAXPAIRS     20
 870 #define HC_MAXNAMELEN   50
 871 
 872 static int
 873 fm_fmri_hc_set_common(nvlist_t *fmri, int version, const nvlist_t *auth)
 874 {
 875         if (version != FM_HC_SCHEME_VERSION) {
 876                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
 877                 return (0);
 878         }
 879 
 880         if (nvlist_add_uint8(fmri, FM_VERSION, version) != 0 ||
 881             nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC) != 0) {
 882                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
 883                 return (0);
 884         }
 885 
 886         if (auth != NULL && nvlist_add_nvlist(fmri, FM_FMRI_AUTHORITY,
 887             (nvlist_t *)auth) != 0) {
 888                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
 889                 return (0);
 890         }
 891 
 892         return (1);
 893 }
 894 
 895 void
 896 fm_fmri_hc_set(nvlist_t *fmri, int version, const nvlist_t *auth,
 897     nvlist_t *snvl, int npairs, ...)
 898 {
 899         nv_alloc_t *nva = nvlist_lookup_nv_alloc(fmri);
 900         nvlist_t *pairs[HC_MAXPAIRS];
 901         va_list ap;
 902         int i;
 903 
 904         if (!fm_fmri_hc_set_common(fmri, version, auth))
 905                 return;
 906 
 907         npairs = MIN(npairs, HC_MAXPAIRS);
 908 
 909         va_start(ap, npairs);
 910         for (i = 0; i < npairs; i++) {
 911                 const char *name = va_arg(ap, const char *);
 912                 uint32_t id = va_arg(ap, uint32_t);
 913                 char idstr[11];
 914 
 915                 (void) snprintf(idstr, sizeof (idstr), "%u", id);
 916 
 917                 pairs[i] = fm_nvlist_create(nva);
 918                 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
 919                     nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0) {
 920                         atomic_inc_64(
 921                             &erpt_kstat_data.fmri_set_failed.value.ui64);
 922                 }
 923         }
 924         va_end(ap);
 925 
 926         if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, pairs, npairs) != 0)
 927                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
 928 
 929         for (i = 0; i < npairs; i++)
 930                 fm_nvlist_destroy(pairs[i], FM_NVA_RETAIN);
 931 
 932         if (snvl != NULL) {
 933                 if (nvlist_add_nvlist(fmri, FM_FMRI_HC_SPECIFIC, snvl) != 0) {
 934                         atomic_inc_64(
 935                             &erpt_kstat_data.fmri_set_failed.value.ui64);
 936                 }
 937         }
 938 }
 939 
 940 /*
 941  * Set-up and validate the members of an dev fmri according to:
 942  *
 943  *      Member name             Type            Value
 944  *      ====================================================
 945  *      version                 uint8_t         0
 946  *      auth                    nvlist_t        <auth>
 947  *      devpath                 string          <devpath>
 948  *      [devid]                 string          <devid>
 949  *      [target-port-l0id]      string          <target-port-lun0-id>
 950  *
 951  * Note that auth and devid are optional members.
 952  */
 953 void
 954 fm_fmri_dev_set(nvlist_t *fmri_dev, int version, const nvlist_t *auth,
 955     const char *devpath, const char *devid, const char *tpl0)
 956 {
 957         int err = 0;
 958 
 959         if (version != DEV_SCHEME_VERSION0) {
 960                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
 961                 return;
 962         }
 963 
 964         err |= nvlist_add_uint8(fmri_dev, FM_VERSION, version);
 965         err |= nvlist_add_string(fmri_dev, FM_FMRI_SCHEME, FM_FMRI_SCHEME_DEV);
 966 
 967         if (auth != NULL) {
 968                 err |= nvlist_add_nvlist(fmri_dev, FM_FMRI_AUTHORITY,
 969                     (nvlist_t *)auth);
 970         }
 971 
 972         err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_PATH, devpath);
 973 
 974         if (devid != NULL)
 975                 err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_ID, devid);
 976 
 977         if (tpl0 != NULL)
 978                 err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_TGTPTLUN0, tpl0);
 979 
 980         if (err)
 981                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
 982 
 983 }
 984 
 985 /*
 986  * Set-up and validate the members of an cpu fmri according to:
 987  *
 988  *      Member name             Type            Value
 989  *      ====================================================
 990  *      version                 uint8_t         0
 991  *      auth                    nvlist_t        <auth>
 992  *      cpuid                   uint32_t        <cpu_id>
 993  *      cpumask                 uint8_t         <cpu_mask>
 994  *      serial                  uint64_t        <serial_id>
 995  *
 996  * Note that auth, cpumask, serial are optional members.
 997  *
 998  */
 999 void
1000 fm_fmri_cpu_set(nvlist_t *fmri_cpu, int version, const nvlist_t *auth,
1001     uint32_t cpu_id, uint8_t *cpu_maskp, const char *serial_idp)
1002 {
1003         uint64_t *failedp = &erpt_kstat_data.fmri_set_failed.value.ui64;
1004 
1005         if (version < CPU_SCHEME_VERSION1) {
1006                 atomic_inc_64(failedp);
1007                 return;
1008         }
1009 
1010         if (nvlist_add_uint8(fmri_cpu, FM_VERSION, version) != 0) {
1011                 atomic_inc_64(failedp);
1012                 return;
1013         }
1014 
1015         if (nvlist_add_string(fmri_cpu, FM_FMRI_SCHEME,
1016             FM_FMRI_SCHEME_CPU) != 0) {
1017                 atomic_inc_64(failedp);
1018                 return;
1019         }
1020 
1021         if (auth != NULL && nvlist_add_nvlist(fmri_cpu, FM_FMRI_AUTHORITY,
1022             (nvlist_t *)auth) != 0)
1023                 atomic_inc_64(failedp);
1024 
1025         if (nvlist_add_uint32(fmri_cpu, FM_FMRI_CPU_ID, cpu_id) != 0)
1026                 atomic_inc_64(failedp);
1027 
1028         if (cpu_maskp != NULL && nvlist_add_uint8(fmri_cpu, FM_FMRI_CPU_MASK,
1029             *cpu_maskp) != 0)
1030                 atomic_inc_64(failedp);
1031 
1032         if (serial_idp == NULL || nvlist_add_string(fmri_cpu,
1033             FM_FMRI_CPU_SERIAL_ID, (char *)serial_idp) != 0)
1034                         atomic_inc_64(failedp);
1035 }
1036 
1037 /*
1038  * Set-up and validate the members of a mem according to:
1039  *
1040  *      Member name             Type            Value
1041  *      ====================================================
1042  *      version                 uint8_t         0
1043  *      auth                    nvlist_t        <auth>            [optional]
1044  *      unum                    string          <unum>
1045  *      serial                  string          <serial>  [optional*]
1046  *      offset                  uint64_t        <offset>  [optional]
1047  *
1048  *      * serial is required if offset is present
1049  */
1050 void
1051 fm_fmri_mem_set(nvlist_t *fmri, int version, const nvlist_t *auth,
1052     const char *unum, const char *serial, uint64_t offset)
1053 {
1054         if (version != MEM_SCHEME_VERSION0) {
1055                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1056                 return;
1057         }
1058 
1059         if (!serial && (offset != (uint64_t)-1)) {
1060                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1061                 return;
1062         }
1063 
1064         if (nvlist_add_uint8(fmri, FM_VERSION, version) != 0) {
1065                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1066                 return;
1067         }
1068 
1069         if (nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM) != 0) {
1070                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1071                 return;
1072         }
1073 
1074         if (auth != NULL) {
1075                 if (nvlist_add_nvlist(fmri, FM_FMRI_AUTHORITY,
1076                     (nvlist_t *)auth) != 0) {
1077                         atomic_inc_64(
1078                             &erpt_kstat_data.fmri_set_failed.value.ui64);
1079                 }
1080         }
1081 
1082         if (nvlist_add_string(fmri, FM_FMRI_MEM_UNUM, unum) != 0) {
1083                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1084         }
1085 
1086         if (serial != NULL) {
1087                 if (nvlist_add_string_array(fmri, FM_FMRI_MEM_SERIAL_ID,
1088                     (char **)&serial, 1) != 0) {
1089                         atomic_inc_64(
1090                             &erpt_kstat_data.fmri_set_failed.value.ui64);






1091                 }
1092                 if (offset != (uint64_t)-1 && nvlist_add_uint64(fmri,
1093                     FM_FMRI_MEM_OFFSET, offset) != 0) {
1094                         atomic_inc_64(
1095                             &erpt_kstat_data.fmri_set_failed.value.ui64);
1096                 }
1097         }
1098 }
1099 
1100 void
1101 fm_fmri_zfs_set(nvlist_t *fmri, int version, uint64_t pool_guid,
1102     uint64_t vdev_guid)
1103 {
1104         if (version != ZFS_SCHEME_VERSION0) {
1105                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1106                 return;
1107         }
1108 
1109         if (nvlist_add_uint8(fmri, FM_VERSION, version) != 0) {
1110                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1111                 return;
1112         }
1113 
1114         if (nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_ZFS) != 0) {
1115                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1116                 return;
1117         }
1118 
1119         if (nvlist_add_uint64(fmri, FM_FMRI_ZFS_POOL, pool_guid) != 0) {
1120                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1121         }
1122 
1123         if (vdev_guid != 0) {
1124                 if (nvlist_add_uint64(fmri, FM_FMRI_ZFS_VDEV, vdev_guid) != 0) {
1125                         atomic_inc_64(
1126                             &erpt_kstat_data.fmri_set_failed.value.ui64);
1127                 }
1128         }
1129 }
1130 
1131 uint64_t
1132 fm_ena_increment(uint64_t ena)
1133 {
1134         uint64_t new_ena;
1135 
1136         switch (ENA_FORMAT(ena)) {
1137         case FM_ENA_FMT1:
1138                 new_ena = ena + (1 << ENA_FMT1_GEN_SHFT);
1139                 break;
1140         case FM_ENA_FMT2:
1141                 new_ena = ena + (1 << ENA_FMT2_GEN_SHFT);
1142                 break;
1143         default:
1144                 new_ena = 0;
1145         }
1146 


1286 void
1287 fm_fmri_hc_create(nvlist_t *fmri, int version, const nvlist_t *auth,
1288     nvlist_t *snvl, nvlist_t *bboard, int npairs, ...)
1289 {
1290         nv_alloc_t *nva = nvlist_lookup_nv_alloc(fmri);
1291         nvlist_t *pairs[HC_MAXPAIRS];
1292         nvlist_t **hcl;
1293         uint_t n;
1294         int i, j;
1295         va_list ap;
1296         char *hcname, *hcid;
1297 
1298         if (!fm_fmri_hc_set_common(fmri, version, auth))
1299                 return;
1300 
1301         /*
1302          * copy the bboard nvpairs to the pairs array
1303          */
1304         if (nvlist_lookup_nvlist_array(bboard, FM_FMRI_HC_LIST, &hcl, &n)
1305             != 0) {
1306                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1307                 return;
1308         }
1309 
1310         for (i = 0; i < n; i++) {
1311                 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME,
1312                     &hcname) != 0) {
1313                         atomic_inc_64(
1314                             &erpt_kstat_data.fmri_set_failed.value.ui64);
1315                         return;
1316                 }
1317                 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &hcid) != 0) {
1318                         atomic_inc_64(
1319                             &erpt_kstat_data.fmri_set_failed.value.ui64);
1320                         return;
1321                 }
1322 
1323                 pairs[i] = fm_nvlist_create(nva);
1324                 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, hcname) != 0 ||
1325                     nvlist_add_string(pairs[i], FM_FMRI_HC_ID, hcid) != 0) {
1326                         for (j = 0; j <= i; j++) {
1327                                 if (pairs[j] != NULL)
1328                                         fm_nvlist_destroy(pairs[j],
1329                                             FM_NVA_RETAIN);
1330                         }
1331                         atomic_inc_64(
1332                             &erpt_kstat_data.fmri_set_failed.value.ui64);
1333                         return;
1334                 }
1335         }
1336 
1337         /*
1338          * create the pairs from passed in pairs
1339          */
1340         npairs = MIN(npairs, HC_MAXPAIRS);
1341 
1342         va_start(ap, npairs);
1343         for (i = n; i < npairs + n; i++) {
1344                 const char *name = va_arg(ap, const char *);
1345                 uint32_t id = va_arg(ap, uint32_t);
1346                 char idstr[11];
1347                 (void) snprintf(idstr, sizeof (idstr), "%u", id);
1348                 pairs[i] = fm_nvlist_create(nva);
1349                 if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
1350                     nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0) {
1351                         for (j = 0; j <= i; j++) {
1352                                 if (pairs[j] != NULL)
1353                                         fm_nvlist_destroy(pairs[j],
1354                                             FM_NVA_RETAIN);
1355                         }
1356                         atomic_inc_64(
1357                             &erpt_kstat_data.fmri_set_failed.value.ui64);
1358                         return;
1359                 }
1360         }
1361         va_end(ap);
1362 
1363         /*
1364          * Create the fmri hc list
1365          */
1366         if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, pairs,
1367             npairs + n) != 0) {
1368                 atomic_inc_64(&erpt_kstat_data.fmri_set_failed.value.ui64);
1369                 return;
1370         }
1371 
1372         for (i = 0; i < npairs + n; i++) {
1373                         fm_nvlist_destroy(pairs[i], FM_NVA_RETAIN);
1374         }
1375 
1376         if (snvl != NULL) {
1377                 if (nvlist_add_nvlist(fmri, FM_FMRI_HC_SPECIFIC, snvl) != 0) {
1378                         atomic_inc_64(
1379                                 &erpt_kstat_data.fmri_set_failed.value.ui64);
1380                         return;
1381                 }
1382         }
1383 }