xref: /illumos-gate/usr/src/lib/udapl/libdat/common/udat.c (revision afab0816ecb604f0099a09ad8ee398f0d7b77b1c)
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 (c) 2002-2003, Network Appliance, Inc. All rights reserved.
23  */
24 
25 /*
26  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 
31 /*
32  *
33  * MODULE: udat.c
34  *
35  * PURPOSE: DAT Provider and Consumer registry functions.
36  *
37  * $Id: udat.c,v 1.13 2003/08/20 14:28:40 hobie16 Exp $
38  */
39 
40 #include <dat/udat.h>
41 #include <dat/dat_registry.h> /* Provider API function prototypes */
42 
43 #include "dat_dr.h"
44 #include "dat_init.h"
45 #include "dat_osd.h"
46 #ifndef	DAT_NO_STATIC_REGISTRY
47 #include "dat_sr.h"
48 #endif
49 
50 
51 #define	UDAT_IS_BAD_POINTER(p) (NULL == (p))
52 
53 /*
54  *
55  * Internal Function Declarations
56  *
57  */
58 
59 DAT_BOOLEAN
60 udat_check_state(void);
61 
62 
63 /*
64  *
65  * External Function Definitions
66  *
67  */
68 
69 
70 /*
71  *
72  * Provider API
73  *
74  */
75 
76 
77 /*
78  * Function: dat_registry_add_provider
79  */
80 
81 DAT_RETURN
82 dat_registry_add_provider(
83 	IN DAT_PROVIDER			*provider,
84 	IN const DAT_PROVIDER_INFO	*provider_info)
85 {
86 	DAT_DR_ENTRY 		entry;
87 
88 	dat_os_dbg_print(DAT_OS_DBG_TYPE_PROVIDER_API,
89 	    "DAT Registry: dat_registry_add_provider() called\n");
90 
91 	if (UDAT_IS_BAD_POINTER(provider)) {
92 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
93 	}
94 
95 	if (UDAT_IS_BAD_POINTER(provider_info)) {
96 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2));
97 	}
98 
99 	if (DAT_FALSE == udat_check_state()) {
100 		return (DAT_ERROR(DAT_INVALID_STATE, 0));
101 	}
102 
103 	entry.ref_count = 0;
104 	entry.ia_open_func = provider->ia_open_func;
105 	entry.info = *provider_info;
106 
107 	return (dat_dr_insert(provider_info, &entry));
108 }
109 
110 
111 /*
112  * Function: dat_registry_remove_provider
113  */
114 
115 DAT_RETURN
116 dat_registry_remove_provider(
117 	IN DAT_PROVIDER 		*provider,
118 	IN  const DAT_PROVIDER_INFO	*provider_info)
119 {
120 	dat_os_dbg_print(DAT_OS_DBG_TYPE_PROVIDER_API,
121 	    "DAT Registry: dat_registry_remove_provider() called\n");
122 
123 	if (UDAT_IS_BAD_POINTER(provider)) {
124 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
125 	}
126 
127 	if (DAT_FALSE == udat_check_state()) {
128 		return (DAT_ERROR(DAT_INVALID_STATE, 0));
129 	}
130 
131 	return (dat_dr_remove(provider_info));
132 }
133 
134 
135 /*
136  *
137  * Consumer API
138  *
139  */
140 
141 /*
142  * Function: dat_ia_open
143  */
144 
145 DAT_RETURN
146 dat_ia_openv(
147 	IN	const DAT_NAME_PTR	name,
148 	IN	DAT_COUNT		async_event_qlen,
149 	INOUT	DAT_EVD_HANDLE		*async_event_handle,
150 	OUT	DAT_IA_HANDLE		*ia_handle,
151 	IN	DAT_UINT32		dapl_major,
152 	IN	DAT_UINT32		dapl_minor,
153 	IN	DAT_BOOLEAN		thread_safety)
154 {
155 	DAT_IA_OPEN_FUNC		ia_open_func;
156 	DAT_PROVIDER_INFO 		info;
157 	DAT_RETURN 			status;
158 	DAT_OS_SIZE 			len;
159 #define	RO_AWARE_PREFIX	"RO_AWARE_"
160 	boolean_t			ro_aware_client;
161 	const char			*_name = name;
162 
163 	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
164 	    "DAT Registry: dat_ia_open() called\n");
165 
166 	if (UDAT_IS_BAD_POINTER(_name)) {
167 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
168 	}
169 
170 	len = dat_os_strlen(_name);
171 
172 	if (DAT_NAME_MAX_LENGTH <= len) {
173 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
174 	}
175 
176 	if (UDAT_IS_BAD_POINTER(ia_handle)) {
177 		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA));
178 	}
179 
180 	if (DAT_FALSE == udat_check_state()) {
181 		return (DAT_ERROR(DAT_INVALID_STATE, 0));
182 	}
183 
184 	/* Find out if this is an RO aware client and if so, strip the prefix */
185 	ro_aware_client =
186 	    (strncmp(RO_AWARE_PREFIX, _name, sizeof (RO_AWARE_PREFIX) - 1) ==
187 	    0);
188 
189 	/* strip off the prefix from the provider's name if present */
190 	if (ro_aware_client) {
191 		_name = _name + sizeof (RO_AWARE_PREFIX) - 1;
192 		len -= sizeof (RO_AWARE_PREFIX) - 1;
193 	}
194 
195 	(void) dat_os_strncpy(info.ia_name, _name, len);
196 	info.ia_name[len] = '\0';
197 
198 	info.dapl_version_major = dapl_major;
199 	info.dapl_version_minor = dapl_minor;
200 	info.is_thread_safe = thread_safety;
201 
202 	/*
203 	 * Since DAT allows providers to be loaded by either the static
204 	 * registry or explicitly through OS dependent methods, do not
205 	 * return an error if no providers are loaded via the static registry.
206 	 * Don't even bother calling the static registry if DAT is compiled
207 	 * with no static registry support.
208 	 */
209 
210 #ifndef DAT_NO_STATIC_REGISTRY
211 	(void) dat_sr_provider_open(&info);
212 #endif
213 
214 	status = dat_dr_provider_open(&info, &ia_open_func);
215 	if (status != DAT_SUCCESS) {
216 		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
217 		    "DAT Registry: dat_ia_open() provider information "
218 		    "for IA name %s not found in dynamic registry\n",
219 		    _name);
220 		return (status);
221 	}
222 
223 	return (*ia_open_func)((const DAT_NAME_PTR) _name,
224 	    async_event_qlen,
225 	    async_event_handle,
226 	    ia_handle,
227 	    ro_aware_client);
228 }
229 
230 
231 /*
232  * Function: dat_ia_close
233  */
234 
235 DAT_RETURN
236 dat_ia_close(
237 	IN DAT_IA_HANDLE	ia_handle,
238 	IN DAT_CLOSE_FLAGS	ia_flags)
239 {
240 	DAT_PROVIDER	*provider;
241 	DAT_PROVIDER_ATTR   provider_attr = {0};
242 	DAT_RETURN 		status;
243 	const char 		*ia_name;
244 
245 	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
246 	    "DAT Registry: dat_ia_close() called\n");
247 
248 	if (UDAT_IS_BAD_POINTER(ia_handle)) {
249 		return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA));
250 	}
251 
252 	if (DAT_FALSE == udat_check_state()) {
253 		return (DAT_ERROR(DAT_INVALID_STATE, 0));
254 	}
255 
256 	provider = DAT_HANDLE_TO_PROVIDER(ia_handle);
257 	ia_name = provider->device_name;
258 
259 	if (DAT_SUCCESS != (status = dat_ia_query(ia_handle,
260 	    NULL,
261 	    0,
262 	    NULL,
263 	    DAT_PROVIDER_FIELD_ALL,
264 	    &provider_attr))) {
265 		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
266 		    "DAT Registry: query function for %s provider failed\n",
267 		    ia_name);
268 	} else if (DAT_SUCCESS != (status =
269 	    (*provider->ia_close_func)(ia_handle, ia_flags))) {
270 		dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
271 		    "DAT Registry: close function for %s provider failed\n",
272 		    ia_name);
273 	} else {
274 		DAT_PROVIDER_INFO info;
275 		DAT_OS_SIZE len;
276 
277 		len = dat_os_strlen(ia_name);
278 
279 		dat_os_assert(len <= DAT_NAME_MAX_LENGTH);
280 
281 		(void) dat_os_strncpy(info.ia_name, ia_name, len);
282 		info.ia_name[len] = '\0';
283 
284 		info.dapl_version_major = provider_attr.dapl_version_major;
285 		info.dapl_version_minor = provider_attr.dapl_version_minor;
286 		info.is_thread_safe = provider_attr.is_thread_safe;
287 
288 		status = dat_dr_provider_close(&info);
289 		if (DAT_SUCCESS != status) {
290 			dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
291 			    "DAT Registry: dynamic registry unable to close "
292 			    "provider for IA name %s\n",
293 			    ia_name);
294 		}
295 
296 #ifndef DAT_NO_STATIC_REGISTRY
297 		status = dat_sr_provider_close(&info);
298 		if (DAT_SUCCESS != status) {
299 			dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
300 			    "DAT Registry: static registry unable to close "
301 			    "provider for IA name %s\n",
302 			    ia_name);
303 		}
304 #endif
305 	}
306 
307 	return (status);
308 }
309 
310 
311 /*
312  * Function: dat_registry_list_providers
313  */
314 
315 DAT_RETURN
316 dat_registry_list_providers(
317 	IN  DAT_COUNT   		max_to_return,
318 	    OUT DAT_COUNT   		*entries_returned,
319 	    OUT	DAT_PROVIDER_INFO 	*(dat_provider_list[]))
320 {
321 	DAT_RETURN	dat_status;
322 
323 	dat_status = DAT_SUCCESS;
324 	dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,
325 	    "DAT Registry: dat_registry_list_providers() called\n");
326 
327 	if (DAT_FALSE == udat_check_state()) {
328 			return (DAT_ERROR(DAT_INVALID_STATE, 0));
329 	}
330 
331 	if ((UDAT_IS_BAD_POINTER(entries_returned))) {
332 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2));
333 	}
334 
335 	if (0 != max_to_return && (UDAT_IS_BAD_POINTER(dat_provider_list))) {
336 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3));
337 	}
338 
339 	if (0 == max_to_return) {
340 		/*
341 		 * the user is allowed to call with max_to_return set to zero.
342 		 * in which case we simply return (in *entries_returned) the
343 		 * number of providers currently installed.  We must also
344 		 * (per spec) return an error
345 		 */
346 #ifndef DAT_NO_STATIC_REGISTRY
347 		(void) dat_sr_size(entries_returned);
348 #else
349 		(void) dat_dr_size(entries_returned);
350 #endif
351 		return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
352 	} else {
353 #ifndef DAT_NO_STATIC_REGISTRY
354 		dat_status = dat_sr_list(max_to_return,
355 		    entries_returned,
356 		    dat_provider_list);
357 #else
358 		dat_status = dat_dr_list(max_to_return,
359 		    entries_returned,
360 		    dat_provider_list);
361 #endif
362 	}
363 	return (dat_status);
364 }
365 
366 
367 /*
368  *
369  * Internal Function Definitions
370  *
371  */
372 
373 
374 /*
375  * Function: udat_check_state
376  */
377 
378 /*
379  * This function returns TRUE if the DAT registry is in a state capable
380  * of handling DAT API calls and false otherwise.
381  */
382 
383 DAT_BOOLEAN
384 udat_check_state(void)
385 {
386 	DAT_MODULE_STATE 		state;
387 	DAT_BOOLEAN 		status;
388 
389 	state = dat_module_get_state();
390 
391 	if (DAT_MODULE_STATE_UNINITIALIZED == state) {
392 		dat_init();
393 		status = DAT_TRUE;
394 	} else if (DAT_MODULE_STATE_DEINITIALIZED == state) {
395 		status = DAT_FALSE;
396 	} else {
397 		status = DAT_TRUE;
398 	}
399 
400 	return (status);
401 }
402 
403 
404 /*
405  * Local variables:
406  *  c-indent-level: 4
407  *  c-basic-offset: 4
408  *  tab-width: 8
409  * End:
410  */
411