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