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