1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Routines for traversing and packing/unpacking the handle
  28  * returned from ri_init.
  29  */
  30 
  31 #include <stdlib.h>
  32 #include <strings.h>
  33 #include "rsrc_info.h"
  34 #include "rsrc_info_impl.h"
  35 
  36 static int ap_list_pack(ri_ap_t *, char **, size_t *, int);
  37 static int ap_list_unpack(char *, size_t, ri_ap_t **);
  38 static int ap_pack(ri_ap_t *, char **, size_t *, int);
  39 static int ap_unpack(char *, size_t, ri_ap_t *);
  40 static int dev_list_pack(ri_dev_t *, char **, size_t *, int);
  41 static int dev_list_unpack(char *, size_t, ri_dev_t **);
  42 static int dev_pack(ri_dev_t *, char **, size_t *, int);
  43 static int dev_unpack(char *, size_t, ri_dev_t *);
  44 static int client_list_pack(ri_client_t *, char **, size_t *, int);
  45 static int client_list_unpack(char *, size_t, ri_client_t **);
  46 static int client_pack(ri_client_t *, char **, size_t *, int);
  47 static int client_unpack(char *, size_t, ri_client_t *);
  48 static int pack_add_byte_array(nvlist_t *, char *, nvlist_t *, int);
  49 static int lookup_unpack_byte_array(nvlist_t *, char *, nvlist_t **);
  50 static void ri_ap_free(ri_ap_t *);
  51 
  52 void
  53 ri_fini(ri_hdl_t *hdl)
  54 {
  55         ri_ap_t         *ap;
  56         ri_client_t     *client;
  57 
  58         if (hdl == NULL)
  59                 return;
  60 
  61         while ((ap = hdl->aps) != NULL) {
  62                 hdl->aps = ap->next;
  63                 ri_ap_free(ap);
  64         }
  65         while ((client = hdl->cpu_cap_clients) != NULL) {
  66                 hdl->cpu_cap_clients = client->next;
  67                 ri_client_free(client);
  68         }
  69         while ((client = hdl->mem_cap_clients) != NULL) {
  70                 hdl->mem_cap_clients = client->next;
  71                 ri_client_free(client);
  72         }
  73         free(hdl);
  74 }
  75 
  76 static void
  77 ri_ap_free(ri_ap_t *ap)
  78 {
  79         ri_dev_t        *dev;
  80 
  81         assert(ap != NULL);
  82 
  83         nvlist_free(ap->conf_props);
  84 
  85         while ((dev = ap->cpus) != NULL) {
  86                 ap->cpus = dev->next;
  87                 ri_dev_free(dev);
  88         }
  89         while ((dev = ap->mems) != NULL) {
  90                 ap->mems = dev->next;
  91                 ri_dev_free(dev);
  92         }
  93         while ((dev = ap->ios) != NULL) {
  94                 ap->ios = dev->next;
  95                 ri_dev_free(dev);
  96         }
  97         free(ap);
  98 }
  99 
 100 void
 101 ri_dev_free(ri_dev_t *dev)
 102 {
 103         ri_client_t     *client;
 104 
 105         assert(dev != NULL);
 106 
 107         nvlist_free(dev->conf_props);
 108         while ((client = dev->rcm_clients) != NULL) {
 109                 dev->rcm_clients = client->next;
 110                 ri_client_free(client);
 111         }
 112         free(dev);
 113 }
 114 
 115 void
 116 ri_client_free(ri_client_t *client)
 117 {
 118         assert(client != NULL);
 119 
 120         nvlist_free(client->usg_props);
 121         nvlist_free(client->v_props);
 122         free(client);
 123 }
 124 
 125 /*
 126  * Pack everything contained in the handle up inside out.
 127  */
 128 int
 129 ri_pack(ri_hdl_t *hdl, caddr_t *bufp, size_t *sizep, int encoding)
 130 {
 131         nvlist_t        *nvl = NULL;
 132         char            *buf = NULL;
 133         size_t          size = 0;
 134 
 135         if (bufp == NULL || sizep == NULL)
 136                 return (RI_INVAL);
 137 
 138         *sizep = 0;
 139         *bufp = NULL;
 140 
 141         /*
 142          * Check the handle. If it is NULL, there
 143          * is nothing to pack, so we are done.
 144          */
 145         if (hdl == NULL) {
 146                 return (RI_SUCCESS);
 147         }
 148 
 149         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
 150                 dprintf((stderr, "nvlist_alloc fail\n", errno));
 151                 goto fail;
 152         }
 153 
 154         if (nvlist_add_int32(nvl, RI_HDL_FLAGS, hdl->flags) != 0) {
 155                 dprintf((stderr, "nvlist_add_int32 fail\n"));
 156                 goto fail;
 157         }
 158 
 159         if (ap_list_pack(hdl->aps, &buf, &size, encoding) != 0 ||
 160             nvlist_add_byte_array(nvl, RI_HDL_APS, (uchar_t *)buf, size) != 0) {
 161                 goto fail;
 162         }
 163 
 164         s_free(buf);
 165         if (client_list_pack(hdl->cpu_cap_clients, &buf, &size,
 166             encoding) != 0 ||
 167             nvlist_add_byte_array(nvl, RI_HDL_CPU_CAPS, (uchar_t *)buf,
 168             size) != 0) {
 169                 goto fail;
 170         }
 171 
 172         s_free(buf);
 173         if (client_list_pack(hdl->mem_cap_clients, &buf, &size,
 174             encoding) != 0 ||
 175             nvlist_add_byte_array(nvl, RI_HDL_MEM_CAPS, (uchar_t *)buf,
 176             size) != 0) {
 177                 goto fail;
 178         }
 179 
 180         s_free(buf);
 181         if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
 182                 dprintf((stderr, "nvlist_pack fail\n"));
 183                 goto fail;
 184         }
 185 
 186         nvlist_free(nvl);
 187         *bufp = buf;
 188         *sizep = size;
 189 
 190         return (RI_SUCCESS);
 191 
 192 fail:
 193         s_free(buf);
 194         nvlist_free(nvl);
 195 
 196         return (RI_FAILURE);
 197 }
 198 
 199 /*
 200  * Pack a list of attachment point handles.
 201  */
 202 static int
 203 ap_list_pack(ri_ap_t *aplist, char **bufp, size_t *sizep, int encoding)
 204 {
 205         nvlist_t        *nvl = NULL;
 206         char            *buf = NULL;
 207         size_t          size;
 208 
 209         assert(bufp != NULL && sizep != NULL);
 210 
 211         *sizep = 0;
 212         *bufp = NULL;
 213 
 214         if (nvlist_alloc(&nvl, 0, 0) != 0) {
 215                 dprintf((stderr, "nvlist_alloc fail\n"));
 216                 return (-1);
 217         }
 218 
 219         while (aplist != NULL) {
 220                 s_free(buf);
 221                 if (ap_pack(aplist, &buf, &size, encoding) != 0)
 222                         goto fail;
 223 
 224                 if (nvlist_add_byte_array(nvl, RI_AP_T, (uchar_t *)buf,
 225                     size) != 0) {
 226                         dprintf((stderr, "nvlist_add_byte_array fail "
 227                             "(%s)\n", RI_AP_T));
 228                         goto fail;
 229                 }
 230                 aplist = aplist->next;
 231         }
 232 
 233         s_free(buf);
 234         if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
 235                 dprintf((stderr, "nvlist_pack fail\n"));
 236                 goto fail;
 237         }
 238 
 239         nvlist_free(nvl);
 240         *bufp = buf;
 241         *sizep = size;
 242 
 243         return (0);
 244 
 245 fail:
 246         s_free(buf);
 247         nvlist_free(nvl);
 248 
 249         return (-1);
 250 }
 251 
 252 /*
 253  * Pack a list of ri_dev_t's.
 254  */
 255 static int
 256 dev_list_pack(ri_dev_t *devlist, char **bufp, size_t *sizep, int encoding)
 257 {
 258         nvlist_t        *nvl = NULL;
 259         char            *buf = NULL;
 260         size_t          size = 0;
 261 
 262         assert(bufp != NULL && sizep != NULL);
 263 
 264         *sizep = 0;
 265         *bufp = NULL;
 266 
 267         if (nvlist_alloc(&nvl, 0, 0) != 0) {
 268                 dprintf((stderr, "nvlist_alloc fail\n"));
 269                 return (-1);
 270         }
 271 
 272         while (devlist != NULL) {
 273                 s_free(buf);
 274                 if (dev_pack(devlist, &buf, &size, encoding) != 0)
 275                         goto fail;
 276 
 277                 if (nvlist_add_byte_array(nvl, RI_DEV_T, (uchar_t *)buf,
 278                     size) != 0) {
 279                         dprintf((stderr, "nvlist_add_byte_array fail "
 280                             "(%s)\n", RI_DEV_T));
 281                         goto fail;
 282                 }
 283                 devlist = devlist->next;
 284         }
 285 
 286         s_free(buf);
 287         if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
 288                 dprintf((stderr, "nvlist_pack fail\n"));
 289                 goto fail;
 290         }
 291 
 292         nvlist_free(nvl);
 293         *bufp = buf;
 294         *sizep = size;
 295 
 296         return (0);
 297 
 298 fail:
 299         s_free(buf);
 300         nvlist_free(nvl);
 301 
 302         return (-1);
 303 }
 304 
 305 /*
 306  * Pack a list of ri_client_t's.
 307  */
 308 static int
 309 client_list_pack(ri_client_t *client_list, char **bufp, size_t *sizep,
 310     int encoding)
 311 {
 312         nvlist_t        *nvl = NULL;
 313         char            *buf = NULL;
 314         size_t          size = 0;
 315 
 316         assert(bufp != NULL && sizep != NULL);
 317 
 318         *sizep = 0;
 319         *bufp = NULL;
 320 
 321         if (nvlist_alloc(&nvl, 0, 0) != 0) {
 322                 dprintf((stderr, "nvlist_alloc fail\n"));
 323                 return (-1);
 324         }
 325 
 326         while (client_list != NULL) {
 327                 s_free(buf);
 328                 if (client_pack(client_list, &buf, &size, encoding) != 0)
 329                         goto fail;
 330 
 331                 if (nvlist_add_byte_array(nvl, RI_CLIENT_T, (uchar_t *)buf,
 332                     size) != 0) {
 333                         dprintf((stderr, "nvlist_add_byte_array fail "
 334                             "(%s)\n", RI_CLIENT_T));
 335                         goto fail;
 336                 }
 337                 client_list = client_list->next;
 338         }
 339 
 340         s_free(buf);
 341         if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
 342                 dprintf((stderr, "nvlist_pack fail\n"));
 343                 goto fail;
 344         }
 345 
 346         nvlist_free(nvl);
 347         *bufp = buf;
 348         *sizep = size;
 349 
 350         return (0);
 351 
 352 fail:
 353         s_free(buf);
 354         nvlist_free(nvl);
 355 
 356         return (-1);
 357 }
 358 
 359 static int
 360 ap_pack(ri_ap_t *ap, char **bufp, size_t *sizep, int encoding)
 361 {
 362         nvlist_t        *nvl = NULL;
 363         char            *buf = NULL;
 364         size_t          size = 0;
 365 
 366         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
 367                 dprintf((stderr, "nvlist_alloc fail\n"));
 368                 return (-1);
 369         }
 370 
 371         if (pack_add_byte_array(ap->conf_props, RI_AP_PROPS, nvl,
 372             encoding) != 0)
 373                 goto fail;
 374 
 375         if (dev_list_pack(ap->cpus, &buf, &size, encoding) != 0)
 376                 goto fail;
 377 
 378         if (nvlist_add_byte_array(nvl, RI_AP_CPUS, (uchar_t *)buf,
 379             size) != 0) {
 380                 dprintf((stderr, "nvlist_add_byte_array (%s)\n", RI_AP_CPUS));
 381                 goto fail;
 382         }
 383 
 384         s_free(buf);
 385         if (dev_list_pack(ap->mems, &buf, &size, encoding) != 0)
 386                 goto fail;
 387 
 388         if (nvlist_add_byte_array(nvl, RI_AP_MEMS, (uchar_t *)buf,
 389             size) != 0) {
 390                 dprintf((stderr, "nvlist_add_byte_array (%s)n", RI_AP_MEMS));
 391                 goto fail;
 392         }
 393 
 394         s_free(buf);
 395         if (dev_list_pack(ap->ios, &buf, &size, encoding) != 0)
 396                 goto fail;
 397 
 398         if (nvlist_add_byte_array(nvl, RI_AP_IOS, (uchar_t *)buf,
 399             size) != 0) {
 400                 dprintf((stderr, "nvlist_add_byte_array (%s)n", RI_AP_IOS));
 401                 goto fail;
 402         }
 403 
 404         s_free(buf);
 405         if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
 406                 dprintf((stderr, "nvlist_pack fail\n"));
 407                 goto fail;
 408         }
 409 
 410         nvlist_free(nvl);
 411         *bufp = buf;
 412         *sizep = size;
 413 
 414         return (0);
 415 
 416 fail:
 417         s_free(buf);
 418         nvlist_free(nvl);
 419 
 420         return (-1);
 421 }
 422 
 423 static int
 424 dev_pack(ri_dev_t *dev, char **bufp, size_t *sizep, int encoding)
 425 {
 426         nvlist_t        *nvl = NULL;
 427         char            *buf = NULL;
 428         size_t          size = 0;
 429 
 430         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
 431                 dprintf((stderr, "nvlist_alloc fail\n"));
 432                 return (-1);
 433         }
 434 
 435         if (pack_add_byte_array(dev->conf_props, RI_DEV_PROPS, nvl,
 436             encoding) != 0)
 437                 goto fail;
 438 
 439         if (client_list_pack(dev->rcm_clients, &buf, &size, encoding) != 0)
 440                 goto fail;
 441 
 442         if (nvlist_add_byte_array(nvl, RI_DEV_CLIENTS, (uchar_t *)buf,
 443             size) != 0) {
 444                 dprintf((stderr, "nvlist_add_byte_array (%s)n",
 445                     RI_DEV_CLIENTS));
 446                 goto fail;
 447         }
 448 
 449         s_free(buf);
 450         if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
 451                 dprintf((stderr, "nvlist_pack fail\n"));
 452                 goto fail;
 453         }
 454 
 455         nvlist_free(nvl);
 456         *bufp = buf;
 457         *sizep = size;
 458 
 459         return (0);
 460 
 461 fail:
 462         s_free(buf);
 463         nvlist_free(nvl);
 464 
 465         return (-1);
 466 }
 467 
 468 static int
 469 client_pack(ri_client_t *client, char **bufp, size_t *sizep, int encoding)
 470 {
 471         nvlist_t        *nvl = NULL;
 472         char            *buf = NULL;
 473         size_t          size = 0;
 474 
 475         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
 476                 dprintf((stderr, "nvlist_alloc fail\n"));
 477                 return (-1);
 478         }
 479 
 480         if (pack_add_byte_array(client->usg_props, RI_CLIENT_USAGE_PROPS,
 481             nvl, encoding) != 0) {
 482                 goto fail;
 483         }
 484 
 485         /*
 486          * This will only be present if RI_VERBOSE was specified
 487          * in the call to ri_init.
 488          */
 489         if (client->v_props != NULL && pack_add_byte_array(client->v_props,
 490             RI_CLIENT_VERB_PROPS, nvl, encoding) != 0) {
 491                 goto fail;
 492         }
 493 
 494         if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
 495                 dprintf((stderr, "nvlist_pack fail\n"));
 496                 goto fail;
 497         }
 498 
 499         nvlist_free(nvl);
 500         *bufp = buf;
 501         *sizep = size;
 502 
 503         return (0);
 504 
 505 fail:
 506         s_free(buf);
 507         nvlist_free(nvl);
 508 
 509         return (-1);
 510 }
 511 
 512 /*
 513  * Pack nvlist_t and add as byte array to another nvlist_t.
 514  */
 515 static int
 516 pack_add_byte_array(nvlist_t *nvl_packme, char *name, nvlist_t *nvl,
 517     int encoding)
 518 {
 519         char    *buf = NULL;
 520         size_t  size = 0;
 521 
 522         if (nvlist_pack(nvl_packme, &buf, &size, encoding, 0) != 0) {
 523                 dprintf((stderr, "nvlist_pack fail (%s)\n", name));
 524                 s_free(buf);
 525                 return (-1);
 526         }
 527 
 528         if (nvlist_add_byte_array(nvl, name, (uchar_t *)buf, size) != 0) {
 529                 dprintf((stderr, "nvlist_add_byte_array fail (%s)\n", name));
 530                 return (-1);
 531         }
 532 
 533         s_free(buf);
 534         return (0);
 535 }
 536 
 537 /*
 538  * Unpack buf into ri_hdl_t.
 539  */
 540 int
 541 ri_unpack(caddr_t buf, size_t size, ri_hdl_t **hdlp)
 542 {
 543         ri_hdl_t        *ri_hdl = NULL;
 544         nvlist_t        *nvl = NULL;
 545 
 546         if (hdlp == NULL)
 547                 return (RI_INVAL);
 548 
 549         *hdlp = NULL;
 550         if ((ri_hdl = calloc(1, sizeof (*ri_hdl))) == NULL) {
 551                 dprintf((stderr, "calloc: %s\n", strerror(errno)));
 552                 return (RI_FAILURE);
 553         }
 554 
 555         if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
 556                 dprintf((stderr, "nvlist_unpack fail\n"));
 557                 goto fail;
 558         }
 559 
 560         if (nvlist_lookup_int32(nvl, RI_HDL_FLAGS, &ri_hdl->flags) != 0) {
 561                 dprintf((stderr, "nvlist_lookup_int32 fail (%s)\n",
 562                     RI_HDL_FLAGS));
 563                 goto fail;
 564         }
 565 
 566         buf = NULL;
 567         size = 0;
 568         if (nvlist_lookup_byte_array(nvl, RI_HDL_APS, (uchar_t **)&buf,
 569             (uint_t *)&size) != 0) {
 570                 dprintf((stderr, "nvlist_lookup_int32 fail (%s)\n",
 571                     RI_HDL_APS));
 572                 goto fail;
 573         }
 574 
 575         if (ap_list_unpack(buf, size, &ri_hdl->aps) != 0)
 576                 goto fail;
 577 
 578         buf = NULL;
 579         size = 0;
 580         if (nvlist_lookup_byte_array(nvl, RI_HDL_CPU_CAPS, (uchar_t **)&buf,
 581             (uint_t *)&size) != 0) {
 582                 dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
 583                     RI_HDL_CPU_CAPS));
 584                 goto fail;
 585         }
 586 
 587         if (client_list_unpack(buf, size, &ri_hdl->cpu_cap_clients) != 0)
 588                 goto fail;
 589 
 590         buf = NULL;
 591         size = 0;
 592         if (nvlist_lookup_byte_array(nvl, RI_HDL_MEM_CAPS, (uchar_t **)&buf,
 593             (uint_t *)&size) != 0) {
 594                 dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
 595                     RI_HDL_MEM_CAPS));
 596                 goto fail;
 597         }
 598 
 599         if (client_list_unpack(buf, size, &ri_hdl->mem_cap_clients) != 0)
 600                 goto fail;
 601 
 602         *hdlp = ri_hdl;
 603 
 604         return (0);
 605 
 606 fail:
 607         free(ri_hdl);
 608         nvlist_free(nvl);
 609 
 610         return (-1);
 611 }
 612 
 613 static int
 614 ap_list_unpack(char *buf, size_t size, ri_ap_t **aps)
 615 {
 616         nvpair_t        *nvp = NULL;
 617         nvlist_t        *nvl;
 618         ri_ap_t         *aplist = NULL;
 619         ri_ap_t         *prev = NULL;
 620         ri_ap_t         *tmp = NULL;
 621 
 622         if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
 623                 dprintf((stderr, "nvlist_unpack fail\n"));
 624                 return (-1);
 625         }
 626 
 627         while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
 628                 assert(strcmp(nvpair_name(nvp), RI_AP_T) == 0 &&
 629                     nvpair_type(nvp) == DATA_TYPE_BYTE_ARRAY);
 630 
 631                 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
 632                         dprintf((stderr, "calloc: %s\n", strerror(errno)));
 633                         goto fail;
 634                 }
 635 
 636                 buf = NULL;
 637                 size = 0;
 638                 if (nvpair_value_byte_array(nvp, (uchar_t **)&buf,
 639                     (uint_t *)&size) != 0) {
 640                         dprintf((stderr, "nvpair_value_byte_array fail\n"));
 641                         goto fail;
 642                 }
 643 
 644                 if (ap_unpack(buf, size, tmp) != 0)
 645                         goto fail;
 646 
 647                 if (aplist == NULL) {
 648                         prev = aplist = tmp;
 649                 } else {
 650                         prev->next = tmp;
 651                         prev = tmp;
 652                 }
 653         }
 654 
 655         nvlist_free(nvl);
 656         *aps = aplist;
 657 
 658         return (0);
 659 
 660 fail:
 661         nvlist_free(nvl);
 662         if (aplist != NULL) {
 663                 while ((tmp = aplist) != NULL) {
 664                         aplist = aplist->next;
 665                         ri_ap_free(tmp);
 666                 }
 667         }
 668 
 669         return (-1);
 670 }
 671 
 672 static int
 673 dev_list_unpack(char *buf, size_t size, ri_dev_t **devs)
 674 {
 675         nvpair_t        *nvp = NULL;
 676         nvlist_t        *nvl;
 677         ri_dev_t        *devlist = NULL;
 678         ri_dev_t        *prev = NULL;
 679         ri_dev_t        *tmp = NULL;
 680 
 681         if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
 682                 dprintf((stderr, "nvlist_unpack fail\n"));
 683                 return (-1);
 684         }
 685 
 686         while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
 687                 assert(strcmp(nvpair_name(nvp), RI_DEV_T) == 0 &&
 688                     nvpair_type(nvp) == DATA_TYPE_BYTE_ARRAY);
 689 
 690                 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
 691                         dprintf((stderr, "calloc: %s\n", strerror(errno)));
 692                         goto fail;
 693                 }
 694 
 695                 if (nvpair_value_byte_array(nvp, (uchar_t **)&buf,
 696                     (uint_t *)&size) != 0) {
 697                         dprintf((stderr, "nvpair_value_byte_array fail\n"));
 698                         goto fail;
 699                 }
 700 
 701                 if (dev_unpack(buf, size, tmp) != 0)
 702                         goto fail;
 703 
 704                 if (devlist == NULL) {
 705                         prev = devlist = tmp;
 706                 } else {
 707                         prev->next = tmp;
 708                         prev = tmp;
 709                 }
 710         }
 711 
 712         nvlist_free(nvl);
 713         *devs = devlist;
 714 
 715         return (0);
 716 
 717 fail:
 718         nvlist_free(nvl);
 719         if (devlist != NULL) {
 720                 while ((tmp = devlist) != NULL) {
 721                         devlist = devlist->next;
 722                         ri_dev_free(tmp);
 723                 }
 724         }
 725 
 726         return (-1);
 727 }
 728 
 729 static int
 730 client_list_unpack(char *buf, size_t size, ri_client_t **clients)
 731 {
 732         nvpair_t        *nvp = NULL;
 733         nvlist_t        *nvl;
 734         ri_client_t     *client_list = NULL;
 735         ri_client_t     *prev = NULL;
 736         ri_client_t     *tmp = NULL;
 737 
 738         if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
 739                 dprintf((stderr, "nvlist_unpack fail\n"));
 740                 return (-1);
 741         }
 742 
 743         while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
 744                 assert(strcmp(nvpair_name(nvp), RI_CLIENT_T) == 0);
 745                 assert(nvpair_type(nvp) == DATA_TYPE_BYTE_ARRAY);
 746 
 747                 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
 748                         dprintf((stderr, "calloc: %s\n", strerror(errno)));
 749                         goto fail;
 750                 }
 751 
 752                 buf = NULL;
 753                 size = 0;
 754                 if (nvpair_value_byte_array(nvp, (uchar_t **)&buf,
 755                     (uint_t *)&size) != 0) {
 756                         dprintf((stderr, "nvpair_value_byte_array fail\n"));
 757                         goto fail;
 758                 }
 759 
 760                 if (client_unpack(buf, size, tmp) != 0)
 761                         goto fail;
 762 
 763                 if (client_list == NULL) {
 764                         prev = client_list = tmp;
 765                 } else {
 766                         prev->next = tmp;
 767                         prev = tmp;
 768                 }
 769         }
 770 
 771         nvlist_free(nvl);
 772         *clients = client_list;
 773 
 774         return (0);
 775 
 776 fail:
 777         nvlist_free(nvl);
 778         if (client_list != NULL) {
 779                 while ((tmp = client_list) != NULL) {
 780                         client_list = client_list->next;
 781                         ri_client_free(tmp);
 782                 }
 783         }
 784 
 785         return (-1);
 786 }
 787 
 788 static int
 789 client_unpack(char *buf, size_t size, ri_client_t *client)
 790 {
 791         nvlist_t        *nvl;
 792 
 793         if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
 794                 dprintf((stderr, "nvlist_unpack fail\n"));
 795                 return (-1);
 796         }
 797 
 798         if (lookup_unpack_byte_array(nvl, RI_CLIENT_USAGE_PROPS,
 799             &client->usg_props) != 0) {
 800                 nvlist_free(nvl);
 801                 return (-1);
 802         }
 803 
 804 #ifdef DEBUG
 805         nvlist_print(stderr, client->usg_props);
 806 #endif /* DEBUG */
 807 
 808         /*
 809          * Verbose properties for RCM clients only present if
 810          * RI_VERBOSE was specified for ri_init.
 811          */
 812         buf = NULL;
 813         size = 0;
 814         if (nvlist_lookup_byte_array(nvl, RI_CLIENT_VERB_PROPS,
 815             (uchar_t **)&buf, (uint_t *)&size) == 0) {
 816                 if (nvlist_unpack(buf, size, &client->v_props, 0) != 0) {
 817                         dprintf((stderr, "nvlist_unpack fail (%s)\n",
 818                             RI_CLIENT_VERB_PROPS));
 819                         nvlist_free(nvl);
 820                         return (-1);
 821                 }
 822         }
 823 
 824         nvlist_free(nvl);
 825 
 826         return (0);
 827 }
 828 
 829 static int
 830 dev_unpack(char *buf, size_t size, ri_dev_t *dev)
 831 {
 832         nvlist_t        *nvl;
 833 
 834         if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
 835                 dprintf((stderr, "nvlist_unpack fail\n"));
 836                 return (-1);
 837         }
 838 
 839         if (lookup_unpack_byte_array(nvl, RI_DEV_PROPS,
 840             &dev->conf_props) != 0) {
 841                 nvlist_free(nvl);
 842                 return (-1);
 843         }
 844 
 845 #ifdef DEBUG
 846         nvlist_print(stderr, dev->conf_props);
 847 #endif /* DEBUG */
 848 
 849         if (nvlist_lookup_byte_array(nvl, RI_DEV_CLIENTS, (uchar_t **)&buf,
 850             (uint_t *)&size) != 0) {
 851                 dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
 852                     RI_DEV_CLIENTS));
 853                 nvlist_free(nvl);
 854                 return (-1);
 855         }
 856 
 857         if (client_list_unpack(buf, size, &dev->rcm_clients) != 0) {
 858                 nvlist_free(nvl);
 859                 return (-1);
 860         }
 861 
 862         nvlist_free(nvl);
 863 
 864         return (0);
 865 }
 866 
 867 static int
 868 ap_unpack(char *buf, size_t size, ri_ap_t *ap)
 869 {
 870         nvlist_t        *nvl;
 871 
 872         if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
 873                 dprintf((stderr, "nvlist_unpack fail\n"));
 874                 return (-1);
 875         }
 876 
 877         if (lookup_unpack_byte_array(nvl, RI_AP_PROPS, &ap->conf_props) != 0) {
 878                 nvlist_free(nvl);
 879                 return (-1);
 880         }
 881 
 882 #ifdef DEBUG
 883         nvlist_print(stderr, ap->conf_props);
 884 #endif /* DEBUG */
 885 
 886         if (nvlist_lookup_byte_array(nvl, RI_AP_CPUS, (uchar_t **)&buf,
 887             (uint_t *)&size) != 0) {
 888                 dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
 889                     RI_AP_CPUS));
 890                 nvlist_free(nvl);
 891                 return (-1);
 892         }
 893 
 894         if (dev_list_unpack(buf, size, &ap->cpus) != 0) {
 895                 nvlist_free(nvl);
 896                 return (-1);
 897         }
 898 
 899         if (nvlist_lookup_byte_array(nvl, RI_AP_MEMS, (uchar_t **)&buf,
 900             (uint_t *)&size) != 0) {
 901                 dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
 902                     RI_AP_MEMS));
 903                 nvlist_free(nvl);
 904                 return (-1);
 905         }
 906 
 907         if (dev_list_unpack(buf, size, &ap->mems) != 0) {
 908                 nvlist_free(nvl);
 909                 return (-1);
 910         }
 911 
 912         if (nvlist_lookup_byte_array(nvl, RI_AP_IOS, (uchar_t **)&buf,
 913             (uint_t *)&size) != 0) {
 914                 dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
 915                     RI_AP_IOS));
 916                 nvlist_free(nvl);
 917                 return (-1);
 918         }
 919 
 920         if (dev_list_unpack(buf, size, &ap->ios) != 0) {
 921                 nvlist_free(nvl);
 922                 return (-1);
 923         }
 924 
 925         nvlist_free(nvl);
 926 
 927         return (0);
 928 }
 929 
 930 /*
 931  * Lookup byte array in old nvlist_t and unpack into new nvlist_t.
 932  */
 933 static int
 934 lookup_unpack_byte_array(nvlist_t *old_nvl, char *name, nvlist_t **new_nvl)
 935 {
 936         char    *buf = NULL;
 937         size_t  size = 0;
 938 
 939         if (nvlist_lookup_byte_array(old_nvl, name, (uchar_t **)&buf,
 940             (uint_t *)&size) != 0) {
 941                 dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
 942                     name));
 943                 return (-1);
 944         }
 945 
 946         if (nvlist_unpack(buf, size, new_nvl, 0) != 0) {
 947                 dprintf((stderr, "nvlist_unpack fail (%s)\n", name));
 948                 return (-1);
 949         }
 950 
 951         return (0);
 952 }
 953 
 954 ri_ap_t *
 955 ri_ap_next(ri_hdl_t *hdl, ri_ap_t *ap)
 956 {
 957         if (hdl == NULL) {
 958                 errno = EINVAL;
 959                 return (NULL);
 960         }
 961         return ((ap == NULL) ? hdl->aps : ap->next);
 962 }
 963 
 964 nvlist_t *
 965 ri_ap_conf_props(ri_ap_t *ap)
 966 {
 967         if (ap == NULL) {
 968                 errno = EINVAL;
 969                 return (NULL);
 970         }
 971         return (ap->conf_props);
 972 }
 973 
 974 ri_dev_t *
 975 ri_cpu_next(ri_ap_t *ap, ri_dev_t *cpu)
 976 {
 977         if (ap == NULL) {
 978                 errno = EINVAL;
 979                 return (NULL);
 980         }
 981         return ((cpu == NULL) ? ap->cpus : cpu->next);
 982 }
 983 
 984 ri_dev_t *
 985 ri_mem_next(ri_ap_t *ap, ri_dev_t *mem)
 986 {
 987         if (ap == NULL) {
 988                 errno = EINVAL;
 989                 return (NULL);
 990         }
 991         return ((mem == NULL) ? ap->mems : mem->next);
 992 }
 993 
 994 ri_dev_t *
 995 ri_io_next(ri_ap_t *ap, ri_dev_t *io)
 996 {
 997         if (ap == NULL) {
 998                 errno = EINVAL;
 999                 return (NULL);
1000         }
1001         return ((io == NULL) ? ap->ios : io->next);
1002 }
1003 
1004 ri_client_t *
1005 ri_client_next(ri_dev_t *dev, ri_client_t *rcm_client)
1006 {
1007         if (dev == NULL) {
1008                 errno = EINVAL;
1009                 return (NULL);
1010         }
1011         return ((rcm_client == NULL) ? dev->rcm_clients : rcm_client->next);
1012 }
1013 
1014 nvlist_t *
1015 ri_dev_conf_props(ri_dev_t *dev)
1016 {
1017         if (dev == NULL) {
1018                 errno = EINVAL;
1019                 return (NULL);
1020         }
1021         return (dev->conf_props);
1022 }
1023 
1024 nvlist_t *
1025 ri_client_usage_props(ri_client_t *rcm_client)
1026 {
1027         if (rcm_client == NULL) {
1028                 errno = EINVAL;
1029                 return (NULL);
1030         }
1031         return (rcm_client->usg_props);
1032 }
1033 
1034 nvlist_t *
1035 ri_client_verbose_props(ri_client_t *rcm_client)
1036 {
1037         if (rcm_client == NULL) {
1038                 errno = EINVAL;
1039                 return (NULL);
1040         }
1041         return (rcm_client->v_props);
1042 }
1043 
1044 ri_client_t *
1045 ri_cpu_cap_client_next(ri_hdl_t *hdl, ri_client_t *rcm_client)
1046 {
1047         if (hdl == NULL) {
1048                 errno = EINVAL;
1049                 return (NULL);
1050         }
1051         return ((rcm_client == NULL) ? hdl->cpu_cap_clients : rcm_client->next);
1052 }
1053 
1054 ri_client_t *
1055 ri_mem_cap_client_next(ri_hdl_t *hdl, ri_client_t *rcm_client)
1056 {
1057         if (hdl == NULL) {
1058                 errno = EINVAL;
1059                 return (NULL);
1060         }
1061         return ((rcm_client == NULL) ? hdl->mem_cap_clients : rcm_client->next);
1062 }