1 /****************************************************************************** 2 * 3 * Description 4 * mpapi.c - Implements Multipath Management API Version 1.0 5 * 6 * License: 7 * The contents of this file are subject to the SNIA Public License 8 * Version 1.1 (the "License"); you may not use this file except in 9 * compliance with the License. You may obtain a copy of the License at 10 * 11 * http://mp-mgmt-api.sourceforge.net 12 * 13 * Software distributed under the License is distributed on an "AS IS" 14 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15 * the License for the specific language governing rights and limitations 16 * under the License. 17 * 18 * The Original Code is SNIA iSCSI Management API and Multipath Management 19 * API header files. 20 * 21 * The Initial Developer of the Original Code is: 22 * Benjamin F. Kuo Troika Networks, Inc. (benk@troikanetworks.com) 23 * David Dillard VERITAS Software(david.dillard@veritas.com) 24 * Jeff Ding Adaptec, Inc. (jding@corp.adaptec.com) 25 * Hyon Kim Sun Microsystems(hyon.kim@sun.com) 26 * 27 * Contributor(s): 28 * Paul von Behren Sun Microsystems(paul.vonbehren@sun.com) 29 * 30 ****************************************************************************** 31 * 32 * Changes: 33 * 1/15/2005 Implemented SNIA MP API specification 1.0 34 * 10/11/2005 35 * - License location was specified in the header comment. 36 * - validate_object() routine was updated per the latest 37 * specification. 38 * - is_zero_oid() routine was added. 39 * - MP_GetObjectType() was updated with validate_object(). 40 * - pplist argument checking added in MP_GetMultipathLus(). 41 * - Corrected typo in MP_GetTaregetPortGroupProperties() 42 * - MP_RegisterForObjectPropertyChanges() was updated with 43 * is_zero_oid() routine. 44 * - MP_DeregisterForObjectPropertyChanges() was updated with 45 * is_zero_oid() routine. 46 * - MP_RegisterForObjectVisibilityChanges() was updated with 47 * is_zero_oid() routine. 48 * - MP_DeregisterForObjectVisibilityChanges() was updated with 49 * is_zero_oid() routine. 50 * - Added stat() check in MP_RegisterPlugin() to validate the 51 * the given plugin file name. 52 * - Made MP_DeregisterPlugin() return MP_STATUS_UNKNOWN_FN 53 * to mach the specification description. 54 ****************************************************************************** 55 */ 56 57 #include <sys/sem.h> 58 #include <dlfcn.h> 59 #include <stdarg.h> 60 #include <unistd.h> 61 #include <sys/stat.h> 62 #include <sys/types.h> 63 #include <sys/mman.h> 64 #include <errno.h> 65 #include <stdio.h> 66 #include <fcntl.h> 67 #include <time.h> 68 #include <pthread.h> 69 #include "mpapi.h" 70 #include "mpapi-sun.h" 71 #include "mpapi-plugin.h" 72 73 #define LIBRARY_SUPPORTED_MP_VERSION 1 74 #define LIBRARY_IMPLEMENTATION_VERSION L"1.0.0" 75 #define LIBRARY_VENDOR L"Sun Microsystems Inc." 76 77 #define LIBRARY_FILE_NAME "libMPAPI.so" 78 79 80 MPPLUGININFO_T plugintable[MP_MAX_NUM_PLUGINS]; 81 pthread_mutex_t mp_lib_mutex = PTHREAD_MUTEX_INITIALIZER; 82 83 static int number_of_plugins = -1; 84 85 86 void InitLibrary(); 87 void ExitLibrary(); 88 static int lock_register(int fd, int cmd, int type, off_t offset, int whence, 89 off_t len); 90 static int search_line(MP_CHAR *buf, size_t buflen, MP_CHAR *srch_id, 91 size_t id_len, int *write_offset, int *bytes_left); 92 static int is_zero_oid(MP_OID); 93 94 /** 95 ****************************************************************************** 96 * 97 * Validate the oid. 98 * 99 * - Return MP_STATUS_OBJECT_NOT_FOUND when no plugin is found or the ownerId 100 * of input OID is not found. 101 * - Return MP_STATUS_INVALID_OBJECT_TYPE when no plugin is found or 102 * the type of input OID is not one of legitimate types defined SNIA 103 * Multipath Management spec. 104 * - Return MP_STATUS_INVALID_PARAMETER when the type of input OID is 105 * legitimate but its object type doesn't match with the object type 106 * argument. 107 * - Otherwise return MP_STATUS_SUCCESS. 108 * 109 ****************************************************************************** 110 */ 111 MP_STATUS validate_object(MP_OID obj, MP_OBJECT_TYPE objType, 112 MP_UINT32 flag) 113 { 114 115 if ((number_of_plugins == 0) || 116 (obj.ownerId > number_of_plugins || obj.ownerId <= 0)) { 117 return (MP_STATUS_OBJECT_NOT_FOUND); 118 } else if (obj.objectType < 0 || obj.objectType > MP_OBJECT_TYPE_MAX) { 119 return (MP_STATUS_INVALID_OBJECT_TYPE); 120 } else if (obj.objectType == MP_OBJECT_TYPE_PLUGIN) { 121 if (obj.objectSequenceNumber != 0) { 122 return (MP_STATUS_OBJECT_NOT_FOUND); 123 } 124 } 125 126 if (flag == MP_OBJECT_TYPE_MATCH) { 127 if (obj.objectType != objType) { 128 return (MP_STATUS_INVALID_PARAMETER); 129 } 130 } 131 return (MP_STATUS_SUCCESS); 132 } 133 134 /** 135 ****************************************************************************** 136 * 137 * Check if an oid is ZERO_OID or not. 138 * 139 * - Return 1 if the input OID is ZERO_OID 140 * 141 * - Return 0 if not. 142 * 143 ****************************************************************************** 144 */ 145 static int is_zero_oid(MP_OID oid) 146 { 147 148 if ((oid.objectType != MP_OBJECT_TYPE_UNKNOWN) || (oid.ownerId != 0) || 149 (oid.objectSequenceNumber != 0)) { 150 return (0); 151 } 152 153 return (1); 154 } 155 156 /** 157 ****************************************************************************** 158 * 159 * Initialize by loading plugin libraries and calling Initialize routine. 160 * Note: The build of libMPAPI.so should include a linker option to make this 161 * routine executed when it is loaded. 162 * 163 * - This routine bypasses a plugin library if it is not found. 164 * - The implementation of this routine is based on configuration file 165 * /etc/mpapi.conf that contains a list of plugin libraries. 166 * 167 ****************************************************************************** 168 */ 169 void InitLibrary() 170 { 171 FILE *mpconf; 172 int fd_mpconf; 173 MP_WCHAR fullline[MAX_LINE_SIZE]; /* line read in from mpapi.conf */ 174 MP_WCHAR name[MAX_NAME_SIZE]; /* Read in from file mpapi.conf */ 175 char path[MAX_NAME_SIZE]; /* Read in from file mpapi.conf */ 176 char systemPath[MAX_NAME_SIZE], mpConfFilePath[MAX_NAME_SIZE]; 177 MP_WCHAR *charPtr; 178 MP_WCHAR *sol; 179 struct stat stat_buf; 180 181 MP_UINT32 i = 0; /* index for plugin table */ 182 183 if(number_of_plugins != -1) { 184 return; 185 } 186 187 (void) pthread_mutex_lock(&mp_lib_mutex); 188 189 number_of_plugins = 0; 190 191 /* Open configuration file from known location */ 192 strncpy(mpConfFilePath, "/etc/mpapi.conf", MAX_NAME_SIZE); 193 194 if ((fd_mpconf = open(mpConfFilePath, O_RDONLY)) < 0) { 195 (void) pthread_mutex_unlock(&mp_lib_mutex); 196 return; 197 } 198 199 if (lock_register(fd_mpconf, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) { 200 close(fd_mpconf); 201 (void) pthread_mutex_unlock(&mp_lib_mutex); 202 return; 203 } 204 205 if ((mpconf = fdopen(fd_mpconf, "r")) == NULL) { 206 lock_register(fd_mpconf, F_SETLK, F_UNLCK, 0, SEEK_SET, 0); 207 close(fd_mpconf); 208 (void) pthread_mutex_unlock(&mp_lib_mutex); 209 return; 210 } 211 212 /* Read in each line and load library */ 213 while ((mpconf != NULL) && 214 (charPtr = fgetws(fullline, MAX_LINE_SIZE, mpconf))) { 215 if ((*charPtr != L'#') && (*charPtr != L'\n')) { 216 /* Take out the '\n' */ 217 if ((charPtr = wcschr(fullline, L'\n')) != NULL) 218 *charPtr = L'\0'; 219 220 charPtr = fullline; 221 /* remove leading blank or taps. */ 222 while ((fullline[0] == L' ') || (fullline[0] == L'\t')) 223 charPtr++; 224 225 sol = charPtr; 226 227 /* 228 * look for first tab or space. 229 */ 230 if ((charPtr = wcschr(fullline, L'\t')) == NULL) 231 charPtr = wcschr(fullline, L' '); 232 233 /* Set Null termination for library name if found */ 234 if (charPtr != NULL) { 235 *charPtr++ = L'\0'; 236 wcsncpy(name, sol, MAX_NAME_SIZE); 237 /* Skip space and tab until the next character found */ 238 while ((*charPtr == L' ') || (*charPtr == L'\t')) 239 charPtr++; 240 } else { 241 continue; /* May be invalid entry */ 242 } 243 244 /* Copy library name and path */ 245 wcstombs(path, charPtr, MAX_NAME_SIZE); 246 247 /* 248 * Continue to the next line if library name or path is 249 * invalid 250 */ 251 if ((wcslen(name) == 0) || 252 (strlen(path) == 0)) 253 continue; 254 255 /* Load the plugin now */ 256 if (stat(path, &stat_buf) != -1) { 257 plugintable[i].hdlPlugin = dlopen(path, RTLD_LAZY); 258 } else { 259 continue; 260 } 261 262 if (plugintable[i].hdlPlugin != NULL) { 263 InitializeFn PassFunc; 264 MP_STATUS status; 265 266 wcsncpy(plugintable[i].pluginName, 267 name, MAX_NAME_SIZE); 268 strncpy(plugintable[i].pluginPath, 269 path, MAX_NAME_SIZE); 270 271 plugintable[i].ownerId = i + 1; 272 273 PassFunc = (InitializeFn) 274 dlsym(plugintable[i].hdlPlugin, "Initialize"); 275 if (PassFunc != NULL) { 276 status = PassFunc(plugintable[i].ownerId); 277 } 278 279 i++; 280 } 281 } 282 } 283 284 if (lock_register(fd_mpconf, F_SETLK, F_UNLCK, 0, SEEK_SET, 0) < 0) { 285 fclose(mpconf); 286 close(fd_mpconf); 287 (void) pthread_mutex_unlock(&mp_lib_mutex); 288 return; 289 } 290 fclose(mpconf); 291 close(fd_mpconf); 292 293 number_of_plugins = i; 294 (void) pthread_mutex_unlock(&mp_lib_mutex); 295 } 296 297 /** 298 ****************************************************************************** 299 * 300 * Exit by calling Terminate routine of plugin libraries. 301 * 302 * Note: The build of libMPAPI.so should include a linker option to make this 303 * routine executed when it is unloaded. 304 * 305 ****************************************************************************** 306 */ 307 void ExitLibrary() 308 { 309 MP_UINT32 i, j; 310 311 if(number_of_plugins == -1) 312 return; 313 314 (void) pthread_mutex_lock(&mp_lib_mutex); 315 for (i = 0; i < number_of_plugins; i++) { 316 if (plugintable[i].hdlPlugin != NULL) { 317 TerminateFn ExitPassFunc; 318 319 ExitPassFunc = (TerminateFn) 320 dlsym(plugintable[i].hdlPlugin, "Terminate"); 321 322 if (ExitPassFunc != NULL) { 323 ExitPassFunc(); 324 } 325 326 /* Unload plugin from memory */ 327 dlclose(plugintable[i].hdlPlugin); 328 } 329 } 330 331 number_of_plugins = -1; 332 333 (void) pthread_mutex_unlock(&mp_lib_mutex); 334 (void) pthread_mutex_destroy(&mp_lib_mutex); 335 } 336 337 /** 338 ****************************************************************************** 339 * 340 * Gets the properties of the MP API library that is being used. 341 * 342 * @param pProps 343 * A pointer to an @ref MP_LIBRARY_PROPERTIES structure allocated by 344 * the caller. On successful return this structure will contain the 345 * properties of the MP library. 346 * 347 * @return An MP_STATUS indicating if the operation was successful or 348 * if an error occurred. 349 * 350 * @retval MP_STATUS_SUCCESS 351 * Returned if the library properties were successfully returned. 352 * 353 * @retval MP_STATUS_INVALID_PARAMETER Returned if @a pProps is NULL or 354 * specifies a memory area to which data cannot be written. 355 * 356 ****************************************************************************** 357 */ 358 MP_STATUS MP_GetLibraryProperties( 359 MP_LIBRARY_PROPERTIES *pProps) 360 { 361 char mpPath[MAX_NAME_SIZE]; 362 363 if(pProps == NULL) { 364 return MP_STATUS_INVALID_PARAMETER; 365 } 366 367 /* Fill in properties */ 368 if (mbstowcs(pProps->buildTime, BUILD_TIME, 256) != 369 strlen(BUILD_TIME)) { 370 return (MP_STATUS_INVALID_PARAMETER); 371 } 372 pProps->supportedMpVersion = LIBRARY_SUPPORTED_MP_VERSION; 373 374 wcsncpy(pProps->implementationVersion, 375 LIBRARY_IMPLEMENTATION_VERSION, MAX_NAME_SIZE); 376 wcsncpy(pProps->vendor, LIBRARY_VENDOR, MAX_NAME_SIZE); 377 378 snprintf(pProps->fileName, MAX_NAME_SIZE, "%s", 379 LIBRARY_FILE_NAME); 380 381 return MP_STATUS_SUCCESS; 382 } 383 384 385 /** 386 ****************************************************************************** 387 * 388 * Gets a list of the object IDs of all currently loaded plugins. 389 * 390 * @param ppList A pointer to a pointer to an @ref MP_OID_LIST. On successful 391 * return this will contain a pointer to an @ref MP_OID_LIST 392 * which contains the object IDs of all of the plugins currently loaded 393 * by the library. 394 * @return An MP_STATUS indicating if the operation was successful or if 395 * an error 396 * occurred. 397 * @retval MP_SUCCESS Returned if the plugin ID list was successfully returned. 398 * @retval MP_STATUS_INVALID_PARAMETER Returned if @a ppList is NULL or 399 * specifies a memory area to which data cannot be written. 400 * 401 ****************************************************************************** 402 */ 403 MP_STATUS MP_GetPluginOidList( 404 MP_OID_LIST **ppList) 405 { 406 MP_UINT32 i; 407 408 if (ppList == NULL) 409 return (MP_STATUS_INVALID_PARAMETER); 410 411 (void) pthread_mutex_lock(&mp_lib_mutex); 412 413 if (number_of_plugins == 0) { 414 *ppList = (MP_OID_LIST*)calloc(1, sizeof(MP_OID_LIST)); 415 } else { 416 *ppList = (MP_OID_LIST*)calloc(1, 417 sizeof(MP_OID_LIST) + (number_of_plugins - 1)* sizeof(MP_OID) ); 418 } 419 420 if ((*ppList) == NULL) { 421 (void) pthread_mutex_unlock(&mp_lib_mutex); 422 return (MP_STATUS_INSUFFICIENT_MEMORY); 423 } 424 425 (*ppList)->oidCount = number_of_plugins; 426 427 if (number_of_plugins != 0) { 428 for (i = 0; i < number_of_plugins; i++) { 429 (*ppList)->oids[i].objectType = MP_OBJECT_TYPE_PLUGIN; 430 (*ppList)->oids[i].ownerId = plugintable[i].ownerId; 431 (*ppList)->oids[i].objectSequenceNumber = 0; 432 } 433 } 434 435 (void) pthread_mutex_unlock(&mp_lib_mutex); 436 return MP_STATUS_SUCCESS; 437 } 438 439 /** 440 ******************************************************************************* 441 * 442 * Gets the properties of the specified vendor plugin. 443 * 444 * @param oid 445 * The ID of the plugin whose properties are being retrieved. 446 * 447 * @param pProps 448 * A pointer to an @ref MP_PLUGIN_PROPERTIES structure allocated by 449 * the caller. On successful return this will contain the properties 450 * of the plugin specified by pluginOid. 451 * 452 * @return An MP_STATUS indicating if the operation was successful or if an 453 * error occurred. 454 * 455 * @retval MP_STATUS_SUCCESS 456 * Returned if the plugin properties were successfully returned. 457 * 458 * @retval MP_STATUS_INVALID_OBJECT_TYPE 459 * Returned if oid does not specify any valid object type. 460 * 461 * @retval MP_STATUS_OBJECT_NOT_FOUND 462 * Returned if oid has an owner that is not currently known to 463 * the system. 464 * 465 * @retval MP_STATUS_INVALID_PARAMETER 466 * Returned if 'pProps' is NULL or specifies a memory area to 467 * which data cannot be written. 468 * 469 ******************************************************************************* 470 */ 471 MP_STATUS MP_GetPluginProperties( 472 MP_OID pluginOid, 473 MP_PLUGIN_PROPERTIES *pProps) 474 { 475 MP_GetPluginPropertiesPluginFn PassFunc; 476 MP_UINT32 index; 477 MP_STATUS status; 478 479 if(pProps == NULL) 480 return (MP_STATUS_INVALID_PARAMETER); 481 482 if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN, 483 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 484 return (status); 485 } 486 487 (void) pthread_mutex_lock(&mp_lib_mutex); 488 489 index = pluginOid.ownerId - 1; 490 if (plugintable[index].hdlPlugin != NULL) { 491 PassFunc = (MP_GetPluginPropertiesPluginFn) 492 dlsym(plugintable[index].hdlPlugin, "MP_GetPluginPropertiesPlugin"); 493 494 if (PassFunc != NULL) { 495 status = PassFunc(pProps); 496 } else { 497 status = MP_STATUS_UNSUPPORTED; 498 } 499 } else { 500 status = MP_STATUS_FAILED; 501 } 502 503 (void) pthread_mutex_unlock(&mp_lib_mutex); 504 return status; 505 } 506 507 /** 508 ******************************************************************************* 509 * 510 * Gets the object ID for the plugin associated with the specified object ID. 511 * 512 * @param oid 513 * The object ID of an object that has been received from a previous 514 * library call. 515 * 516 * @param pPluginOid 517 * A pointer to an MP_OID structure allocated by the caller. On 518 * successful return this will contain the object ID of the plugin 519 * associated with the object specified by @a objectId. 520 * 521 * @return An MP_STATUS indicating if the operation was successful or if 522 * an error occurred. 523 * 524 * @retval MP_STATUS_SUCCESS 525 * Returned if the associated plugin ID was successfully returned. 526 * 527 * @retval MP_STATUS_OBJECT_NOT_FOUND 528 * Returned if oid does not specify a plugin that is currently known to 529 * the system. 530 * 531 * @retval MP_STATUS_INVALID_PARAMETER 532 * Returned if 'oid' specifies an object not owned by a plugin or 533 * if pPluginOid is NULL or specifies a memory area to which data 534 * cannot be written. 535 * 536 * @retval MP_STATUS_INVALID_OBJECT_TYPE 537 * Returned if 'oid' specifies an object with an invalid type. 538 * 539 ******************************************************************************* 540 */ 541 MP_STATUS MP_GetAssociatedPluginOid( 542 MP_OID objectId, 543 MP_OID *pPluginId) 544 { 545 MP_UINT32 i; 546 MP_STATUS status; 547 548 if (pPluginId == NULL) 549 return (MP_STATUS_INVALID_PARAMETER); 550 551 if ((status = validate_object(objectId, 0, MP_OBJECT_TYPE_ANY)) != 552 MP_STATUS_SUCCESS) { 553 return (status); 554 } 555 556 pPluginId->objectType = MP_OBJECT_TYPE_PLUGIN; 557 pPluginId->ownerId = objectId.ownerId; 558 pPluginId->objectSequenceNumber = 0; 559 560 return (MP_STATUS_SUCCESS); 561 } 562 563 /** 564 ******************************************************************************* 565 * 566 * Gets the object type of an initialized object ID. 567 * 568 * @param oid 569 * The object ID of an object that has been received from a previous 570 * library call. 571 * 572 * @param pObjectType 573 * A pointer to an MP_OBJECT_TYPE variable allocated by the caller. 574 * On successful return this will contain the object type of oid. 575 * 576 * @return An MP_STATUS indicating if the operation was successful or 577 * if an error occurred. 578 * 579 * @retval MP_STATUS_OBJECT_NOT_FOUND 580 * Returned if oid has an owner that is not currently known to 581 * the system. 582 * 583 * @retval MP_STATUS_INVALID_PARAMETER 584 * Returned if oid does not specify any valid object type. 585 * 586 * @retval MP_STATUS_SUCCESS 587 * Returned when the operation is successful. 588 * 589 ******************************************************************************* 590 */ 591 MP_STATUS MP_GetObjectType( 592 MP_OID oid, 593 MP_OBJECT_TYPE *pObjectType) 594 { 595 MP_STATUS status; 596 597 if (pObjectType == NULL) 598 return MP_STATUS_INVALID_PARAMETER; 599 600 if ((status = validate_object(oid, 0, MP_OBJECT_TYPE_ANY)) 601 != MP_STATUS_SUCCESS) { 602 return (status); 603 } 604 605 *pObjectType = oid.objectType; 606 return MP_STATUS_SUCCESS; 607 } 608 609 /** 610 ******************************************************************************* 611 * 612 * Gets a list of the object IDs of all the device product properties 613 * associated with this plugin. 614 * 615 * @param oid 616 * The object ID of plugin. 617 * 618 * @param ppList 619 * A pointer to a pointer to an MP_OID_LIST structure. 620 * On a successful return, this will contain a pointer to 621 * an MP_OID_LIST that contains the object IDs of all the device 622 * product descriptors associated with the specified plugin. 623 * 624 * @return An MP_STATUS indicating if the operation was successful or if 625 * an error occurred. 626 * 627 * @retval MP_STATUS_SUCCESS 628 * Returned when the operation is successful. 629 * 630 * @retval MP_STATUS_INVALID_PARAMETER 631 * Returned if ppList pointer passed as placeholder for holding 632 * the device product list is found to be invalid. 633 * 634 * @retval MP_STATUS_INVALID_OBJECT_TYPE 635 * Returned if oid does not specify any valid object type. 636 * 637 * @retval MP_STATUS_FAILED 638 * Returned when the plugin for the specified oid is not found. 639 * 640 * @retval MP_STATUS_INSUFFICIENT_MEMORY 641 * Returned when memory allocation failure occurs 642 * 643 * @retval MP_STATUS_UNSUPPORTED 644 * Returned when the API is not supported. 645 * 646 ******************************************************************************* 647 */ 648 MP_STATUS MP_GetDeviceProductOidList( 649 MP_OID oid, 650 MP_OID_LIST **ppList) 651 { 652 MP_GetDeviceProductOidListPluginFn PassFunc; 653 MP_UINT32 index; 654 MP_STATUS status; 655 656 if (ppList == NULL) 657 return MP_STATUS_INVALID_PARAMETER; 658 659 if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 660 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 661 return (status); 662 } 663 664 (void) pthread_mutex_lock(&mp_lib_mutex); 665 666 index = oid.ownerId - 1; 667 if (plugintable[index].hdlPlugin != NULL) { 668 PassFunc = (MP_GetDeviceProductOidListPluginFn) 669 dlsym(plugintable[index].hdlPlugin, 670 "MP_GetDeviceProductOidListPlugin"); 671 if (PassFunc != NULL) { 672 status = PassFunc(ppList); 673 } else { 674 status = MP_STATUS_UNSUPPORTED; 675 } 676 } else { 677 status = MP_STATUS_FAILED; 678 } 679 680 (void) pthread_mutex_unlock(&mp_lib_mutex); 681 return status; 682 } 683 684 /** 685 ******************************************************************************* 686 * 687 * Gets the device product properties of the specified plugin oid. 688 * 689 * @param oid 690 * The object ID of the plugin. 691 * 692 * @param ppProps 693 * A pointer to a pointer to an MP_DEVICE_PRODUCT_PROPERTIES structure 694 * allocated by the caller. On successful return it will contain 695 * a pointer to an MP_DEVICE_PRODUCT_PROPERTIES structure allocated 696 * by the library. 697 * 698 * @return An MP_STATUS indicating if the operation was successful or if 699 * an error occurred. 700 * 701 * @retval MP_STATUS_SUCCESS 702 * Returned when the operation is successful. 703 * 704 * @retval MP_STATUS_INVALID_PARAMETER 705 * Returned if ppProps pointer passed as placeholder for holding 706 * the device product properties is found to be invalid. 707 * 708 * @retval MP_STATUS_INVALID_OBJECT_TYPE 709 * Returned if oid does not specify any valid object type. 710 * 711 * @retval MP_STATUS_FAILED 712 * Returned when the plugin for the specified oid is not found. 713 * 714 * @retval MP_STATUS_INSUFFICIENT_MEMORY 715 * Returned when memory allocation failure occurs 716 * 717 * @retval MP_STATUS_UNSUPPORTED 718 * Returned when the API is not supported. 719 * 720 ******************************************************************************* 721 */ 722 MP_STATUS MP_GetDeviceProductProperties( 723 MP_OID oid, 724 MP_DEVICE_PRODUCT_PROPERTIES *pProps) 725 { 726 MP_GetDeviceProductPropertiesFn PassFunc; 727 MP_UINT32 index; 728 MP_STATUS status; 729 730 if (pProps == NULL) 731 return MP_STATUS_INVALID_PARAMETER; 732 733 if ((status = validate_object(oid, MP_OBJECT_TYPE_DEVICE_PRODUCT, 734 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 735 return (status); 736 } 737 738 (void) pthread_mutex_lock(&mp_lib_mutex); 739 740 index = oid.ownerId - 1; 741 if (plugintable[index].hdlPlugin != NULL) { 742 PassFunc = (MP_GetDeviceProductPropertiesFn) 743 dlsym(plugintable[index].hdlPlugin, 744 "MP_GetDeviceProductProperties"); 745 746 if (PassFunc != NULL) { 747 status = PassFunc(oid, pProps); 748 } else { 749 status = MP_STATUS_UNSUPPORTED; 750 } 751 } else { 752 status = MP_STATUS_FAILED; 753 } 754 755 (void) pthread_mutex_unlock(&mp_lib_mutex); 756 return status; 757 } 758 759 /** 760 ******************************************************************************* 761 * 762 * Gets a list of the object IDs of all the initiator ports associated 763 * with this plugin. 764 * 765 * @param oid 766 * The object ID of plugin. 767 * 768 * @param ppList 769 * A pointer to a pointer to an MP_OID_LIST structure. 770 * On a successful return, this will contain a pointer to 771 * an MP_OID_LIST that contains the object IDs of all the initiator 772 * ports associated with the specified plugin. 773 * 774 * @return An MP_STATUS indicating if the operation was successful or if 775 * an error occurred. 776 * 777 * @retval MP_STATUS_SUCCESS 778 * Returned when the operation is successful. 779 * 780 * @retval MP_STATUS_INVALID_PARAMETER 781 * Returned if ppList pointer passed as placeholder for holding 782 * the initiator port list is found to be invalid. 783 * 784 * @retval MP_STATUS_INVALID_OBJECT_TYPE 785 * Returned if oid does not specify any valid object type. 786 * 787 * @retval MP_STATUS_FAILED 788 * Returned when the plugin for the specified oid is not found. 789 * 790 * @retval MP_STATUS_INSUFFICIENT_MEMORY 791 * Returned when memory allocation failure occurs 792 * 793 * @retval MP_STATUS_UNSUPPORTED 794 * Returned when the API is not supported. 795 * 796 ******************************************************************************* 797 */ 798 MP_STATUS MP_GetInitiatorPortOidList( 799 MP_OID oid, 800 MP_OID_LIST **ppList) 801 { 802 MP_GetInitiatorPortOidListPluginFn PassFunc; 803 MP_UINT32 index; 804 MP_STATUS status; 805 806 if (ppList == NULL) 807 return MP_STATUS_INVALID_PARAMETER; 808 809 if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 810 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 811 return (status); 812 } 813 814 (void) pthread_mutex_lock(&mp_lib_mutex); 815 816 index = oid.ownerId - 1; 817 if (plugintable[index].hdlPlugin != NULL) { 818 PassFunc = (MP_GetDeviceProductOidListPluginFn) 819 dlsym(plugintable[index].hdlPlugin, "MP_GetInitiatorPortOidListPlugin"); 820 821 if (PassFunc != NULL) { 822 status = PassFunc(ppList); 823 } else { 824 status = MP_STATUS_UNSUPPORTED; 825 } 826 } else { 827 status = MP_STATUS_FAILED; 828 } 829 830 (void) pthread_mutex_unlock(&mp_lib_mutex); 831 return (status); 832 } 833 834 /** 835 ******************************************************************************* 836 * 837 * Gets the properties of the specified initiator port. 838 * 839 * @param oid 840 * The object ID of the initiator port. 841 * 842 * @param pProps 843 * A pointer to an MP_INITIATOR_PORT_PROPERTIES structure 844 * allocated by the caller. On successful return, this structure 845 * will contain the properties of the port specified by oid. 846 * 847 * @return An MP_STATUS indicating if the operation was successful or if 848 * an error occurred. 849 * 850 * @retval MP_STATUS_SUCCESS 851 * Returned when the operation is successful. 852 * 853 * @retval MP_STATUS_INVALID_PARAMETER 854 * Returned if pProps is NULL or specifies a memory area to 855 * which data cannot be written. 856 * 857 * @retval MP_STATUS_INVALID_OBJECT_TYPE 858 * Returned if oid does not specify any valid object type. 859 * 860 * @retval MP_STATUS_OBJECT_NOT_FOUND 861 * Returned if oid has an owner that is not currently known to 862 * the system. 863 * 864 ******************************************************************************* 865 */ 866 MP_STATUS MP_GetInitiatorPortProperties( 867 MP_OID oid, 868 MP_INITIATOR_PORT_PROPERTIES *pProps) 869 { 870 MP_GetInitiatorPortPropertiesFn PassFunc; 871 MP_UINT32 index; 872 MP_STATUS status; 873 874 if (pProps == NULL) 875 return MP_STATUS_INVALID_PARAMETER; 876 877 if ((status = validate_object(oid, MP_OBJECT_TYPE_INITIATOR_PORT, 878 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 879 return (status); 880 } 881 882 (void) pthread_mutex_lock(&mp_lib_mutex); 883 884 index = oid.ownerId - 1; 885 if (plugintable[index].hdlPlugin != NULL) { 886 PassFunc = (MP_GetInitiatorPortPropertiesFn) 887 dlsym(plugintable[index].hdlPlugin, 888 "MP_GetInitiatorPortProperties"); 889 890 if (PassFunc != NULL) { 891 status = PassFunc(oid, pProps); 892 } else { 893 status = MP_STATUS_UNSUPPORTED; 894 } 895 } else { 896 status = MP_STATUS_FAILED; 897 } 898 899 (void) pthread_mutex_unlock(&mp_lib_mutex); 900 return status; 901 } 902 903 /** 904 ******************************************************************************* 905 * 906 * Gets a list of multipath logical units associated to a plugin. 907 * 908 * @param oid 909 * The object ID of plugin. 910 * 911 * @param ppList 912 * A pointer to a pointer to an MP_OID_LIST structure. 913 * On a successful return, this will contain a pointer to 914 * an MP_OID_LIST that contains the object IDs of all the multipath 915 * logical units associated with the specified plugin. 916 * 917 * @return An MP_STATUS indicating if the operation was successful or if 918 * an error occurred. 919 * 920 * @retval MP_STATUS_SUCCESS 921 * Returned when the operation is successful. 922 * 923 * @retval MP_STATUS_INVALID_PARAMETER 924 * Returned if ppList pointer passed as placeholder for holding 925 * the multipath logical unit list is found to be invalid. 926 * 927 * @retval MP_STATUS_INVALID_OBJECT_TYPE 928 * Returned if oid does not specify any valid object type. 929 * 930 * @retval MP_STATUS_FAILED 931 * Returned when the plugin for the specified oid is not found. 932 * 933 * @retval MP_STATUS_INSUFFICIENT_MEMORY 934 * Returned when memory allocation failure occurs 935 * 936 * @retval MP_STATUS_UNSUPPORTED 937 * Returned when the API is not supported. 938 * 939 ******************************************************************************* 940 */ 941 MP_STATUS MP_GetMultipathLus( 942 MP_OID oid, 943 MP_OID_LIST **ppList) 944 { 945 MP_UINT32 index; 946 MP_STATUS status; 947 948 if (ppList == NULL) 949 return MP_STATUS_INVALID_PARAMETER; 950 951 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 952 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 953 ((status = validate_object(oid, MP_OBJECT_TYPE_DEVICE_PRODUCT, 954 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 955 return (status); 956 } 957 958 (void) pthread_mutex_lock(&mp_lib_mutex); 959 960 index = oid.ownerId - 1; 961 if (plugintable[index].hdlPlugin != NULL) { 962 if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) { 963 MP_GetMultipathLusPluginFn PassFunc; 964 PassFunc = (MP_GetMultipathLusPluginFn) 965 dlsym(plugintable[index].hdlPlugin, 966 "MP_GetMultipathLusPlugin"); 967 968 if (PassFunc != NULL) { 969 status = PassFunc(ppList); 970 } else { 971 status = MP_STATUS_UNSUPPORTED; 972 } 973 } else if (oid.objectType == MP_OBJECT_TYPE_DEVICE_PRODUCT) { 974 MP_GetMultipathLusDevProdFn PassFunc; 975 PassFunc = (MP_GetMultipathLusDevProdFn) 976 dlsym(plugintable[index].hdlPlugin, 977 "MP_GetMultipathLusDevProd"); 978 979 if (PassFunc != NULL) { 980 status = PassFunc(oid, ppList); 981 } else { 982 status = MP_STATUS_UNSUPPORTED; 983 } 984 } else { 985 status = MP_STATUS_INVALID_PARAMETER; 986 } 987 } 988 989 (void) pthread_mutex_unlock(&mp_lib_mutex); 990 return (status); 991 } 992 993 994 /** 995 ******************************************************************************* 996 * 997 * Gets the properties of the specified logical unit. 998 * 999 * @param oid 1000 * The object ID of the multipath logical unit. 1001 * 1002 * @param pProps 1003 * A pointer to an MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES structure 1004 * allocated by the caller. On successful return, this structure 1005 * will contain the properties of the port specified by oid. 1006 * 1007 * @return An MP_STATUS indicating if the operation was successful or if 1008 * an error occurred. 1009 * 1010 * @retval MP_STATUS_SUCCESS 1011 * Returned when the operation is successful. 1012 * 1013 * @retval MP_STATUS_INVALID_PARAMETER 1014 * Returned if pProps is NULL or specifies a memory area to 1015 * which data cannot be written. 1016 * 1017 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1018 * Returned if oid does not specify any valid object type. 1019 * 1020 * @retval MP_STATUS_OBJECT_NOT_FOUND 1021 * Returned if oid has an owner that is not currently known to 1022 * the system. 1023 * 1024 ******************************************************************************* 1025 */ 1026 MP_STATUS MP_GetMPLogicalUnitProperties( 1027 MP_OID oid, 1028 MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES *pProps) 1029 { 1030 MP_GetMPLogicalUnitPropertiesFn PassFunc; 1031 MP_UINT32 index; 1032 MP_STATUS status; 1033 1034 if (pProps == NULL) 1035 return MP_STATUS_INVALID_PARAMETER; 1036 1037 if ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 1038 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1039 return (status); 1040 } 1041 1042 (void) pthread_mutex_lock(&mp_lib_mutex); 1043 1044 index = oid.ownerId - 1; 1045 if (plugintable[index].hdlPlugin != NULL) { 1046 PassFunc = (MP_GetMPLogicalUnitPropertiesFn) 1047 dlsym(plugintable[index].hdlPlugin, 1048 "MP_GetMPLogicalUnitProperties"); 1049 1050 if (PassFunc != NULL) { 1051 status = PassFunc(oid, pProps); 1052 } else { 1053 status = MP_STATUS_UNSUPPORTED; 1054 } 1055 } else { 1056 status = MP_STATUS_FAILED; 1057 } 1058 1059 (void) pthread_mutex_unlock(&mp_lib_mutex); 1060 return (status); 1061 } 1062 1063 /** 1064 ******************************************************************************* 1065 * 1066 * Gets a list of the object IDs of all the path logical units associated 1067 * with the specified multipath logical unit, initiator port, or target port. 1068 * 1069 * @param oid 1070 * The object ID of multipath logical unit, initiator port, or 1071 * target port. 1072 * 1073 * @param ppList 1074 * A pointer to a pointer to an MP_OID_LIST structure. 1075 * On a successful return, this will contain a pointer to 1076 * an MP_OID_LIST that contains the object IDs of all the mp path 1077 * logical units associated with the specified OID. 1078 * 1079 * @return An MP_STATUS indicating if the operation was successful or if 1080 * an error occurred. 1081 * 1082 * @retval MP_STATUS_SUCCESS 1083 * Returned when the operation is successful. 1084 * 1085 * @retval MP_STATUS_INVALID_PARAMETER 1086 * Returned if ppList pointer passed as placeholder for holding 1087 * the device product list is found to be invalid. 1088 * 1089 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1090 * Returned if oid does not specify any valid object type. 1091 * 1092 * @retval MP_STATUS_FAILED 1093 * Returned when the plugin for the specified oid is not found. 1094 * 1095 * @retval MP_STATUS_INSUFFICIENT_MEMORY 1096 * Returned when memory allocation failure occurs 1097 * 1098 * @retval MP_STATUS_OBJECT_NOT_FOUND 1099 * Returned if oid has an owner that is not currently known to 1100 * the system. 1101 * 1102 ******************************************************************************* 1103 */ 1104 MP_STATUS MP_GetAssociatedPathOidList( 1105 MP_OID oid, 1106 MP_OID_LIST **ppList) 1107 { 1108 MP_GetAssociatedPathOidListFn PassFunc; 1109 MP_UINT32 index; 1110 MP_STATUS status; 1111 1112 if (ppList == NULL) 1113 return MP_STATUS_INVALID_PARAMETER; 1114 1115 if (((status = validate_object(oid, MP_OBJECT_TYPE_INITIATOR_PORT, 1116 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 1117 ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT, 1118 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 1119 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 1120 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 1121 return (status); 1122 } 1123 1124 (void) pthread_mutex_lock(&mp_lib_mutex); 1125 1126 index = oid.ownerId - 1; 1127 if (plugintable[index].hdlPlugin != NULL) { 1128 PassFunc = (MP_GetAssociatedPathOidListFn) 1129 dlsym(plugintable[index].hdlPlugin, 1130 "MP_GetAssociatedPathOidList"); 1131 1132 if (PassFunc != NULL) { 1133 status = PassFunc(oid, ppList); 1134 } else { 1135 status = MP_STATUS_UNSUPPORTED; 1136 } 1137 } else { 1138 status = MP_STATUS_FAILED; 1139 } 1140 1141 (void) pthread_mutex_unlock(&mp_lib_mutex); 1142 return (status); 1143 } 1144 1145 /** 1146 ******************************************************************************* 1147 * 1148 * Gets the properties of the specified path logical unit. 1149 * 1150 * @param oid 1151 * The object ID of the path logical unit. 1152 * 1153 * @param pProps 1154 * A pointer to an MP_PATH_LOGICAL_UNIT_PROPERTIES structure 1155 * allocated by the caller. On successful return, this structure 1156 * will contain the properties of the port specified by oid. 1157 * 1158 * @return An MP_STATUS indicating if the operation was successful or if 1159 * an error occurred. 1160 * 1161 * @retval MP_STATUS_SUCCESS 1162 * Returned when the operation is successful. 1163 * 1164 * @retval MP_STATUS_INVALID_PARAMETER 1165 * Returned if pProps is NULL or specifies a memory area to 1166 * which data cannot be written. 1167 * 1168 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1169 * Returned if oid does not specify any valid object type. 1170 * 1171 * @retval MP_STATUS_OBJECT_NOT_FOUND 1172 * Returned if oid has an owner that is not currently known to 1173 * the system. 1174 * 1175 ******************************************************************************* 1176 */ 1177 MP_STATUS MP_GetPathLogicalUnitProperties( 1178 MP_OID oid, 1179 MP_PATH_LOGICAL_UNIT_PROPERTIES *pProps) 1180 { 1181 MP_GetPathLogicalUnitPropertiesFn PassFunc; 1182 MP_UINT32 index; 1183 MP_STATUS status; 1184 1185 if (pProps == NULL) 1186 return MP_STATUS_INVALID_PARAMETER; 1187 1188 if ((status = validate_object(oid, MP_OBJECT_TYPE_PATH_LU, 1189 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1190 return (status); 1191 } 1192 1193 (void) pthread_mutex_lock(&mp_lib_mutex); 1194 1195 index = oid.ownerId - 1; 1196 if (plugintable[index].hdlPlugin != NULL) { 1197 PassFunc = (MP_GetPathLogicalUnitPropertiesFn) 1198 dlsym(plugintable[index].hdlPlugin, 1199 "MP_GetPathLogicalUnitProperties"); 1200 1201 if (PassFunc != NULL) { 1202 status = PassFunc(oid, pProps); 1203 } else { 1204 status = MP_STATUS_UNSUPPORTED; 1205 } 1206 } else { 1207 status = MP_STATUS_FAILED; 1208 } 1209 1210 (void) pthread_mutex_unlock(&mp_lib_mutex); 1211 return (status); 1212 } 1213 1214 /** 1215 ******************************************************************************* 1216 * 1217 * Gets a list of the object IDs of all the target port group associated 1218 * with the specified multipath logical unit. 1219 * 1220 * @param oid 1221 * The object ID of the multiple logical unit. 1222 * 1223 * @param ppList 1224 * A pointer to a pointer to an MP_OID_LIST structure. 1225 * On a successful return, this will contain a pointer to 1226 * an MP_OID_LIST that contains the object IDs of all the target 1227 * port group associated with the specified multipath logical unit. 1228 * 1229 * @return An MP_STATUS indicating if the operation was successful or if 1230 * an error occurred. 1231 * 1232 * @retval MP_STATUS_SUCCESS 1233 * Returned when the operation is successful. 1234 * 1235 * @retval MP_STATUS_INVALID_PARAMETER 1236 * Returned if ppList pointer passed as placeholder for holding 1237 * the target port group list is found to be invalid. 1238 * 1239 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1240 * Returned if oid does not specify any valid object type. 1241 * 1242 * @retval MP_STATUS_FAILED 1243 * Returned when the plugin for the specified oid is not found. 1244 * 1245 * @retval MP_STATUS_INSUFFICIENT_MEMORY 1246 * Returned when memory allocation failure occurs 1247 * 1248 * 1249 ******************************************************************************* 1250 */ 1251 MP_STATUS MP_GetAssociatedTPGOidList( 1252 MP_OID oid, 1253 MP_OID_LIST **ppList) 1254 { 1255 MP_GetAssociatedTPGOidListFn PassFunc; 1256 MP_UINT32 index; 1257 MP_STATUS status; 1258 1259 if (ppList == NULL) 1260 return MP_STATUS_INVALID_PARAMETER; 1261 1262 if ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 1263 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1264 return (status); 1265 } 1266 1267 (void) pthread_mutex_lock(&mp_lib_mutex); 1268 1269 index = oid.ownerId - 1; 1270 if (plugintable[index].hdlPlugin != NULL) { 1271 PassFunc = (MP_GetAssociatedTPGOidListFn) 1272 dlsym(plugintable[index].hdlPlugin, 1273 "MP_GetAssociatedTPGOidList"); 1274 1275 if (PassFunc != NULL) { 1276 status = PassFunc(oid, ppList); 1277 } else { 1278 status = MP_STATUS_UNSUPPORTED; 1279 } 1280 } else { 1281 status = MP_STATUS_FAILED; 1282 } 1283 1284 (void) pthread_mutex_unlock(&mp_lib_mutex); 1285 return (status); 1286 } 1287 1288 /** 1289 ******************************************************************************* 1290 * 1291 * Gets the properties of the specified target port group. 1292 * 1293 * @param oid 1294 * The object ID of the target port group. 1295 * 1296 * @param pProps 1297 * A pointer to an MP_TARGET_PORT_GROUP_PROPERTIES structure 1298 * allocated by the caller. On successful return, this structure 1299 * will contain the properties of the port specified by oid. 1300 * 1301 * @return An MP_STATUS indicating if the operation was successful or if 1302 * an error occurred. 1303 * 1304 * @retval MP_STATUS_SUCCESS 1305 * Returned when the operation is successful. 1306 * 1307 * @retval MP_STATUS_INVALID_PARAMETER 1308 * Returned if pProps is NULL or specifies a memory area to 1309 * which data cannot be written. 1310 * 1311 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1312 * Returned if oid does not specify any valid object type. 1313 * 1314 * @retval MP_STATUS_OBJECT_NOT_FOUND 1315 * Returned if oid has an owner that is not currently known to 1316 * the system. 1317 * 1318 ******************************************************************************* 1319 */ 1320 MP_STATUS MP_GetTargetPortGroupProperties( 1321 MP_OID oid, 1322 MP_TARGET_PORT_GROUP_PROPERTIES *pProps) 1323 { 1324 MP_GetTargetPortGroupPropertiesFn PassFunc; 1325 MP_UINT32 index; 1326 MP_STATUS status; 1327 1328 if (pProps == NULL) 1329 return MP_STATUS_INVALID_PARAMETER; 1330 1331 if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT_GROUP, 1332 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1333 return (status); 1334 } 1335 1336 (void) pthread_mutex_lock(&mp_lib_mutex); 1337 1338 index = oid.ownerId - 1; 1339 if (plugintable[index].hdlPlugin != NULL) { 1340 PassFunc = (MP_GetTargetPortGroupPropertiesFn) 1341 dlsym(plugintable[index].hdlPlugin, 1342 "MP_GetTargetPortGroupProperties"); 1343 1344 if (PassFunc != NULL) { 1345 status = PassFunc(oid, pProps); 1346 } else { 1347 status = MP_STATUS_UNSUPPORTED; 1348 } 1349 } else { 1350 status = MP_STATUS_FAILED; 1351 } 1352 1353 (void) pthread_mutex_unlock(&mp_lib_mutex); 1354 return (status); 1355 } 1356 1357 /** 1358 ******************************************************************************* 1359 * 1360 * Gets a list of multipath logical units associated with the specific target 1361 * port group. 1362 * 1363 * @param oid 1364 * The object ID of the target port group. 1365 * 1366 * @param ppList 1367 * A pointer to a pointer to an MP_OID_LIST structure. 1368 * On a successful return, this will contain a pointer to 1369 * an MP_OID_LIST that contains the object IDs of all the multipath 1370 * logical units associated with the specified target port group. 1371 * 1372 * @return An MP_STATUS indicating if the operation was successful or if 1373 * an error occurred. 1374 * 1375 * @retval MP_STATUS_SUCCESS 1376 * Returned when the operation is successful. 1377 * 1378 * @retval MP_STATUS_INVALID_PARAMETER 1379 * Returned if ppList pointer passed as placeholder for holding 1380 * the multipath logical unit list is found to be invalid. 1381 * 1382 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1383 * Returned if oid does not specify any valid object type. 1384 * 1385 * @retval MP_STATUS_FAILED 1386 * Returned when the plugin for the specified oid is not found. 1387 * 1388 * @retval MP_STATUS_INSUFFICIENT_MEMORY 1389 * Returned when memory allocation failure occurs 1390 * 1391 ******************************************************************************* 1392 */ 1393 MP_STATUS MP_GetMPLuOidListFromTPG( 1394 MP_OID oid, 1395 MP_OID_LIST **ppList) 1396 { 1397 MP_GetMPLuOidListFromTPGFn PassFunc; 1398 MP_UINT32 index; 1399 MP_STATUS status; 1400 1401 if (ppList == NULL) 1402 return MP_STATUS_INVALID_PARAMETER; 1403 1404 if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT_GROUP, 1405 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1406 return (status); 1407 } 1408 1409 (void) pthread_mutex_lock(&mp_lib_mutex); 1410 1411 index = oid.ownerId - 1; 1412 if (plugintable[index].hdlPlugin != NULL) { 1413 PassFunc = (MP_GetMPLuOidListFromTPGFn) 1414 dlsym(plugintable[index].hdlPlugin, 1415 "MP_GetMPLuOidListFromTPG"); 1416 1417 if (PassFunc != NULL) { 1418 status = PassFunc(oid, ppList); 1419 } else { 1420 status = MP_STATUS_UNSUPPORTED; 1421 } 1422 } else { 1423 status = MP_STATUS_FAILED; 1424 } 1425 1426 (void) pthread_mutex_unlock(&mp_lib_mutex); 1427 return (status); 1428 } 1429 1430 /** 1431 ******************************************************************************* 1432 * 1433 * Gets a list of the object IDs of all the proprietary load balance 1434 * algorithms associated with this plugin. 1435 * 1436 * @param oid 1437 * The object ID of the plugin. 1438 * 1439 * @param ppList 1440 * A pointer to a pointer to an MP_OID_LIST structure. 1441 * On a successful return, this will contain a pointer to 1442 * an MP_OID_LIST that contains the object IDs of all the proprietary 1443 * load balance algorithms associated with the specified plugin. 1444 * 1445 * @return An MP_STATUS indicating if the operation was successful or if 1446 * an error occurred. 1447 * 1448 * @retval MP_STATUS_SUCCESS 1449 * Returned when the operation is successful. 1450 * 1451 * @retval MP_STATUS_INVALID_PARAMETER 1452 * Returned if ppList pointer passed as placeholder for holding 1453 * the proprietary load balance oid list is found to be invalid. 1454 * 1455 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1456 * Returned if oid does not specify any valid object type. 1457 * 1458 * @retval MP_STATUS_FAILED 1459 * Returned when the plugin for the specified oid is not found. 1460 * 1461 * @retval MP_STATUS_INSUFFICIENT_MEMORY 1462 * Returned when memory allocation failure occurs 1463 * 1464 * @retval MP_STATUS_UNSUPPORTED 1465 * Returned when the API is not supported. 1466 * 1467 ******************************************************************************* 1468 */ 1469 MP_STATUS MP_GetProprietaryLoadBalanceOidList( 1470 MP_OID oid, 1471 MP_OID_LIST **ppList) 1472 { 1473 MP_GetProprietaryLoadBalanceOidListPluginFn PassFunc; 1474 MP_UINT32 index; 1475 MP_STATUS status; 1476 1477 if (ppList == NULL) 1478 return MP_STATUS_INVALID_PARAMETER; 1479 1480 if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 1481 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1482 return (status); 1483 } 1484 1485 (void) pthread_mutex_lock(&mp_lib_mutex); 1486 1487 index = oid.ownerId - 1; 1488 if (plugintable[index].hdlPlugin != NULL) { 1489 PassFunc = (MP_GetProprietaryLoadBalanceOidListPluginFn) 1490 dlsym(plugintable[index].hdlPlugin, 1491 "MP_GetProprietaryLoadBalanceOidListPlugin"); 1492 1493 if (PassFunc != NULL) { 1494 status = PassFunc(ppList); 1495 } else { 1496 status = MP_STATUS_UNSUPPORTED; 1497 } 1498 } else { 1499 status = MP_STATUS_FAILED; 1500 } 1501 1502 (void) pthread_mutex_unlock(&mp_lib_mutex); 1503 return (status); 1504 } 1505 1506 /** 1507 ******************************************************************************* 1508 * 1509 * Gets the properties of the specified load balance properties structure. 1510 * 1511 * @param oid 1512 * The object ID of the load balance properties structure. 1513 * 1514 * @param pProps 1515 * A pointer to an MP_LOAD_BALANCE_PROPRIETARY_TYPE structure 1516 * allocated by the caller. On successful return, this structure 1517 * will contain the properties of the proprietary load balance algorithm 1518 * specified by oid. 1519 * 1520 * @return An MP_STATUS indicating if the operation was successful or if 1521 * an error occurred. 1522 * 1523 * @retval MP_STATUS_SUCCESS 1524 * Returned when the operation is successful. 1525 * 1526 * @retval MP_STATUS_INVALID_PARAMETER 1527 * Returned if pProps is NULL or specifies a memory area to 1528 * which data cannot be written. 1529 * 1530 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1531 * Returned if oid does not specify any valid object type. 1532 * 1533 * @retval MP_STATUS_OBJECT_NOT_FOUND 1534 * Returned if oid has an owner that is not currently known to 1535 * the system. 1536 * 1537 ******************************************************************************* 1538 */ 1539 MP_STATUS MP_GetProprietaryLoadBalanceProperties ( 1540 MP_OID oid, 1541 MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES *pProps) 1542 { 1543 MP_GetProprietaryLoadBalancePropertiesFn PassFunc; 1544 MP_UINT32 index; 1545 MP_STATUS status; 1546 1547 if (pProps == NULL) 1548 return MP_STATUS_INVALID_PARAMETER; 1549 1550 if ((status = validate_object(oid, MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE, 1551 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1552 return (status); 1553 } 1554 1555 (void) pthread_mutex_lock(&mp_lib_mutex); 1556 1557 index = oid.ownerId - 1; 1558 if (plugintable[index].hdlPlugin != NULL) { 1559 PassFunc = (MP_GetProprietaryLoadBalancePropertiesFn) 1560 dlsym(plugintable[index].hdlPlugin, 1561 "MP_GetProprietaryLoadBalanceProperties"); 1562 1563 if (PassFunc != NULL) { 1564 status = PassFunc(oid, pProps); 1565 } else { 1566 status = MP_STATUS_UNSUPPORTED; 1567 } 1568 } else { 1569 status = MP_STATUS_FAILED; 1570 } 1571 1572 (void) pthread_mutex_unlock(&mp_lib_mutex); 1573 return (status); 1574 } 1575 1576 /** 1577 ******************************************************************************* 1578 * 1579 * Gets a list of the object IDs of the target ports in the specified target 1580 * port group. 1581 * 1582 * @param oid 1583 * The object ID of the target port group. 1584 * 1585 * @param ppList 1586 * A pointer to a pointer to an MP_OID_LIST structure. 1587 * On a successful return, this will contain a pointer to 1588 * an MP_OID_LIST that contains the object IDs of all the target ports 1589 * associated with the specified target port group. 1590 * 1591 * @return An MP_STATUS indicating if the operation was successful or if 1592 * an error occurred. 1593 * 1594 * @retval MP_STATUS_SUCCESS 1595 * Returned when the operation is successful. 1596 * 1597 * @retval MP_STATUS_INVALID_PARAMETER 1598 * Returned if ppList pointer passed as placeholder for holding 1599 * the multipath logical unit list is found to be invalid. 1600 * 1601 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1602 * Returned if oid does not specify any valid object type. 1603 * 1604 * @retval MP_STATUS_FAILED 1605 * Returned when the plugin for the specified oid is not found. 1606 * 1607 * @retval MP_STATUS_INSUFFICIENT_MEMORY 1608 * Returned when memory allocation failure occurs 1609 * 1610 ******************************************************************************* 1611 */ 1612 MP_STATUS MP_GetTargetPortOidList( 1613 MP_OID oid, 1614 MP_OID_LIST **ppList) 1615 { 1616 MP_GetTargetPortOidListFn PassFunc; 1617 MP_UINT32 index; 1618 MP_STATUS status; 1619 1620 if (ppList == NULL) 1621 return MP_STATUS_INVALID_PARAMETER; 1622 1623 if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT_GROUP, 1624 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1625 return (status); 1626 } 1627 1628 (void) pthread_mutex_lock(&mp_lib_mutex); 1629 1630 index = oid.ownerId - 1; 1631 if (plugintable[index].hdlPlugin != NULL) { 1632 PassFunc = (MP_GetTargetPortOidListFn) 1633 dlsym(plugintable[index].hdlPlugin, 1634 "MP_GetTargetPortOidList"); 1635 1636 if (PassFunc != NULL) { 1637 status = PassFunc(oid, ppList); 1638 } else { 1639 status = MP_STATUS_UNSUPPORTED; 1640 } 1641 } else { 1642 status = MP_STATUS_FAILED; 1643 } 1644 1645 (void) pthread_mutex_unlock(&mp_lib_mutex); 1646 return (status); 1647 } 1648 1649 /** 1650 ******************************************************************************* 1651 * 1652 * Gets the properties of the specified target port. 1653 * 1654 * @param oid 1655 * The object ID of the target port. 1656 * 1657 * @param pProps 1658 * A pointer to an MP_TARGET_PORT_PROPERTIES structure 1659 * allocated by the caller. On successful return, this structure 1660 * will contain the properties of the port specified by oid. 1661 * 1662 * @return An MP_STATUS indicating if the operation was successful or if 1663 * an error occurred. 1664 * 1665 * @retval MP_STATUS_SUCCESS 1666 * Returned when the operation is successful. 1667 * 1668 * @retval MP_STATUS_INVALID_PARAMETER 1669 * Returned if pProps is NULL or specifies a memory area to 1670 * which data cannot be written. 1671 * 1672 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1673 * Returned if oid does not specify any valid object type. 1674 * 1675 * @retval MP_STATUS_OBJECT_NOT_FOUND 1676 * Returned if oid has an owner that is not currently known to 1677 * the system. 1678 * 1679 ******************************************************************************* 1680 */ 1681 MP_STATUS MP_GetTargetPortProperties( 1682 MP_OID oid, 1683 MP_TARGET_PORT_PROPERTIES *pProps) 1684 { 1685 MP_GetTargetPortPropertiesFn PassFunc; 1686 MP_UINT32 index; 1687 MP_STATUS status; 1688 1689 if (pProps == NULL) 1690 return MP_STATUS_INVALID_PARAMETER; 1691 1692 if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT, 1693 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1694 return (status); 1695 } 1696 1697 (void) pthread_mutex_lock(&mp_lib_mutex); 1698 1699 index = oid.ownerId - 1; 1700 if (plugintable[index].hdlPlugin != NULL) { 1701 PassFunc = (MP_GetTargetPortPropertiesFn) 1702 dlsym(plugintable[index].hdlPlugin, 1703 "MP_GetTargetPortProperties"); 1704 1705 if (PassFunc != NULL) { 1706 status = PassFunc(oid, pProps); 1707 } else { 1708 status = MP_STATUS_UNSUPPORTED; 1709 } 1710 } else { 1711 status = MP_STATUS_FAILED; 1712 } 1713 1714 (void) pthread_mutex_unlock(&mp_lib_mutex); 1715 return (status); 1716 } 1717 1718 1719 /** 1720 ******************************************************************************* 1721 * 1722 * Assign a multipath logical unit to a target port group. 1723 * 1724 * @param tpgOid 1725 * An MP_TARGET_PORT_GROUP oid. The target port group currently in 1726 * active access state that the administrator would like the LU 1727 * assigned to. 1728 * 1729 * @param luOid 1730 * An MP_MULTIPATH_LOGICAL_UNIT oid. 1731 * 1732 * @return An MP_STATUS indicating if the operation was successful or if 1733 * an error occurred. 1734 * 1735 * @retval MP_STATUS_SUCCESS 1736 * Returned when the operation is successful. 1737 * 1738 * @retval MP_STATUS_INVALID_PARAMETER 1739 * Returned when luOid is not associated with tpgOid. 1740 * 1741 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1742 * Returned if oid does not specify any valid object type. 1743 * 1744 * @retval MP_STATUS_OBJECT_NOT_FOUND 1745 * Returned if oid has an owner that is not currently known to 1746 * the system. 1747 * 1748 ******************************************************************************* 1749 */ 1750 MP_STATUS MP_AssignLogicalUnitToTPG( 1751 MP_OID tpgOid, 1752 MP_OID luOid) 1753 { 1754 MP_AssignLogicalUnitToTPGFn PassFunc; 1755 MP_UINT32 index; 1756 MP_STATUS status; 1757 1758 if (luOid.ownerId != tpgOid.ownerId) { 1759 return (MP_STATUS_INVALID_PARAMETER); 1760 } 1761 1762 if ((status = validate_object(tpgOid, MP_OBJECT_TYPE_TARGET_PORT_GROUP, 1763 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1764 return (status); 1765 } 1766 1767 if ((status = validate_object(luOid, MP_OBJECT_TYPE_MULTIPATH_LU, 1768 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1769 return (status); 1770 } 1771 1772 (void) pthread_mutex_lock(&mp_lib_mutex); 1773 1774 index = tpgOid.ownerId - 1; 1775 if (plugintable[index].hdlPlugin != NULL) { 1776 PassFunc = (MP_AssignLogicalUnitToTPGFn) 1777 dlsym(plugintable[index].hdlPlugin, 1778 "MP_AssignLogicalUnitToTPG"); 1779 1780 if (PassFunc != NULL) { 1781 status = PassFunc(tpgOid, luOid); 1782 } else { 1783 status = MP_STATUS_UNSUPPORTED; 1784 } 1785 } else { 1786 status = MP_STATUS_FAILED; 1787 } 1788 1789 (void) pthread_mutex_unlock(&mp_lib_mutex); 1790 return (status); 1791 } 1792 1793 /** 1794 ******************************************************************************* 1795 * 1796 * Manually override the path for a logical unit. The path exclusively used to 1797 * access the logical unit until cleared. 1798 * 1799 * @param logicalUnitOid 1800 * The object ID of the multipath logical unit. 1801 * 1802 * @param pathOid 1803 * The object ID of the path logical unit. 1804 * 1805 * @return An MP_STATUS indicating if the operation was successful or if 1806 * an error occurred. 1807 * 1808 * @retval MP_STATUS_SUCCESS 1809 * Returned when the operation is successful. 1810 * 1811 * @retval MP_STATUS_INVALID_PARAMETER 1812 * Returned if the oid of the object is not valid 1813 * 1814 * @retval MP_STATUS_UNSUPPORTED 1815 * Returned when the implementation does not support the API 1816 * 1817 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1818 * Returned if oid does not specify any valid object type. 1819 * 1820 * @retval MP_STATUS_PATH_NONOPERATIONAL 1821 * Returned when the driver cannot communicate through selected path. 1822 * 1823 ******************************************************************************* 1824 */ 1825 MP_STATUS MP_SetOverridePath( 1826 MP_OID logicalUnitOid, 1827 MP_OID pathOid) 1828 { 1829 MP_SetOverridePathFn PassFunc; 1830 MP_UINT32 index; 1831 MP_STATUS status; 1832 1833 if ((status = validate_object(logicalUnitOid, MP_OBJECT_TYPE_MULTIPATH_LU, 1834 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1835 return (status); 1836 } 1837 if ((status = validate_object(pathOid, MP_OBJECT_TYPE_PATH_LU, 1838 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1839 return (status); 1840 } 1841 1842 (void) pthread_mutex_lock(&mp_lib_mutex); 1843 1844 index = pathOid.ownerId - 1; 1845 if (plugintable[index].hdlPlugin != NULL) { 1846 PassFunc = (MP_SetOverridePathFn) 1847 dlsym(plugintable[index].hdlPlugin, 1848 "MP_SetOverridePath"); 1849 1850 if (PassFunc != NULL) { 1851 status = PassFunc(logicalUnitOid, pathOid); 1852 } else { 1853 status = MP_STATUS_UNSUPPORTED; 1854 } 1855 } else { 1856 status = MP_STATUS_FAILED; 1857 } 1858 1859 (void) pthread_mutex_unlock(&mp_lib_mutex); 1860 return (status); 1861 } 1862 1863 /** 1864 ******************************************************************************* 1865 * 1866 * Cancel a path override and re-enable load balancing. 1867 * 1868 * @param luOid 1869 * An MP_MULTIPATH_LOGICAL_UNIT oid. 1870 * 1871 * @return An MP_STATUS indicating if the operation was successful or if 1872 * an error occurred. 1873 * 1874 * @retval MP_STATUS_SUCCESS 1875 * Returned when the operation is successful. 1876 * 1877 * @retval MP_STATUS_INVALID_PARAMETER 1878 * Returned if MP_MULTIPATH_LOGICAL_UNIT with the luOid is not found. 1879 * 1880 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1881 * Returned if oid does not specify any valid object type. 1882 * 1883 * @retval MP_STATUS_OBJECT_NOT_FOUND 1884 * Returned if oid has an owner that is not currently known to 1885 * the system. 1886 * 1887 ******************************************************************************* 1888 */ 1889 MP_STATUS MP_CancelOverridePath( 1890 MP_OID luOid) 1891 { 1892 MP_CancelOverridePathFn PassFunc; 1893 MP_UINT32 index; 1894 MP_STATUS status; 1895 1896 if ((status = validate_object(luOid, MP_OBJECT_TYPE_MULTIPATH_LU, 1897 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 1898 return (status); 1899 } 1900 1901 (void) pthread_mutex_lock(&mp_lib_mutex); 1902 1903 index = luOid.ownerId - 1; 1904 if (plugintable[index].hdlPlugin != NULL) { 1905 PassFunc = (MP_CancelOverridePathFn) 1906 dlsym(plugintable[index].hdlPlugin, 1907 "MP_CancelOverridePath"); 1908 1909 if (PassFunc != NULL) { 1910 status = PassFunc(luOid); 1911 } else { 1912 status = MP_STATUS_UNSUPPORTED; 1913 } 1914 } else { 1915 status = MP_STATUS_FAILED; 1916 } 1917 1918 (void) pthread_mutex_unlock(&mp_lib_mutex); 1919 return (status); 1920 } 1921 1922 /** 1923 ******************************************************************************* 1924 * 1925 * Enables Auto-failback. 1926 * 1927 * @param oid 1928 * The oid of the plugin. 1929 * 1930 * @return An MP_STATUS indicating if the operation was successful or if 1931 * an error occurred. 1932 * 1933 * @retval MP_STATUS_SUCCESS 1934 * Returned when the operation is successful. 1935 * 1936 * @retval MP_STATUS_INVALID_PARAMETER 1937 * Returned if oid is NULL or specifies a memory area that is not 1938 * a valid plugin oid. 1939 * 1940 * @retval MP_STATUS_INVALID_OBJECT_TYPE 1941 * Returned if oid does not specify any valid object type. 1942 * 1943 ******************************************************************************* 1944 */ 1945 MP_STATUS MP_EnableAutoFailback( 1946 MP_OID oid) 1947 { 1948 MP_UINT32 index; 1949 MP_STATUS status; 1950 1951 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 1952 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 1953 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 1954 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 1955 return (status); 1956 } 1957 1958 (void) pthread_mutex_lock(&mp_lib_mutex); 1959 1960 index = oid.ownerId - 1; 1961 if (plugintable[index].hdlPlugin != NULL) { 1962 if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) { 1963 MP_EnableAutoFailbackPluginFn PassFunc; 1964 PassFunc = (MP_EnableAutoFailbackPluginFn) 1965 dlsym(plugintable[index].hdlPlugin, 1966 "MP_EnableAutoFailbackPlugin"); 1967 1968 if (PassFunc != NULL) { 1969 status = PassFunc(); 1970 } else { 1971 status = MP_STATUS_UNSUPPORTED; 1972 } 1973 } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) { 1974 MP_EnableAutoFailbackLuFn PassFunc; 1975 PassFunc = (MP_EnableAutoFailbackLuFn) 1976 dlsym(plugintable[index].hdlPlugin, 1977 "MP_EnableAutoFailbackLu"); 1978 1979 if (PassFunc != NULL) { 1980 status = PassFunc(oid); 1981 } else { 1982 status = MP_STATUS_UNSUPPORTED; 1983 } 1984 } else { 1985 status = MP_STATUS_INVALID_PARAMETER; 1986 } 1987 } 1988 1989 (void) pthread_mutex_unlock(&mp_lib_mutex); 1990 return (status); 1991 } 1992 1993 /** 1994 ******************************************************************************* 1995 * 1996 * Enables Auto-probing. 1997 * 1998 * @param oid 1999 * The oid of the plugin or the multipath logical unit. 2000 * 2001 * @return An MP_STATUS indicating if the operation was successful or if 2002 * an error occurred. 2003 * 2004 * @retval MP_STATUS_SUCCESS 2005 * Returned when the operation is successful. 2006 * 2007 * @retval MP_STATUS_INVALID_PARAMETER 2008 * Returned if oid is NULL or specifies a memory area that is not 2009 * a valid plugin oid. 2010 * 2011 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2012 * Returned if oid does not specify any valid object type. 2013 * 2014 ******************************************************************************* 2015 */ 2016 MP_STATUS MP_EnableAutoProbing( 2017 MP_OID oid) 2018 { 2019 MP_UINT32 index; 2020 MP_STATUS status; 2021 2022 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 2023 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 2024 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 2025 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 2026 return (status); 2027 } 2028 2029 (void) pthread_mutex_lock(&mp_lib_mutex); 2030 2031 index = oid.ownerId - 1; 2032 if (plugintable[index].hdlPlugin != NULL) { 2033 if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) { 2034 MP_EnableAutoProbingPluginFn PassFunc; 2035 PassFunc = (MP_EnableAutoProbingPluginFn) 2036 dlsym(plugintable[index].hdlPlugin, 2037 "MP_EnableAutoProbingPlugin"); 2038 2039 if (PassFunc != NULL) { 2040 status = PassFunc(); 2041 } else { 2042 status = MP_STATUS_UNSUPPORTED; 2043 } 2044 } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) { 2045 MP_EnableAutoProbingLuFn PassFunc; 2046 PassFunc = (MP_EnableAutoProbingLuFn) 2047 dlsym(plugintable[index].hdlPlugin, 2048 "MP_EnableAutoProbingLu"); 2049 2050 if (PassFunc != NULL) { 2051 status = PassFunc(oid); 2052 } else { 2053 status = MP_STATUS_UNSUPPORTED; 2054 } 2055 } else { 2056 status = MP_STATUS_INVALID_PARAMETER; 2057 } 2058 } 2059 2060 (void) pthread_mutex_unlock(&mp_lib_mutex); 2061 return (status); 2062 } 2063 2064 /** 2065 ******************************************************************************* 2066 * 2067 * Disables Auto-failback. 2068 * 2069 * @param oid 2070 * The oid of the plugin. 2071 * 2072 * @return An MP_STATUS indicating if the operation was successful or if 2073 * an error occurred. 2074 * 2075 * @retval MP_STATUS_SUCCESS 2076 * Returned when the operation is successful. 2077 * 2078 * @retval MP_STATUS_INVALID_PARAMETER 2079 * Returned if oid is NULL or specifies a memory area that is not 2080 * a valid plugin oid. 2081 * 2082 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2083 * Returned if oid does not specify any valid object type. 2084 * 2085 ******************************************************************************* 2086 */ 2087 MP_STATUS MP_DisableAutoFailback( 2088 MP_OID oid) 2089 { 2090 MP_UINT32 index; 2091 MP_STATUS status; 2092 2093 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 2094 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 2095 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 2096 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 2097 return (status); 2098 } 2099 2100 (void) pthread_mutex_lock(&mp_lib_mutex); 2101 2102 index = oid.ownerId - 1; 2103 if (plugintable[index].hdlPlugin != NULL) { 2104 if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) { 2105 MP_DisableAutoFailbackPluginFn PassFunc; 2106 PassFunc = (MP_DisableAutoFailbackPluginFn) 2107 dlsym(plugintable[index].hdlPlugin, 2108 "MP_DisableAutoFailbackPlugin"); 2109 2110 if (PassFunc != NULL) { 2111 status = PassFunc(); 2112 } else { 2113 status = MP_STATUS_UNSUPPORTED; 2114 } 2115 } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) { 2116 MP_DisableAutoFailbackLuFn PassFunc; 2117 PassFunc = (MP_DisableAutoFailbackLuFn) 2118 dlsym(plugintable[index].hdlPlugin, 2119 "MP_DisableAutoFailbackLu"); 2120 2121 if (PassFunc != NULL) { 2122 status = PassFunc(oid); 2123 } else { 2124 status = MP_STATUS_UNSUPPORTED; 2125 } 2126 } else { 2127 status = MP_STATUS_INVALID_PARAMETER; 2128 } 2129 } 2130 2131 (void) pthread_mutex_unlock(&mp_lib_mutex); 2132 return (status); 2133 } 2134 2135 /** 2136 ******************************************************************************* 2137 * 2138 * Disables Auto-probing. 2139 * 2140 * @param oid 2141 * The oid of the plugin or the multipath logical unit. 2142 * 2143 * @return An MP_STATUS indicating if the operation was successful or if 2144 * an error occurred. 2145 * 2146 * @retval MP_STATUS_SUCCESS 2147 * Returned when the operation is successful. 2148 * 2149 * @retval MP_STATUS_INVALID_PARAMETER 2150 * Returned if oid is NULL or specifies a memory area that is not 2151 * a valid plugin oid. 2152 * 2153 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2154 * Returned if oid does not specify any valid object type. 2155 * 2156 ******************************************************************************* 2157 */ 2158 MP_STATUS MP_DisableAutoProbing( 2159 MP_OID oid) 2160 { 2161 MP_UINT32 index; 2162 MP_STATUS status; 2163 2164 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 2165 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 2166 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 2167 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 2168 return (status); 2169 } 2170 2171 (void) pthread_mutex_lock(&mp_lib_mutex); 2172 2173 index = oid.ownerId - 1; 2174 if (plugintable[index].hdlPlugin != NULL) { 2175 if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) { 2176 MP_DisableAutoProbingPluginFn PassFunc; 2177 PassFunc = (MP_DisableAutoProbingPluginFn) 2178 dlsym(plugintable[index].hdlPlugin, 2179 "MP_DisableAutoProbingPlugin"); 2180 2181 if (PassFunc != NULL) { 2182 status = PassFunc(); 2183 } else { 2184 status = MP_STATUS_UNSUPPORTED; 2185 } 2186 } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) { 2187 MP_DisableAutoFailbackLuFn PassFunc; 2188 PassFunc = (MP_DisableAutoProbingLuFn) 2189 dlsym(plugintable[index].hdlPlugin, 2190 "MP_DisableAutoProbingLu"); 2191 2192 if (PassFunc != NULL) { 2193 status = PassFunc(oid); 2194 } else { 2195 status = MP_STATUS_UNSUPPORTED; 2196 } 2197 } else { 2198 status = MP_STATUS_INVALID_PARAMETER; 2199 } 2200 } 2201 2202 (void) pthread_mutex_unlock(&mp_lib_mutex); 2203 return (status); 2204 } 2205 2206 /** 2207 ******************************************************************************* 2208 * 2209 * Enables a path. This API may cause failover in a logical unit with 2210 * asymmetric access. 2211 * 2212 * @param oid 2213 * The oid of the path. 2214 * 2215 * @return An MP_STATUS indicating if the operation was successful or if 2216 * an error occurred. 2217 * 2218 * @retval MP_STATUS_SUCCESS 2219 * Returned when the operation is successful. 2220 * 2221 * @retval MP_STATUS_INVALID_PARAMETER 2222 * Returned if oid is NULL or specifies a memory area that is not 2223 * a valid path oid. 2224 * 2225 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2226 * Returned if oid does not specify any valid object type. 2227 * 2228 ******************************************************************************* 2229 */ 2230 MP_STATUS MP_EnablePath( 2231 MP_OID oid) 2232 { 2233 MP_EnablePathFn PassFunc; 2234 MP_UINT32 index; 2235 MP_STATUS status; 2236 2237 if ((status = validate_object(oid, MP_OBJECT_TYPE_PATH_LU, 2238 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 2239 return (status); 2240 } 2241 2242 (void) pthread_mutex_lock(&mp_lib_mutex); 2243 2244 index = oid.ownerId - 1; 2245 if (plugintable[index].hdlPlugin != NULL) { 2246 PassFunc = (MP_EnablePathFn) 2247 dlsym(plugintable[index].hdlPlugin, 2248 "MP_EnablePath"); 2249 2250 if (PassFunc != NULL) { 2251 status = PassFunc(oid); 2252 } else { 2253 status = MP_STATUS_UNSUPPORTED; 2254 } 2255 } else { 2256 status = MP_STATUS_FAILED; 2257 } 2258 2259 (void) pthread_mutex_unlock(&mp_lib_mutex); 2260 return (status); 2261 } 2262 2263 /** 2264 ******************************************************************************* 2265 * 2266 * Disables a path. This API may cause failover in a logical unit with 2267 * asymmetric access. This API may cause a logical unit to become unavailable. 2268 * 2269 * @param oid 2270 * The oid of the path. 2271 * 2272 * @return An MP_STATUS indicating if the operation was successful or if 2273 * an error occurred. 2274 * 2275 * @retval MP_STATUS_SUCCESS 2276 * Returned when the operation is successful. 2277 * 2278 * @retval MP_STATUS_INVALID_PARAMETER 2279 * Returned if oid is NULL or specifies a memory area that is not 2280 * a valid path oid. 2281 * 2282 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2283 * Returned if oid does not specify any valid object type. 2284 * 2285 ******************************************************************************* 2286 */ 2287 MP_STATUS MP_DisablePath( 2288 MP_OID oid) 2289 { 2290 MP_DisablePathFn PassFunc; 2291 MP_UINT32 index; 2292 MP_STATUS status; 2293 2294 if ((status = validate_object(oid, MP_OBJECT_TYPE_PATH_LU, 2295 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 2296 return (status); 2297 } 2298 2299 (void) pthread_mutex_lock(&mp_lib_mutex); 2300 2301 index = oid.ownerId - 1; 2302 if (plugintable[index].hdlPlugin != NULL) { 2303 PassFunc = (MP_DisablePathFn) 2304 dlsym(plugintable[index].hdlPlugin, 2305 "MP_DisablePath"); 2306 2307 if (PassFunc != NULL) { 2308 status = PassFunc(oid); 2309 } else { 2310 status = MP_STATUS_UNSUPPORTED; 2311 } 2312 } else { 2313 status = MP_STATUS_FAILED; 2314 } 2315 2316 (void) pthread_mutex_unlock(&mp_lib_mutex); 2317 return (status); 2318 } 2319 2320 /** 2321 ******************************************************************************* 2322 * 2323 * Set the multipath logical unit s load balancing policy. 2324 * 2325 * @param logicalUnitoid 2326 * The object ID of the multipath logical unit. 2327 * 2328 * @param loadBanlance 2329 * The desired load balance policy for the specified logical unit. 2330 * 2331 * @return An MP_STATUS indicating if the operation was successful or if 2332 * an error occurred. 2333 * 2334 * @retval MP_STATUS_SUCCESS 2335 * Returned when the operation is successful. 2336 * 2337 * @retval MP_STATUS_INVALID_PARAMETER 2338 * Returned if no MP_MULTIPATH_LOGICAL_UNIT associated with 2339 * @ref ligicalUnitrOid is found or invalid MP_LOAD_BALANCE_TYPE is 2340 * specified. 2341 * 2342 * @retval MP_STATUS_FAILED 2343 * Returned when the specified loadBalance type cannot be handled 2344 * by the plugin. 2345 * 2346 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2347 * Returned if oid does not specify any valid object type. 2348 * 2349 ******************************************************************************* 2350 */ 2351 MP_STATUS MP_SetLogicalUnitLoadBalanceType( 2352 MP_OID logicalUnitOid, 2353 MP_LOAD_BALANCE_TYPE loadBalance) 2354 { 2355 MP_SetLogicalUnitLoadBalanceTypeFn PassFunc; 2356 MP_UINT32 index; 2357 MP_STATUS status; 2358 2359 if ((status = validate_object(logicalUnitOid, 2360 MP_OBJECT_TYPE_MULTIPATH_LU, 2361 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 2362 return (status); 2363 } 2364 2365 (void) pthread_mutex_lock(&mp_lib_mutex); 2366 2367 index = logicalUnitOid.ownerId - 1; 2368 if (plugintable[index].hdlPlugin != NULL) { 2369 PassFunc = (MP_SetLogicalUnitLoadBalanceTypeFn) 2370 dlsym(plugintable[index].hdlPlugin, 2371 "MP_SetLogicalUnitLoadBalanceType"); 2372 2373 if (PassFunc != NULL) { 2374 status = PassFunc(logicalUnitOid, loadBalance); 2375 } else { 2376 status = MP_STATUS_UNSUPPORTED; 2377 } 2378 } else { 2379 status = MP_STATUS_FAILED; 2380 } 2381 2382 (void) pthread_mutex_unlock(&mp_lib_mutex); 2383 return (status); 2384 } 2385 2386 /** 2387 ******************************************************************************* 2388 * 2389 * Set the weight to be assigned to a particular path. 2390 * 2391 * @param pathOid 2392 * The object ID of the path logical unit. 2393 * 2394 * @param weight 2395 * weight that will be assigned to the path logical unit. 2396 * 2397 * @return An MP_STATUS indicating if the operation was successful or if 2398 * an error occurred. 2399 * 2400 * @retval MP_STATUS_SUCCESS 2401 * Returned when the operation is successful. 2402 * 2403 * @retval MP_STATUS_OBJECT_NOT_FOUND 2404 * Returned when the MP Path specified by the PathOid could not be 2405 * found. 2406 * 2407 * @retval MP_STATUS_UNSUPPORTED 2408 * Returned when the implementation does not support the API 2409 * 2410 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2411 * Returned if oid does not specify any valid object type. 2412 * 2413 * @retval MP_STATUS_FAILED 2414 * Returned when the operation failed. 2415 * 2416 * @retval MP_STATUS_PATH_NONOPERATIONAL 2417 * Returned when the driver cannot communicate through selected path. 2418 * 2419 * @retval MP_STATUS_INVALID_WEIGHT 2420 * Returned when the weight parameter is greater than the plugin's 2421 * maxWeight property. 2422 * 2423 ******************************************************************************* 2424 */ 2425 MP_STATUS MP_SetPathWeight( 2426 MP_OID pathOid, 2427 MP_UINT32 weight) 2428 { 2429 MP_SetPathWeightFn PassFunc; 2430 MP_UINT32 index; 2431 MP_STATUS status; 2432 2433 if ((status = validate_object(pathOid, MP_OBJECT_TYPE_PATH_LU, 2434 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 2435 return (status); 2436 } 2437 2438 (void) pthread_mutex_lock(&mp_lib_mutex); 2439 2440 index = pathOid.ownerId - 1; 2441 if (plugintable[index].hdlPlugin != NULL) { 2442 PassFunc = (MP_SetPathWeightFn) 2443 dlsym(plugintable[index].hdlPlugin, 2444 "MP_SetPathWeight"); 2445 2446 if (PassFunc != NULL) { 2447 status = PassFunc(pathOid, weight); 2448 } else { 2449 status = MP_STATUS_UNSUPPORTED; 2450 } 2451 } else { 2452 status = MP_STATUS_FAILED; 2453 } 2454 2455 (void) pthread_mutex_unlock(&mp_lib_mutex); 2456 return (status); 2457 } 2458 2459 /** 2460 ******************************************************************************* 2461 * 2462 * Set the default load balance policy for the plugin. 2463 * 2464 * @param oid 2465 * The object ID of the plugin 2466 * 2467 * @param loadBalance 2468 * The desired default load balance policy for the specified plugin. 2469 * 2470 * @return An MP_STATUS indicating if the operation was successful or if 2471 * an error occurred. 2472 * 2473 * @retval MP_STATUS_SUCCESS 2474 * Returned when the operation is successful. 2475 * 2476 * @retval MP_STATUS_OBJECT_NOT_FOUND 2477 * Returned when the the plugin specified by @ref oid could not be 2478 * found. 2479 * 2480 * @retval MP_STATUS_INVALID_PARAMETER 2481 * Returned if the oid of the object is not valid. 2482 * 2483 * @retval MP_STATUS_UNSUPPORTED 2484 * Returned when the implementation does not support the API 2485 * 2486 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2487 * Returned if oid does not specify any valid object type. 2488 * 2489 * @retval MP_STATUS_FAILED 2490 * Returned when the specified loadBalance type cannot be handled 2491 * by the plugin. 2492 * 2493 ******************************************************************************* 2494 */ 2495 MP_STATUS MP_SetPluginLoadBalanceType( 2496 MP_OID oid, 2497 MP_LOAD_BALANCE_TYPE loadBalance) 2498 { 2499 MP_SetPluginLoadBalanceTypePluginFn PassFunc; 2500 MP_UINT32 index; 2501 MP_STATUS status; 2502 2503 if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 2504 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 2505 return (status); 2506 } 2507 2508 (void) pthread_mutex_lock(&mp_lib_mutex); 2509 2510 index = oid.ownerId - 1; 2511 if (plugintable[index].hdlPlugin != NULL) { 2512 PassFunc = (MP_SetPluginLoadBalanceTypePluginFn) 2513 dlsym(plugintable[index].hdlPlugin, 2514 "MP_SetPluginLoadBalanceTypePlugin"); 2515 2516 if (PassFunc != NULL) { 2517 status = PassFunc(loadBalance); 2518 } else { 2519 status = MP_STATUS_UNSUPPORTED; 2520 } 2521 } else { 2522 status = MP_STATUS_FAILED; 2523 } 2524 2525 (void) pthread_mutex_unlock(&mp_lib_mutex); 2526 return (status); 2527 } 2528 2529 /** 2530 ******************************************************************************* 2531 * 2532 * Set the failback polling rates. Setting both rates to zero disables polling. 2533 * 2534 * @param pluginOid 2535 * The object ID of the plugin or multipath lu. 2536 * 2537 * @param pollingRate 2538 * The value to be set in MP_PLUGIN_PROPERTIES currentPollingRate.or 2539 * MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES pollingRate. 2540 * 2541 * @return An MP_STATUS indicating if the operation was successful or if 2542 * an error occurred. 2543 * 2544 * @retval MP_STATUS_SUCCESS 2545 * Returned when the operation is successful. 2546 * 2547 * @retval MP_STATUS_OBJECT_NOT_FOUND 2548 * Returned when the the plugin specified by @ref oid could not be 2549 * found. 2550 * 2551 * @retval MP_STATUS_INVALID_PARAMETER 2552 * Returned if one of the polling values is outside the range 2553 * supported by the driver. 2554 * 2555 * @retval MP_STATUS_UNSUPPORTED 2556 * Returned when the implementation does not support the API 2557 * 2558 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2559 * Returned if oid does not specify any valid object type. 2560 * 2561 ******************************************************************************* 2562 */ 2563 MP_STATUS MP_SetFailbackPollingRate( 2564 MP_OID oid, 2565 MP_UINT32 pollingRate) 2566 { 2567 MP_UINT32 index; 2568 MP_STATUS status; 2569 2570 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 2571 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 2572 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 2573 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 2574 return (status); 2575 } 2576 2577 (void) pthread_mutex_lock(&mp_lib_mutex); 2578 2579 index = oid.ownerId - 1; 2580 if (plugintable[index].hdlPlugin != NULL) { 2581 if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) { 2582 MP_SetFailbackPollingRatePluginFn PassFunc; 2583 PassFunc = (MP_SetFailbackPollingRatePluginFn) 2584 dlsym(plugintable[index].hdlPlugin, 2585 "MP_SetFailbackPollingRatePlugin"); 2586 2587 if (PassFunc != NULL) { 2588 status = PassFunc(pollingRate); 2589 } else { 2590 status = MP_STATUS_UNSUPPORTED; 2591 } 2592 } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) { 2593 MP_SetFailbackPollingRateLuFn PassFunc; 2594 PassFunc = (MP_SetFailbackPollingRateLuFn) 2595 dlsym(plugintable[index].hdlPlugin, 2596 "MP_SetFailbackPollingRateLu"); 2597 2598 if (PassFunc != NULL) { 2599 status = PassFunc(oid, pollingRate); 2600 } else { 2601 status = MP_STATUS_UNSUPPORTED; 2602 } 2603 } else { 2604 status = MP_STATUS_INVALID_PARAMETER; 2605 } 2606 } 2607 2608 (void) pthread_mutex_unlock(&mp_lib_mutex); 2609 return (status); 2610 } 2611 2612 /** 2613 ******************************************************************************* 2614 * 2615 * Set the probing polling rates. Setting both rates to zero disables polling. 2616 * 2617 * @param pluginOid 2618 * The object ID of either the plugin or a multipath logical unit. 2619 * 2620 * @param pollingRate 2621 * The value to be set in MP_PLUGIN_PROPERTIES current pollingRate or 2622 * MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES pollingRate. 2623 * 2624 * @return An MP_STATUS indicating if the operation was successful or if 2625 * an error occurred. 2626 * 2627 * @retval MP_STATUS_SUCCESS 2628 * Returned when the operation is successful. 2629 * 2630 * @retval MP_STATUS_OBJECT_NOT_FOUND 2631 * Returned when the the plugin specified by @ref oid could not be 2632 * found. 2633 * 2634 * @retval MP_STATUS_INVALID_PARAMETER 2635 * Returned if one of the polling values is outside the range 2636 * supported by the driver. 2637 * 2638 * @retval MP_STATUS_UNSUPPORTED 2639 * Returned when the implementation does not support the API 2640 * 2641 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2642 * Returned if oid does not specify any valid object type. 2643 * 2644 ******************************************************************************* 2645 */ 2646 MP_STATUS MP_SetProbingPollingRate( 2647 MP_OID oid, 2648 MP_UINT32 pollingRate) 2649 { 2650 MP_UINT32 index; 2651 MP_STATUS status; 2652 2653 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 2654 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 2655 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 2656 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 2657 return (status); 2658 } 2659 2660 (void) pthread_mutex_lock(&mp_lib_mutex); 2661 2662 index = oid.ownerId - 1; 2663 if (plugintable[index].hdlPlugin != NULL) { 2664 if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) { 2665 MP_SetProbingPollingRatePluginFn PassFunc; 2666 PassFunc = (MP_SetProbingPollingRatePluginFn) 2667 dlsym(plugintable[index].hdlPlugin, 2668 "MP_SetProbingPollingRatePlugin"); 2669 2670 if (PassFunc != NULL) { 2671 status = PassFunc(pollingRate); 2672 } else { 2673 status = MP_STATUS_UNSUPPORTED; 2674 } 2675 } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) { 2676 MP_SetProbingPollingRateLuFn PassFunc; 2677 PassFunc = (MP_SetProbingPollingRateLuFn) 2678 dlsym(plugintable[index].hdlPlugin, 2679 "MP_SetProbingPollingRateLu"); 2680 2681 if (PassFunc != NULL) { 2682 status = PassFunc(oid, pollingRate); 2683 } else { 2684 status = MP_STATUS_UNSUPPORTED; 2685 } 2686 } else { 2687 status = MP_STATUS_INVALID_PARAMETER; 2688 } 2689 } 2690 2691 (void) pthread_mutex_unlock(&mp_lib_mutex); 2692 return (status); 2693 } 2694 2695 /** 2696 ******************************************************************************* 2697 * 2698 * Set proprietary properties in supported object instances. 2699 * 2700 * @param pluginOid 2701 * The object ID of MP_LOAD_BALANCE_PROPRIETARY_TYPE, MP_PLUGIN_PROPERTIES 2702 * or MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES. 2703 * 2704 * @param count 2705 * The number of valid items in pPropertyList. 2706 * 2707 * @param pPropertyList 2708 * A pointer to an array of property name/value pairs. This array must 2709 * contain the same number of elements as count. 2710 * 2711 * @return An MP_STATUS indicating if the operation was successful or if 2712 * an error occurred. 2713 * 2714 * @retval MP_STATUS_SUCCESS 2715 * Returned when the operation is successful. 2716 * 2717 * @retval MP_STATUS_OBJECT_NOT_FOUND 2718 * Returned when the the plugin specified by @ref oid could not be 2719 * found. 2720 * 2721 * @retval MP_STATUS_INVALID_PARAMETER 2722 * Returned if one of the polling values is outside the range 2723 * supported by the driver. 2724 * 2725 * @retval MP_STATUS_UNSUPPORTED 2726 * Returned when the implementation does not support the API 2727 * 2728 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2729 * Returned if oid does not specify any valid object type. 2730 * 2731 ******************************************************************************* 2732 */ 2733 MP_STATUS MP_SetProprietaryProperties( 2734 MP_OID oid, 2735 MP_UINT32 count, 2736 MP_PROPRIETARY_PROPERTY *pPropertyList) 2737 { 2738 MP_SetProprietaryPropertiesFn PassFunc; 2739 MP_UINT32 index; 2740 MP_STATUS status; 2741 2742 if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN, 2743 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 2744 ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU, 2745 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) && 2746 ((status = validate_object(oid, MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE, 2747 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) { 2748 return (status); 2749 } 2750 2751 (void) pthread_mutex_lock(&mp_lib_mutex); 2752 2753 index = oid.ownerId - 1; 2754 if (plugintable[index].hdlPlugin != NULL) { 2755 PassFunc = (MP_SetProprietaryPropertiesFn) 2756 dlsym(plugintable[index].hdlPlugin, 2757 "MP_SetProprietaryProperties"); 2758 2759 if (PassFunc != NULL) { 2760 status = PassFunc(oid, count, pPropertyList); 2761 } else { 2762 status = MP_STATUS_UNSUPPORTED; 2763 } 2764 } else { 2765 status = MP_STATUS_FAILED; 2766 } 2767 2768 (void) pthread_mutex_unlock(&mp_lib_mutex); 2769 return (status); 2770 } 2771 2772 /** 2773 ******************************************************************************* 2774 * 2775 * Set the access state for a list of target port groups. This allows 2776 * a client to force a failover or failback to a desired set of target port 2777 * groups. 2778 * 2779 * @param luOid 2780 * The object ID of the logical unit where the command is sent. 2781 * 2782 * @param count 2783 * The number of valid items in the pTpgStateList. 2784 * 2785 * @param pTpgStateList 2786 * A pointer to an array of TPG/access-state values. This array must 2787 * contain the same number of elements as @ref count. 2788 * 2789 * @return An MP_STATUS indicating if the operation was successful or if 2790 * an error occurred. 2791 * 2792 * @retval MP_STATUS_SUCCESS 2793 * Returned when the operation is successful. 2794 * 2795 * @retval MP_STATUS_OBJECT_NOT_FOUND 2796 * Returned when the MP_MULTIPATH_LOGICAL_UNIT associated with @ref 2797 * oid could not be found. 2798 * 2799 * @retval MP_STATUS_INVALID_PARAMETER 2800 * Returned if pTpgStateList is null or if one of the TPGs referenced 2801 * in the list is not associated with the specified MP logical unit. 2802 * 2803 * @retval MP_STATUS_UNSUPPORTED 2804 * Returned when the implementation does not support the API 2805 * 2806 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2807 * Returned if oid does not specify any valid object type. 2808 * 2809 * @retval MP_STATUS_ACCESS_STATE_INVALID 2810 * Returned if the target device returns a status indicating the caller 2811 * is attempting to establish an illegal combination of access states. 2812 * 2813 * @retval MP_STATUS_FAILED 2814 * Returned if the underlying interface failed the commend for some 2815 * reason other than MP_STATUS_ACCESS_STATE_INVALID 2816 * 2817 ******************************************************************************* 2818 */ 2819 MP_STATUS MP_SetTPGAccess( 2820 MP_OID luOid, 2821 MP_UINT32 count, 2822 MP_TPG_STATE_PAIR *pTpgStateList) 2823 { 2824 MP_SetTPGAccessFn PassFunc; 2825 MP_UINT32 index; 2826 MP_STATUS status; 2827 2828 if ((status = validate_object(luOid, MP_OBJECT_TYPE_MULTIPATH_LU, 2829 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 2830 return (status); 2831 } 2832 2833 (void) pthread_mutex_lock(&mp_lib_mutex); 2834 2835 index = luOid.ownerId - 1; 2836 if (plugintable[index].hdlPlugin != NULL) { 2837 PassFunc = (MP_SetTPGAccessFn) 2838 dlsym(plugintable[index].hdlPlugin, 2839 "MP_SetTPGAccess"); 2840 2841 if (PassFunc != NULL) { 2842 status = PassFunc(luOid, count, pTpgStateList); 2843 } else { 2844 status = MP_STATUS_UNSUPPORTED; 2845 } 2846 } else { 2847 status = MP_STATUS_FAILED; 2848 } 2849 2850 (void) pthread_mutex_unlock(&mp_lib_mutex); 2851 return (status); 2852 } 2853 2854 /** 2855 ******************************************************************************* 2856 * 2857 * Registers a client function that is to be called 2858 * whenever the property of an an object changes. 2859 * 2860 * @param pClientFn, 2861 * A pointer to an MP_OBJECT_PROPERTY_FN function defined by the 2862 * client. On successful return this function will be called to 2863 * inform the client of objects that have had one or more properties 2864 * change. 2865 * 2866 * @param objectType 2867 * The type of object the client wishes to deregister for 2868 * property change callbacks. If null, then all objects types are 2869 * deregistered. 2870 * 2871 * @param pCallerData 2872 * A pointer that is passed to the callback routine with each event. 2873 * This may be used by the caller to correlate the event to source of 2874 * the registration. 2875 * 2876 * @return An MP_STATUS indicating if the operation was successful or if 2877 * an error occurred. 2878 * 2879 * @retval MP_STATUS_SUCCESS 2880 * Returned when the operation is successful. 2881 * 2882 * @retval MP_STATUS_INVALID_PARAMETER 2883 * Returned if pClientFn is NULL or specifies a memory area 2884 * that is not executable. 2885 * 2886 * @retval MP_STATUS_FN_REPLACED 2887 * Returned when an existing client function is replaced with the one 2888 * specified in pClientFn. 2889 * 2890 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2891 * Returned if oid does not specify any valid object type. 2892 * 2893 ******************************************************************************* 2894 */ 2895 MP_STATUS MP_RegisterForObjectPropertyChanges( 2896 MP_OBJECT_PROPERTY_FN pClientFn, 2897 MP_OBJECT_TYPE objectType, 2898 void *pCallerData, 2899 MP_OID pluginOid) 2900 { 2901 MP_RegisterForObjectPropertyChangesPluginFn PassFunc; 2902 MP_UINT32 i; 2903 MP_UINT32 index; 2904 MP_STATUS status; 2905 2906 if (pClientFn == NULL) { 2907 return (MP_STATUS_INVALID_PARAMETER); 2908 } 2909 2910 if (objectType > MP_OBJECT_TYPE_MAX) { 2911 return (MP_STATUS_INVALID_OBJECT_TYPE); 2912 } 2913 2914 if (!(is_zero_oid(pluginOid))) { 2915 if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN, 2916 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 2917 return (status); 2918 } 2919 } 2920 2921 (void) pthread_mutex_lock(&mp_lib_mutex); 2922 2923 if (is_zero_oid(pluginOid)) { 2924 for (i = 0; i < number_of_plugins; i++) { 2925 if (plugintable[i].hdlPlugin != NULL) { 2926 PassFunc = (MP_RegisterForObjectPropertyChangesPluginFn) 2927 dlsym(plugintable[i].hdlPlugin, 2928 "MP_RegisterForObjectPropertyChangesPlugin"); 2929 } 2930 2931 if (PassFunc != NULL) { 2932 status = 2933 PassFunc(pClientFn, objectType, pCallerData); 2934 /* ignore an error and continue */ 2935 } 2936 } 2937 } else { 2938 index = pluginOid.ownerId - 1; 2939 if (plugintable[index].hdlPlugin != NULL) { 2940 PassFunc = (MP_RegisterForObjectPropertyChangesPluginFn) 2941 dlsym(plugintable[index].hdlPlugin, 2942 "MP_RegisterForObjectPropertyChangesPlugin"); 2943 } 2944 2945 if (PassFunc != NULL) { 2946 status = PassFunc(pClientFn, objectType, pCallerData); 2947 } 2948 } 2949 (void) pthread_mutex_unlock(&mp_lib_mutex); 2950 return (status); 2951 } 2952 2953 /** 2954 ******************************************************************************* 2955 * 2956 * Deregisters a previously registered client function that is to be invoked 2957 * whenever an object's property changes. 2958 * 2959 * @param pClientFn, 2960 * A pointer to an MP_OBJECT_PROPERTY_FN function defined by the 2961 * client that was previously registered using 2962 * the MP_RegisterForObjectPropertyChanges API. On successful return 2963 * this function will no longer be called to inform the client of 2964 * object property changes. 2965 * 2966 * @param objectType 2967 * The type of object the client wishes to deregister for 2968 * property change callbacks. If null, then all objects types are 2969 * deregistered. 2970 * 2971 * @return An MP_STATUS indicating if the operation was successful or if 2972 * an error occurred. 2973 * 2974 * @retval MP_STATUS_SUCCESS 2975 * Returned when the operation is successful. 2976 * 2977 * @retval MP_STATUS_INVALID_PARAMETER 2978 * Returned if pClientFn is NULL or specifies a memory area 2979 * that is not executable. 2980 * 2981 * @retval MP_STATUS_UNKNOWN_FN 2982 * Returned if pClientFn is not the same as the previously registered 2983 * function. 2984 * 2985 * @retval MP_STATUS_INVALID_OBJECT_TYPE 2986 * Returned if oid does not specify any valid object type. 2987 * 2988 * @retval MP_STATUS_FAILED 2989 * Returned if pClientFn deregistration is not possible at this time. 2990 * 2991 ******************************************************************************* 2992 */ 2993 MP_STATUS MP_DeregisterForObjectPropertyChanges( 2994 MP_OBJECT_PROPERTY_FN pClientFn, 2995 MP_OBJECT_TYPE objectType, 2996 MP_OID pluginOid) 2997 { 2998 MP_DeregisterForObjectPropertyChangesPluginFn PassFunc; 2999 MP_UINT32 i; 3000 MP_UINT32 index; 3001 MP_STATUS status; 3002 3003 if (pClientFn == NULL) { 3004 return (MP_STATUS_INVALID_PARAMETER); 3005 } 3006 3007 if (objectType > MP_OBJECT_TYPE_MAX) { 3008 return (MP_STATUS_INVALID_OBJECT_TYPE); 3009 } 3010 3011 if (!(is_zero_oid(pluginOid))) { 3012 if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN, 3013 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 3014 return (status); 3015 } 3016 } 3017 3018 (void) pthread_mutex_lock(&mp_lib_mutex); 3019 3020 if (is_zero_oid(pluginOid)) { 3021 for (i = 0; i < number_of_plugins; i++) { 3022 if (plugintable[i].hdlPlugin != NULL) { 3023 PassFunc = (MP_DeregisterForObjectPropertyChangesPluginFn) 3024 dlsym(plugintable[i].hdlPlugin, 3025 "MP_DeregisterForObjectPropertyChangesPlugin"); 3026 } 3027 3028 if (PassFunc != NULL) { 3029 status = PassFunc(pClientFn, objectType); 3030 } 3031 } 3032 } else { 3033 index = pluginOid.ownerId - 1; 3034 if (plugintable[index].hdlPlugin != NULL) { 3035 PassFunc = (MP_DeregisterForObjectPropertyChangesPluginFn) 3036 dlsym(plugintable[index].hdlPlugin, 3037 "MP_DeregisterForObjectPropertyChangesPlugin"); 3038 } 3039 3040 if (PassFunc != NULL) { 3041 status = PassFunc(pClientFn, objectType); 3042 } 3043 } 3044 (void) pthread_mutex_unlock(&mp_lib_mutex); 3045 return (status); 3046 } 3047 3048 /** 3049 ******************************************************************************* 3050 * 3051 * Registers a client function that is to be called 3052 * whenever a high level object appears or disappears. 3053 * 3054 * @param pClientFn, 3055 * A pointer to an MP_OBJECT_VISIBILITY_FN function defined by the 3056 * client. On successful return this function will be called to 3057 * inform the client of objects whose visibility has changed. 3058 * 3059 * @param objectType 3060 * The type of object the client wishes to deregister for 3061 * property change callbacks. If null, then all objects types are 3062 * deregistered. 3063 * 3064 * @param pCallerData 3065 * A pointer that is passed to the callback routine with each event. 3066 * This may be used by the caller to correlate the event to source of 3067 * the registration. 3068 * 3069 * @return An MP_STATUS indicating if the operation was successful or if 3070 * an error occurred. 3071 * 3072 * @retval MP_STATUS_SUCCESS 3073 * Returned when the operation is successful. 3074 * 3075 * @retval MP_STATUS_INVALID_PARAMETER 3076 * Returned if pClientFn is NULL or specifies a memory area 3077 * that is not executable. 3078 * 3079 * @retval MP_STATUS_FN_REPLACED 3080 * Returned when an existing client function is replaced with the one 3081 * specified in pClientFn. 3082 * 3083 * @retval MP_STATUS_INVALID_OBJECT_TYPE 3084 * Returned if objectType does not specify any valid object type. 3085 * 3086 ******************************************************************************* 3087 */ 3088 MP_STATUS MP_RegisterForObjectVisibilityChanges( 3089 MP_OBJECT_VISIBILITY_FN pClientFn, 3090 MP_OBJECT_TYPE objectType, 3091 void *pCallerData, 3092 MP_OID pluginOid) 3093 { 3094 MP_RegisterForObjectVisibilityChangesPluginFn PassFunc; 3095 MP_UINT32 i; 3096 MP_UINT32 index; 3097 MP_STATUS status; 3098 3099 if (pClientFn == NULL) { 3100 return (MP_STATUS_INVALID_PARAMETER); 3101 } 3102 3103 if (objectType > MP_OBJECT_TYPE_MAX) { 3104 return (MP_STATUS_INVALID_OBJECT_TYPE); 3105 } 3106 3107 if (!(is_zero_oid(pluginOid))) { 3108 if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN, 3109 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 3110 return (status); 3111 } 3112 } 3113 3114 (void) pthread_mutex_lock(&mp_lib_mutex); 3115 3116 if (is_zero_oid(pluginOid)) { 3117 for (i = 0; i < number_of_plugins; i++) { 3118 if (plugintable[i].hdlPlugin != NULL) { 3119 PassFunc = (MP_RegisterForObjectVisibilityChangesPluginFn) 3120 dlsym(plugintable[i].hdlPlugin, 3121 "MP_RegisterForObjectVisibilityChangesPlugin"); 3122 } 3123 3124 if (PassFunc != NULL) { 3125 status = PassFunc(pClientFn, objectType, pCallerData); 3126 /* ignore an error and continue. */ 3127 } 3128 } 3129 } else { 3130 index = pluginOid.ownerId - 1; 3131 if (plugintable[index].hdlPlugin != NULL) { 3132 PassFunc = (MP_RegisterForObjectVisibilityChangesPluginFn) 3133 dlsym(plugintable[index].hdlPlugin, 3134 "MP_RegisterForObjectVisibilityChangesPlugin"); 3135 } 3136 3137 if (PassFunc != NULL) { 3138 status = PassFunc(pClientFn, objectType, pCallerData); 3139 } 3140 } 3141 (void) pthread_mutex_unlock(&mp_lib_mutex); 3142 return (status); 3143 3144 } 3145 3146 /** 3147 ******************************************************************************* 3148 * 3149 * Deregisters a previously registered client function that is to be invoked 3150 * whenever a high level object appears or disappears. 3151 * 3152 * @param pClientFn, 3153 * A pointer to an MP_OBJECT_VISIBILITY_FN function defined by the 3154 * client that was previously registered using 3155 * the MP_RegisterForObjectVisibilityChanges API. On successful return 3156 * this function will no longer be called to inform the client of 3157 * object property changes. 3158 * 3159 * @param objectType 3160 * The type of object the client wishes to deregister for visibility 3161 * change callbacks. If null, then all objects types are 3162 * deregistered. 3163 * 3164 * @return An MP_STATUS indicating if the operation was successful or if 3165 * an error occurred. 3166 * 3167 * @retval MP_STATUS_SUCCESS 3168 * Returned when the operation is successful. 3169 * 3170 * @retval MP_STATUS_INVALID_PARAMETER 3171 * Returned if pClientFn is NULL or specifies a memory area 3172 * that is not executable. 3173 * 3174 * @retval MP_STATUS_UNKNOWN_FN 3175 * Returned if pClientFn is not the same as the previously registered 3176 * function. 3177 * 3178 * @retval MP_STATUS_INVALID_OBJECT_TYPE 3179 * Returned if objectType does not specify any valid object type. 3180 * 3181 * @retval MP_STATUS_FAILED 3182 * Returned if pClientFn deregistration is not possible at this time. 3183 * 3184 ******************************************************************************* 3185 */ 3186 MP_STATUS MP_DeregisterForObjectVisibilityChanges( 3187 MP_OBJECT_VISIBILITY_FN pClientFn, 3188 MP_OBJECT_TYPE objectType, 3189 MP_OID pluginOid) 3190 { 3191 MP_DeregisterForObjectVisibilityChangesPluginFn PassFunc; 3192 MP_UINT32 i; 3193 MP_UINT32 index; 3194 MP_STATUS status; 3195 3196 if (pClientFn == NULL) { 3197 return (MP_STATUS_INVALID_PARAMETER); 3198 } 3199 3200 if (objectType > MP_OBJECT_TYPE_MAX) { 3201 return (MP_STATUS_INVALID_OBJECT_TYPE); 3202 } 3203 3204 if (!(is_zero_oid(pluginOid))) { 3205 if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN, 3206 MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) { 3207 return (status); 3208 } 3209 } 3210 3211 (void) pthread_mutex_lock(&mp_lib_mutex); 3212 3213 if (is_zero_oid(pluginOid)) { 3214 for (i = 0; i < number_of_plugins; i++) { 3215 if (plugintable[i].hdlPlugin != NULL) { 3216 PassFunc = (MP_DeregisterForObjectVisibilityChangesPluginFn) 3217 dlsym(plugintable[i].hdlPlugin, 3218 "MP_DeregisterForObjectVisibilityChangesPlugin"); 3219 if (PassFunc != NULL) { 3220 status = PassFunc(pClientFn, objectType); 3221 } 3222 } 3223 } 3224 } else { 3225 index = pluginOid.ownerId - 1; 3226 if (plugintable[index].hdlPlugin != NULL) { 3227 PassFunc = (MP_DeregisterForObjectVisibilityChangesPluginFn) 3228 dlsym(plugintable[index].hdlPlugin, 3229 "MP_DeregisterForObjectVisibilityChangesPlugin"); 3230 if (PassFunc != NULL) { 3231 status = PassFunc(pClientFn, objectType); 3232 } 3233 } 3234 } 3235 3236 (void) pthread_mutex_unlock(&mp_lib_mutex); 3237 return (status); 3238 } 3239 3240 /** 3241 ******************************************************************************* 3242 * 3243 * Compare two Oids for equality to see whether they refer to the same object. 3244 * 3245 * @param oid1 3246 * Oid to compare. 3247 * 3248 * @param oid2 3249 * Oid to compare. 3250 * 3251 * @return An MP_STATUS indicating if the operation was successful or if 3252 * an error occurred. 3253 * 3254 * @retval MP_STATUS_SUCCESS 3255 * Returned when the two Oids do refer to the same object. 3256 * 3257 * @retval MP_STATUS_FAILED 3258 * Returned if the Oids don't compare. 3259 * 3260 ******************************************************************************* 3261 */ 3262 MP_STATUS MP_CompareOIDs( 3263 MP_OID oid1, 3264 MP_OID oid2) 3265 { 3266 if ((oid1.objectType == oid2.objectType) && (oid1.ownerId == oid2.ownerId) 3267 && (oid1.objectSequenceNumber == oid2.objectSequenceNumber)) { 3268 return (MP_STATUS_SUCCESS); 3269 } else { 3270 return (MP_STATUS_FAILED); 3271 } 3272 } 3273 3274 /** 3275 ******************************************************************************* 3276 * 3277 * Frees memory returned by an MP API. 3278 * 3279 * @param pOidList 3280 * A pointer to the memory returned by an MP API. On successful 3281 return, the allocated memory is freed. 3282 * 3283 * @return An MP_STATUS indicating if the operation was successful or if 3284 * an error occurred. 3285 * 3286 * @retval MP_STATUS_SUCCESS 3287 * Returned when pPluginId is deregistered successfully. 3288 * 3289 * @retval MP_STATUS_INVALID_PARAMETER 3290 * Returned if pMemory is NULL or specifies a memory area to which 3291 * data cannot be written. 3292 * 3293 ******************************************************************************* 3294 */ 3295 MP_STATUS MP_FreeOidList(MP_OID_LIST *pOidList) 3296 { 3297 if (pOidList == NULL) { 3298 return (MP_STATUS_INVALID_PARAMETER); 3299 } 3300 3301 free(pOidList); 3302 3303 return (MP_STATUS_SUCCESS); 3304 } 3305 3306 static MP_CHAR *HDR = 3307 "#\n" 3308 "# This file contains names and references to MP API plugin libraries\n" 3309 "#\n" 3310 "# Do NOT manually edit this file\n" 3311 "#\n" 3312 "# Format:\n" 3313 "#\n" 3314 "# <library ID> <library pathname>\n" 3315 "#\n"; 3316 3317 #define CLEANUP_N_RET(fd, ret) \ 3318 if (lock_register(fd, F_SETLK, F_UNLCK, 0, SEEK_SET, 0) < 0) { \ 3319 close(fd); \ 3320 return (MP_STATUS_FAILED); \ 3321 } \ 3322 close(fd); \ 3323 return (ret) 3324 3325 /* 3326 * This function sets an advisory lock on the file pointed to by the argument 3327 * fd, which is a file descriptor. The lock is set using fcntl() which uses 3328 * flock structure. 3329 */ 3330 static int 3331 lock_register(int fd, int cmd, int type, off_t offset, int whence, off_t len) 3332 { 3333 struct flock lock; 3334 3335 lock.l_type = type; 3336 lock.l_start = offset; 3337 lock.l_whence = whence; 3338 lock.l_len = len; 3339 3340 return (fcntl(fd, cmd, &lock)); 3341 } 3342 3343 /* 3344 * This function searches for "srch_str" (of length "slen") in "buf" (of length 3345 * "buflen"). If it is not found, "write_offset" has the offset in "buf" where 3346 * "srch_str" would have to be added in "buf". If "srch_str" is found in "buf", 3347 * "write_offset" has its offset in "buf" 3348 * 3349 * ARGUMENTS : 3350 * buf - buffer to search in 3351 * buflen - length of buffer 3352 * srch_id - id to search 3353 * id_len - length of srch_id 3354 * write_offset - Set in function on exit 3355 * - It is the offset in buf where srch_str is or should be 3356 * bytes_left - Set in function on exit 3357 * - It is the # of bytes left beyond write_offset in buf 3358 * RETURN VALUES : 3359 * Zero - "srch_id" found in "buf"... "write_offset" has offset in "buf" 3360 * != 0 - "srch_str" NOT found in "buf" ... "write_offset" points to the end of 3361 * "buf". 3362 */ 3363 static int 3364 search_line(MP_CHAR *buf, size_t buflen, MP_CHAR *srch_id, size_t id_len, 3365 int *write_offset, int *bytes_left) 3366 { 3367 int retval, sizeof_conf_hdr = strlen(HDR); 3368 MP_CHAR *sol; /* Pointer to Start-Of-Line */ 3369 MP_CHAR *cur_pos; /* current position */ 3370 3371 *bytes_left = buflen; 3372 *write_offset = 0; 3373 3374 if (buf == NULL || buflen <= 0) 3375 return (-1); 3376 3377 if (srch_id == NULL || id_len <= 0) 3378 return (0); 3379 3380 sol = cur_pos = buf; 3381 3382 /* 3383 * mp conf file should not be edited but takes care of 3384 * any extra white space when parsing the line. 3385 * 3386 * The line should have id + delimiter + name + newline. 3387 */ 3388 while (*bytes_left >= (id_len + 3)) { 3389 /* skip leading blank or space. */ 3390 while ((*cur_pos == ' ') || (*cur_pos == '\t')) { 3391 cur_pos++; 3392 } 3393 3394 if (strncmp(cur_pos, srch_id, id_len) == 0) { 3395 /* id matched. */ 3396 cur_pos += id_len; 3397 3398 while (*cur_pos != '\n') { 3399 cur_pos++; 3400 } 3401 *write_offset = (sol - buf); 3402 *bytes_left = buflen - ((cur_pos + 1) - buf); 3403 return (0); 3404 } else { 3405 /* move to the next line */ 3406 while (*cur_pos != '\n') { 3407 cur_pos++; 3408 } 3409 *bytes_left = buflen - ((cur_pos + 1) - buf); 3410 } 3411 sol = cur_pos = cur_pos + 1; 3412 } 3413 3414 /* Given strings are not found. */ 3415 *write_offset = buflen; 3416 return (-1); 3417 } 3418 3419 /** 3420 ******************************************************************************* 3421 * 3422 * Registers a plugin with common library. The implementation of this routine 3423 * is based on configuration file /etc/mpapi.conf that contains a list of 3424 * plugin libraries. 3425 * 3426 * @param pPluginId 3427 * A pointer to the key name shall be the reversed domain name of 3428 * the vendor followed by followed by the vendor specific name for 3429 * the plugin that uniquely identifies the plugin. Should be NULL 3430 * terminated. 3431 * 3432 * @param pFileName 3433 * The full path to the plugin library. 3434 * Should be NULL terminated. 3435 * 3436 * @return An MP_STATUS indicating if the operation was successful or if 3437 * an error occurred. 3438 * 3439 * @retval MP_STATUS_SUCCESS 3440 * Returned when pPluginId is deregistered successfully. 3441 * 3442 * @retval MP_STATUS_INVALID_PARAMETER 3443 * Returned if pPluginId is NULL or specifies a memory area that 3444 * is not executable. 3445 * 3446 * @retval MP_STATUS_FAILED 3447 * Returned if pClientFn deregistration is not possible at this time. 3448 * 3449 ******************************************************************************* 3450 */ 3451 MP_STATUS MP_RegisterPlugin( 3452 MP_WCHAR *pPluginId, 3453 char *pFileName) 3454 { 3455 int mpconf, bytes_left, write_offset; 3456 MP_CHAR fullline[MAX_LINE_SIZE]; /* Full line to add to mpapi.conf */ 3457 MP_CHAR *mpconf_buf; 3458 MP_CHAR pluginid[MAX_NAME_SIZE]; 3459 char systemPath[MAX_NAME_SIZE], mpConfFilePath[MAX_NAME_SIZE]; 3460 MP_UINT32 new_file_flag = 0; 3461 MP_UINT32 sizeof_conf_hdr = strlen(HDR); 3462 struct stat stbuf; 3463 3464 if ((pPluginId == NULL) || (pFileName == NULL)) { 3465 return (MP_STATUS_INVALID_PARAMETER); 3466 } 3467 3468 if (stat(pFileName, &stbuf) != 0) { 3469 return (MP_STATUS_INVALID_PARAMETER); 3470 } 3471 3472 if (wcstombs(pluginid, pPluginId, MAX_NAME_SIZE) != wcslen(pPluginId)) { 3473 return (MP_STATUS_INVALID_PARAMETER); 3474 } 3475 3476 *fullline = '\0'; 3477 strncpy(fullline, pluginid, MAX_NAME_SIZE); 3478 /* add tab */ 3479 strncat(fullline, "\t", MAX_LINE_SIZE - strlen(pluginid)); 3480 strncat(fullline, pFileName, MAX_LINE_SIZE - strlen(pluginid) - 1); 3481 /* add a new line. */ 3482 strncat(fullline, "\n", 3483 MAX_LINE_SIZE - strlen(pluginid) - strlen(pFileName) -1); 3484 3485 /* Open configuration file from known location */ 3486 strncpy(mpConfFilePath, "/etc/mpapi.conf", MAX_NAME_SIZE); 3487 3488 if ((chmod(mpConfFilePath, S_IRUSR|S_IRGRP|S_IROTH) == -1) && 3489 (errno == ENOENT)) { 3490 new_file_flag = 1; 3491 } 3492 3493 if ((mpconf = open(mpConfFilePath, O_RDWR | O_CREAT)) == -1) { 3494 return (MP_STATUS_FAILED); 3495 } 3496 3497 if (fchmod(mpconf, S_IRUSR | S_IRGRP | S_IROTH) < 0) { 3498 close(mpconf); 3499 return (MP_STATUS_FAILED); 3500 } 3501 3502 if (lock_register(mpconf, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) { 3503 close(mpconf); 3504 return (MP_STATUS_FAILED); 3505 } 3506 3507 if (fstat(mpconf, &stbuf) == -1) { 3508 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3509 } 3510 3511 if ((new_file_flag) || (stbuf.st_size == 0)) { 3512 if (write(mpconf, HDR, sizeof_conf_hdr) != 3513 sizeof_conf_hdr) { 3514 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3515 } 3516 3517 if (pwrite(mpconf, fullline, strlen(fullline), 3518 sizeof_conf_hdr) != 3519 strlen(fullline)) { 3520 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3521 } 3522 CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS); 3523 } 3524 3525 if ((mpconf_buf = (MP_CHAR *)mmap(0, stbuf.st_size, 3526 PROT_READ | PROT_WRITE, 3527 MAP_SHARED, mpconf, 0)) == MAP_FAILED) { 3528 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3529 } 3530 3531 if (search_line(mpconf_buf, stbuf.st_size, 3532 pluginid, strlen(pluginid), &write_offset, &bytes_left) == 0) { 3533 /* found a match. */ 3534 munmap((void *)mpconf_buf, stbuf.st_size); 3535 CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS); 3536 } else { 3537 munmap((void *)mpconf_buf, stbuf.st_size); 3538 /* append the fullline to the mpconf. */ 3539 if (pwrite(mpconf, fullline, strlen(fullline), 3540 write_offset) != 3541 strlen(fullline)) { 3542 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3543 } else { 3544 CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS); 3545 } 3546 } 3547 } 3548 3549 /** 3550 ******************************************************************************* 3551 * 3552 * Deregisters a plugin from the common library. This routine is based on 3553 * configuration file /etc/mpapi.conf that contains a list of plugin libraries. 3554 * 3555 * @param pPluginId 3556 * A pointer to a Plugin ID previously registered using 3557 * the MP_RegisterPlugin API.. 3558 * 3559 * @return An MP_STATUS indicating if the operation was successful or if 3560 * an error occurred. 3561 * 3562 * @retval MP_STATUS_SUCCESS 3563 * Returned when pPluginId is deregistered successfully. 3564 * 3565 * @retval MP_STATUS_INVALID_PARAMETER 3566 * Returned if pPluginId is NULL or specifies a memory area that 3567 * is not executable. 3568 * 3569 * @retval MP_STATUS_FAILED 3570 * Returned if pClientFn deregistration is not possible at this time. 3571 * 3572 ******************************************************************************* 3573 */ 3574 MP_STATUS MP_DeregisterPlugin( 3575 MP_WCHAR *pPluginId) 3576 { 3577 int mpconf, tmp_mpconf, bytes_left, write_offset; 3578 char systemPath[MAX_NAME_SIZE], mpConfFilePath[MAX_NAME_SIZE], 3579 tmp_mpConfFilePath[MAX_NAME_SIZE + sizeof(pid_t)]; 3580 MP_CHAR pluginid[MAX_NAME_SIZE]; 3581 MP_CHAR *mpconf_buf; 3582 MP_UINT32 sizeof_conf_hdr = strlen(HDR); 3583 struct stat stbuf; 3584 3585 if (pPluginId == NULL) { 3586 return (MP_STATUS_INVALID_PARAMETER); 3587 } 3588 3589 if (wcstombs(pluginid, pPluginId, MAX_NAME_SIZE) != wcslen(pPluginId)) { 3590 return (MP_STATUS_INVALID_PARAMETER); 3591 } 3592 3593 /* Open configuration file from known location */ 3594 strncpy(mpConfFilePath, "/etc/mpapi.conf", MAX_NAME_SIZE); 3595 3596 if ((chmod(mpConfFilePath, S_IRUSR|S_IRGRP|S_IROTH) == -1) && 3597 (errno == ENOENT)) { 3598 /* no file found */ 3599 return (MP_STATUS_UNKNOWN_FN); 3600 } 3601 3602 if ((mpconf = open(mpConfFilePath, O_RDWR)) == -1) { 3603 return (MP_STATUS_FAILED); 3604 } 3605 3606 if (fchmod(mpconf, S_IRUSR | S_IRGRP | S_IROTH) < 0) { 3607 close(mpconf); 3608 return (MP_STATUS_FAILED); 3609 } 3610 3611 if (lock_register(mpconf, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) { 3612 close(mpconf); 3613 return (MP_STATUS_FAILED); 3614 } 3615 3616 if (fstat(mpconf, &stbuf) == -1) { 3617 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3618 } 3619 3620 if (stbuf.st_size == 0) { 3621 CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS); 3622 } 3623 3624 if ((mpconf_buf = (MP_CHAR *)mmap(0, stbuf.st_size, 3625 PROT_READ | PROT_WRITE, 3626 MAP_SHARED, mpconf, 0)) == MAP_FAILED) { 3627 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3628 } 3629 3630 if (search_line(mpconf_buf, stbuf.st_size, pluginid, strlen(pluginid), 3631 &write_offset, &bytes_left) != 0) { 3632 munmap((void *)mpconf_buf, stbuf.st_size); 3633 CLEANUP_N_RET(mpconf, MP_STATUS_UNKNOWN_FN); 3634 } else { 3635 /* 3636 * found a match. 3637 * construct temp file name using pid. 3638 */ 3639 (void) snprintf(tmp_mpConfFilePath, MAX_NAME_SIZE, 3640 "%s%ld", "/etc/mpapi.conf", getpid()); 3641 3642 if ((tmp_mpconf = open(tmp_mpConfFilePath, 3643 O_RDWR|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR)) < 0) { 3644 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3645 } 3646 3647 if (write(tmp_mpconf, mpconf_buf, write_offset) != write_offset) { 3648 close(tmp_mpconf); 3649 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3650 } 3651 3652 if (pwrite(tmp_mpconf, mpconf_buf + (stbuf.st_size - bytes_left), 3653 bytes_left, write_offset) != bytes_left) { 3654 close(tmp_mpconf); 3655 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3656 } 3657 3658 close(tmp_mpconf); 3659 munmap((void *)mpconf_buf, stbuf.st_size); 3660 3661 /* rename temp file to mpConfFile before unlock and close. */ 3662 if (rename(tmp_mpConfFilePath, mpConfFilePath) != 0) { 3663 CLEANUP_N_RET(mpconf, MP_STATUS_FAILED); 3664 } else { 3665 CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS); 3666 } 3667 } 3668 } 3669