1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Block comment which describes the contents of this file. 28 */ 29 30 #include <dlfcn.h> 31 #include <meta.h> 32 #include <metadyn.h> 33 #include <sdssc.h> 34 35 #define SDSSC_PATH SDSSC_CL_LIBDIR "/sc/libsds_sc.so" 36 37 static func_table_t dl_table[] = { 38 { "_sdssc_version", (void **)&sdssc_version }, 39 { "_sdssc_create_begin", (void **)&sdssc_create_begin }, 40 { "_sdssc_mo_create_begin", (void **)&sdssc_mo_create_begin }, 41 { "_sdssc_create_end", (void **)&sdssc_create_end }, 42 { "_sdssc_delete_begin", (void **)&sdssc_delete_begin }, 43 { "_sdssc_delete_end", (void **)&sdssc_delete_end }, 44 { "_sdssc_get_index", (void **)&sdssc_get_index }, 45 { "_sdssc_add_hosts", (void **)&sdssc_add_hosts }, 46 { "_sdssc_delete_hosts", (void **)&sdssc_delete_hosts }, 47 { "_sdssc_get_primary_host", (void **)&sdssc_get_primary_host }, 48 { "_sdssc_cmd_proxy", (void **)&sdssc_cmd_proxy }, 49 { "_sdssc_getnodelist", (void **)&sdssc_getnodelist }, 50 { "_sdssc_freenodelist", (void **)&sdssc_freenodelist }, 51 { "_sdssc_binddevs", (void **)&sdssc_binddevs }, 52 { "_sdssc_bindclusterdevs", (void **)&sdssc_bindclusterdevs }, 53 { "_sdssc_gettransportbynode", (void **)&sdssc_gettransportbynode }, 54 { "_sdssc_free_mdcerr_list", (void **)&sdssc_free_mdcerr_list }, 55 { "_sdssc_property_get", (void **)&sdssc_property_get }, 56 { "_sdssc_property_set", (void **)&sdssc_property_set }, 57 { "_sdssc_get_services", (void **)&sdssc_get_services }, 58 { "_sdssc_get_services_free", (void **)&sdssc_get_services_free }, 59 { "_sdssc_suspend", (void **)&sdssc_suspend }, 60 { "_sdssc_convert_cluster_path", 61 (void **)&sdssc_convert_cluster_path }, 62 { "_sdssc_convert_ctd_path", 63 (void **)&sdssc_convert_ctd_path }, 64 { "_sdssc_convert_path_free", 65 (void **)&sdssc_convert_path_free }, 66 { "_sdssc_notify_service", (void **)&sdssc_notify_service }, 67 { "_sdssc_cm_nm2nid", (void **)&sdssc_cm_nm2nid }, 68 { "_sdssc_cm_sr_nm2nid", (void **)&sdssc_cm_sr_nm2nid }, 69 { "_sdssc_cm_nid2nm", (void **)&sdssc_cm_nid2nm }, 70 { "_sdssc_cm_sr_nid2nm", (void **)&sdssc_cm_sr_nid2nm }, 71 { "_sdssc_get_priv_ipaddr", (void **)&sdssc_get_priv_ipaddr }, 72 { (char *)0, (void **)0 } 73 }; 74 75 static rval_e 76 just_dup_string(const char *source, char **dest) 77 { 78 *dest = strdup(source); 79 return (SDSSC_OKAY); 80 } 81 82 static void 83 free_dup_string(char *source) 84 { 85 free(source); 86 } 87 88 /* 89 * not_bound -- routine to always return NOT_BOUND 90 */ 91 static rval_e 92 not_bound(void) 93 { 94 return (SDSSC_NOT_BOUND); 95 } 96 97 /* 98 * not_bound_error -- routine to always return SDSSC_NOT_BOUND_ERROR since 99 * routine is not bound. This is used when using an older version 100 * of libsdssc that doesn't support MN disksets. When an MN specific 101 * routine is called (such as sdssc_mo_create_set) an SDSSC_NOT_BOUND_ERROR 102 * will be returned. 103 */ 104 static rval_e 105 not_bound_error(void) 106 { 107 return (SDSSC_NOT_BOUND_ERROR); 108 } 109 110 111 /* 112 * set_common_routine -- set cluster interface routines to return NOT_BOUND 113 */ 114 static void 115 set_common_routine() 116 { 117 func_table_p f; 118 119 for (f = dl_table; f->fptr != (void *)0; f++) { 120 if (strcmp(f->fname, "_sdssc_convert_cluster_path") == 0) { 121 *f->fptr = (void *)&just_dup_string; 122 } else if (strcmp(f->fname, "_sdssc_free_convert_cluster_path") 123 == 0) { 124 *f->fptr = (void *)&free_dup_string; 125 } else { 126 *f->fptr = (void *)¬_bound; 127 } 128 } 129 } 130 131 /* 132 * sdssc_bind_library -- entry point which resolves all cluster interface pts. 133 */ 134 rval_e 135 sdssc_bind_library(void) 136 { 137 void *dp; 138 int (*lb)(); 139 func_table_p ftp; 140 static int initialised = 0; 141 142 /* 143 * If already bound then just return okay so this routine 144 * becomes idempotent. If this check isn't made then we'll 145 * fail when calling the "_bind_library" function because 146 * dcs_initialize() can only be called once. 147 * If not bound first time we try it again. 148 */ 149 if (initialised && (void *)sdssc_version != (void *)not_bound) { 150 return (SDSSC_OKAY); 151 } 152 initialised = 1; 153 154 if ((dp = dlopen(SDSSC_PATH, RTLD_LAZY)) == NULL) { 155 set_common_routine(); 156 return (SDSSC_NOT_BOUND); 157 } else { 158 159 /* 160 * Allow the binding library to initialize state if 161 * necessary. Currently this calls the DCS initialize() 162 * routine which checks to see if we're part of a cluster. 163 */ 164 if ((lb = (int (*)())dlsym(dp, "_bind_library")) != NULL) { 165 if (lb() != 0) { 166 set_common_routine(); 167 return (SDSSC_NOT_BOUND); 168 } 169 } 170 171 /* 172 * Load 'em up. Pick up the function address and store 173 * the values in the global pointers for other routines 174 * to use. 175 */ 176 for (ftp = dl_table; ftp->fptr != (void *)0; ftp++) { 177 if ((*ftp->fptr = dlsym(dp, ftp->fname)) == NULL) { 178 179 /* 180 * If old libsdssc library is there, then 181 * sdssc_mo_create_begin is not yet supported. 182 */ 183 if (strcmp(ftp->fname, 184 "sdssc_mo_create_begin")) { 185 *ftp->fptr = (void *)¬_bound_error; 186 continue; 187 } 188 /* 189 * If this routine fails to find a single 190 * entry point that it's expecting 191 * (except sdssc_mo_create_begin) then 192 * setup non-sdssc stubs routines 193 * as function pointers. 194 */ 195 set_common_routine(); 196 return (SDSSC_ERROR); 197 } 198 } 199 200 return (SDSSC_OKAY); 201 } 202 } 203