xref: /titanic_41/usr/src/lib/lvm/libmeta/common/sdssc_bind.c (revision 1816cb7076d3ec8a78ef9ac9f895574e13c43645)
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 *)&not_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 *)&not_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