corosync  2.3.2
lib/cfg.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002-2005 MontaVista Software, Inc.
3  * Copyright (c) 2006-2013 Red Hat, Inc.
4  *
5  * All rights reserved.
6  *
7  * Author: Steven Dake (sdake@redhat.com)
8  *
9  * This software licensed under BSD license, the text of which follows:
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *
14  * - Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  * - Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  * - Neither the name of the MontaVista Software, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived from this
21  * software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <config.h>
37 
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <pthread.h>
44 #include <limits.h>
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <sys/select.h>
48 #include <sys/un.h>
49 #include <sys/uio.h>
50 
51 #include <qb/qbipcc.h>
52 
53 #include <corosync/corotypes.h>
54 #include <corosync/corodefs.h>
55 #include <corosync/hdb.h>
56 
57 #include <corosync/cfg.h>
58 #include <corosync/ipc_cfg.h>
59 
60 #include "util.h"
61 
62 /*
63  * Data structure for instance data
64  */
65 struct cfg_inst {
66  qb_ipcc_connection_t *c;
70  int finalize;
71 };
72 
73 /*
74  * All instances in one database
75  */
76 static void cfg_inst_free (void *inst);
77 
78 DECLARE_HDB_DATABASE (cfg_hdb, cfg_inst_free);
79 
80 /*
81  * Implementation
82  */
83 
86  corosync_cfg_handle_t *cfg_handle,
87  const corosync_cfg_callbacks_t *cfg_callbacks)
88 {
89  struct cfg_inst *cfg_inst;
90  cs_error_t error = CS_OK;
91 
92  error = hdb_error_to_cs (hdb_handle_create (&cfg_hdb, sizeof (struct cfg_inst), cfg_handle));
93  if (error != CS_OK) {
94  goto error_no_destroy;
95  }
96 
97  error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, *cfg_handle, (void *)&cfg_inst));
98  if (error != CS_OK) {
99  goto error_destroy;
100  }
101 
102  cfg_inst->finalize = 0;
103  cfg_inst->c = qb_ipcc_connect ("cfg", IPC_REQUEST_SIZE);
104  if (cfg_inst->c == NULL) {
105  error = qb_to_cs_error(-errno);
106  goto error_put_destroy;
107  }
108 
109  if (cfg_callbacks) {
110  memcpy (&cfg_inst->callbacks, cfg_callbacks, sizeof (corosync_cfg_callbacks_t));
111  }
112 
113  (void)hdb_handle_put (&cfg_hdb, *cfg_handle);
114 
115  return (CS_OK);
116 
117 error_put_destroy:
118  (void)hdb_handle_put (&cfg_hdb, *cfg_handle);
119 error_destroy:
120  (void)hdb_handle_destroy (&cfg_hdb, *cfg_handle);
121 error_no_destroy:
122  return (error);
123 }
124 
127  corosync_cfg_handle_t cfg_handle,
128  int32_t *selection_fd)
129 {
130  struct cfg_inst *cfg_inst;
131  cs_error_t error;
132 
133  error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst));
134  if (error != CS_OK) {
135  return (error);
136  }
137 
138  error = qb_to_cs_error (qb_ipcc_fd_get (cfg_inst->c, selection_fd));
139 
140  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
141  return (error);
142 }
143 
146  corosync_cfg_handle_t cfg_handle,
147  cs_dispatch_flags_t dispatch_flags)
148 {
149  int timeout = -1;
150  cs_error_t error;
151  int cont = 1; /* always continue do loop except when set to 0 */
152  struct cfg_inst *cfg_inst;
154  corosync_cfg_callbacks_t callbacks;
155  struct qb_ipc_response_header *dispatch_data;
156  char dispatch_buf[IPC_DISPATCH_SIZE];
157 
158  error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle,
159  (void *)&cfg_inst));
160  if (error != CS_OK) {
161  return (error);
162  }
163 
164  /*
165  * Timeout instantly for CS_DISPATCH_ONE_NONBLOCKING or CS_DISPATCH_ALL and
166  * wait indefinately for CS_DISPATCH_ONE or CS_DISPATCH_BLOCKING
167  */
168  if (dispatch_flags == CS_DISPATCH_ALL || dispatch_flags == CS_DISPATCH_ONE_NONBLOCKING) {
169  timeout = 0;
170  }
171 
172  dispatch_data = (struct qb_ipc_response_header *)dispatch_buf;
173  do {
174  error = qb_to_cs_error (qb_ipcc_event_recv (
175  cfg_inst->c,
176  dispatch_buf,
178  timeout));
179  if (error == CS_ERR_BAD_HANDLE) {
180  error = CS_OK;
181  goto error_put;
182  }
183  if (error == CS_ERR_TRY_AGAIN) {
184  if (dispatch_flags == CS_DISPATCH_ONE_NONBLOCKING) {
185  /*
186  * Don't mask error
187  */
188  goto error_put;
189  }
190  error = CS_OK;
191  if (dispatch_flags == CS_DISPATCH_ALL) {
192  break; /* exit do while cont is 1 loop */
193  } else {
194  continue; /* next poll */
195  }
196  }
197  if (error != CS_OK) {
198  goto error_put;
199  }
200 
201  /*
202  * Make copy of callbacks, message data, unlock instance, and call callback
203  * A risk of this dispatch method is that the callback routines may
204  * operate at the same time that cfgFinalize has been called in another thread.
205  */
206  memcpy (&callbacks, &cfg_inst->callbacks, sizeof (corosync_cfg_callbacks_t));
207 
208  /*
209  * Dispatch incoming response
210  */
211  switch (dispatch_data->id) {
213  if (callbacks.corosync_cfg_shutdown_callback == NULL) {
214  break;
215  }
216 
217  res_lib_cfg_testshutdown = (struct res_lib_cfg_testshutdown *)dispatch_data;
218  callbacks.corosync_cfg_shutdown_callback(cfg_handle, res_lib_cfg_testshutdown->flags);
219  break;
220  default:
221  error = CS_ERR_LIBRARY;
222  goto error_nounlock;
223  break;
224  }
225  if (cfg_inst->finalize) {
226  /*
227  * If the finalize has been called then get out of the dispatch.
228  */
229  error = CS_ERR_BAD_HANDLE;
230  goto error_put;
231  }
232 
233  /*
234  * Determine if more messages should be processed
235  */
236  if (dispatch_flags == CS_DISPATCH_ONE || dispatch_flags == CS_DISPATCH_ONE_NONBLOCKING) {
237  cont = 0;
238  }
239  } while (cont);
240 
241 error_put:
242  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
243 error_nounlock:
244  return (error);
245 }
246 
247 static void cfg_inst_free (void *inst)
248 {
249  struct cfg_inst *cfg_inst = (struct cfg_inst *)inst;
250  qb_ipcc_disconnect(cfg_inst->c);
251 }
252 
255  corosync_cfg_handle_t cfg_handle)
256 {
257  struct cfg_inst *cfg_inst;
258  cs_error_t error;
259 
260  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst));
261  if (error != CS_OK) {
262  return (error);
263  }
264 
265  /*
266  * Another thread has already started finalizing
267  */
268  if (cfg_inst->finalize) {
269  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
270  return (CS_ERR_BAD_HANDLE);
271  }
272 
273  cfg_inst->finalize = 1;
274 
275  (void)hdb_handle_destroy (&cfg_hdb, cfg_handle);
276 
277  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
278 
279  return (error);
280 }
281 
284  corosync_cfg_handle_t cfg_handle,
285  char ***interface_names,
286  char ***status,
287  unsigned int *interface_count)
288 {
289  struct cfg_inst *cfg_inst;
290  struct req_lib_cfg_ringstatusget req_lib_cfg_ringstatusget;
291  struct res_lib_cfg_ringstatusget res_lib_cfg_ringstatusget;
292  unsigned int i, j;
293  cs_error_t error;
294  struct iovec iov;
295 
296  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst));
297  if (error != CS_OK) {
298  return (error);
299  }
300 
301  req_lib_cfg_ringstatusget.header.size = sizeof (struct req_lib_cfg_ringstatusget);
302  req_lib_cfg_ringstatusget.header.id = MESSAGE_REQ_CFG_RINGSTATUSGET;
303 
304  iov.iov_base = (void *)&req_lib_cfg_ringstatusget,
305  iov.iov_len = sizeof (struct req_lib_cfg_ringstatusget),
306 
307  error = qb_to_cs_error (qb_ipcc_sendv_recv(cfg_inst->c,
308  &iov,
309  1,
310  &res_lib_cfg_ringstatusget,
311  sizeof (struct res_lib_cfg_ringstatusget), CS_IPC_TIMEOUT_MS));
312 
313  *interface_count = res_lib_cfg_ringstatusget.interface_count;
314  *interface_names = malloc (sizeof (char *) * *interface_count);
315  if (*interface_names == NULL) {
316  return (CS_ERR_NO_MEMORY);
317  }
318  memset (*interface_names, 0, sizeof (char *) * *interface_count);
319 
320  *status = malloc (sizeof (char *) * *interface_count);
321  if (*status == NULL) {
322  error = CS_ERR_NO_MEMORY;
323  goto error_free_interface_names_array;
324  }
325  memset (*status, 0, sizeof (char *) * *interface_count);
326 
327  for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) {
328  (*(interface_names))[i] = strdup (res_lib_cfg_ringstatusget.interface_name[i]);
329  if ((*(interface_names))[i] == NULL) {
330  error = CS_ERR_NO_MEMORY;
331  goto error_free_interface_names;
332  }
333  }
334 
335  for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) {
336  (*(status))[i] = strdup (res_lib_cfg_ringstatusget.interface_status[i]);
337  if ((*(status))[i] == NULL) {
338  error = CS_ERR_NO_MEMORY;
339  goto error_free_status;
340  }
341  }
342  goto no_error;
343 
344 error_free_status:
345  for (j = 0; j < i; j++) {
346  free ((*(status))[j]);
347  }
348  i = *interface_count;
349 
350 error_free_interface_names:
351  for (j = 0; j < i; j++) {
352  free ((*(interface_names))[j]);
353  }
354 
355  free (*status);
356 
357 error_free_interface_names_array:
358  free (*interface_names);
359 
360 no_error:
361  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
362 
363  return (error);
364 }
365 
368  corosync_cfg_handle_t cfg_handle)
369 {
370  struct cfg_inst *cfg_inst;
371  struct req_lib_cfg_ringreenable req_lib_cfg_ringreenable;
372  struct res_lib_cfg_ringreenable res_lib_cfg_ringreenable;
373  cs_error_t error;
374  struct iovec iov;
375 
376  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst));
377  if (error != CS_OK) {
378  return (error);
379  }
380 
381  req_lib_cfg_ringreenable.header.size = sizeof (struct req_lib_cfg_ringreenable);
382  req_lib_cfg_ringreenable.header.id = MESSAGE_REQ_CFG_RINGREENABLE;
383 
384  iov.iov_base = (void *)&req_lib_cfg_ringreenable,
385  iov.iov_len = sizeof (struct req_lib_cfg_ringreenable);
386 
387  error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
388  &iov,
389  1,
390  &res_lib_cfg_ringreenable,
391  sizeof (struct res_lib_cfg_ringreenable), CS_IPC_TIMEOUT_MS));
392 
393  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
394 
395  return (error);
396 }
397 
400  corosync_cfg_handle_t cfg_handle,
401  unsigned int nodeid,
402  const char *reason)
403 {
404  struct cfg_inst *cfg_inst;
405  struct req_lib_cfg_killnode req_lib_cfg_killnode;
406  struct res_lib_cfg_killnode res_lib_cfg_killnode;
407  cs_error_t error;
408  struct iovec iov;
409 
410  if (strlen(reason) >= CS_MAX_NAME_LENGTH)
411  return CS_ERR_NAME_TOO_LONG;
412 
413  error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle,
414  (void *)&cfg_inst));
415  if (error != CS_OK) {
416  return (error);
417  }
418 
419  req_lib_cfg_killnode.header.id = MESSAGE_REQ_CFG_KILLNODE;
420  req_lib_cfg_killnode.header.size = sizeof (struct req_lib_cfg_killnode);
421  req_lib_cfg_killnode.nodeid = nodeid;
422  strcpy((char *)req_lib_cfg_killnode.reason.value, reason);
423  req_lib_cfg_killnode.reason.length = strlen(reason)+1;
424 
425  iov.iov_base = (void *)&req_lib_cfg_killnode;
426  iov.iov_len = sizeof (struct req_lib_cfg_killnode);
427 
428  error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
429  &iov,
430  1,
431  &res_lib_cfg_killnode,
432  sizeof (struct res_lib_cfg_killnode), CS_IPC_TIMEOUT_MS));
433 
434  error = res_lib_cfg_killnode.header.error;
435 
436  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
437 
438  return (error == CS_OK ? res_lib_cfg_killnode.header.error : error);
439 }
440 
443  corosync_cfg_handle_t cfg_handle,
445 {
446  struct cfg_inst *cfg_inst;
447  struct req_lib_cfg_tryshutdown req_lib_cfg_tryshutdown;
448  struct res_lib_cfg_tryshutdown res_lib_cfg_tryshutdown;
449  cs_error_t error;
450  struct iovec iov;
451 
452  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle,
453  (void *)&cfg_inst));
454  if (error != CS_OK) {
455  return (error);
456  }
457 
458  req_lib_cfg_tryshutdown.header.id = MESSAGE_REQ_CFG_TRYSHUTDOWN;
459  req_lib_cfg_tryshutdown.header.size = sizeof (struct req_lib_cfg_tryshutdown);
460  req_lib_cfg_tryshutdown.flags = flags;
461 
462  iov.iov_base = (void *)&req_lib_cfg_tryshutdown;
463  iov.iov_len = sizeof (req_lib_cfg_tryshutdown);
464 
465  error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
466  &iov,
467  1,
468  &res_lib_cfg_tryshutdown,
469  sizeof (struct res_lib_cfg_tryshutdown), CS_IPC_TIMEOUT_MS));
470 
471  (void)hdb_handle_put (&cfg_hdb, cfg_handle);
472 
473  return (error == CS_OK ? res_lib_cfg_tryshutdown.header.error : error);
474 }
475 
478  corosync_cfg_handle_t cfg_handle,
480 {
481  struct cfg_inst *cfg_inst;
482  struct req_lib_cfg_replytoshutdown req_lib_cfg_replytoshutdown;
483  struct res_lib_cfg_replytoshutdown res_lib_cfg_replytoshutdown;
484  struct iovec iov;
485  cs_error_t error;
486 
487  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle,
488  (void *)&cfg_inst));
489  if (error != CS_OK) {
490  return (error);
491  }
492 
493  req_lib_cfg_replytoshutdown.header.id = MESSAGE_REQ_CFG_REPLYTOSHUTDOWN;
494  req_lib_cfg_replytoshutdown.header.size = sizeof (struct req_lib_cfg_replytoshutdown);
495  req_lib_cfg_replytoshutdown.response = response;
496 
497  iov.iov_base = (void *)&req_lib_cfg_replytoshutdown;
498  iov.iov_len = sizeof (struct req_lib_cfg_replytoshutdown);
499 
500  error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
501  &iov,
502  1,
503  &res_lib_cfg_replytoshutdown,
504  sizeof (struct res_lib_cfg_replytoshutdown), CS_IPC_TIMEOUT_MS));
505 
506  return (error);
507 }
508 
510  corosync_cfg_handle_t cfg_handle,
511  int nodeid,
512  size_t max_addrs,
513  int *num_addrs,
515 {
516  cs_error_t error;
517  struct req_lib_cfg_get_node_addrs req_lib_cfg_get_node_addrs;
519  struct cfg_inst *cfg_inst;
520  int addrlen = 0;
521  int i;
522  struct iovec iov;
523  const char *addr_buf;
524  char response_buf[IPC_RESPONSE_SIZE];
525 
526  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle,
527  (void *)&cfg_inst));
528  if (error != CS_OK) {
529  return (error);
530  }
531 
532  req_lib_cfg_get_node_addrs.header.size = sizeof (req_lib_cfg_get_node_addrs);
533  req_lib_cfg_get_node_addrs.header.id = MESSAGE_REQ_CFG_GET_NODE_ADDRS;
534  req_lib_cfg_get_node_addrs.nodeid = nodeid;
535 
536  iov.iov_base = (char *)&req_lib_cfg_get_node_addrs;
537  iov.iov_len = sizeof (req_lib_cfg_get_node_addrs);
538 
539  error = qb_to_cs_error (qb_ipcc_sendv_recv (
540  cfg_inst->c,
541  &iov, 1,
542  response_buf, IPC_RESPONSE_SIZE, CS_IPC_TIMEOUT_MS));
543  res_lib_cfg_get_node_addrs = (struct res_lib_cfg_get_node_addrs *)response_buf;
544 
545  if (error != CS_OK) {
546  goto error_put;
547  }
548 
549  if (res_lib_cfg_get_node_addrs->family == AF_INET)
550  addrlen = sizeof(struct sockaddr_in);
551  if (res_lib_cfg_get_node_addrs->family == AF_INET6)
552  addrlen = sizeof(struct sockaddr_in6);
553 
554  for (i = 0, addr_buf = (char *)res_lib_cfg_get_node_addrs->addrs;
555  i < max_addrs && i<res_lib_cfg_get_node_addrs->num_addrs;
556  i++, addr_buf += TOTEMIP_ADDRLEN) {
557  struct sockaddr_in *in;
558  struct sockaddr_in6 *in6;
559 
560  addrs[i].address_length = addrlen;
561 
562  if (res_lib_cfg_get_node_addrs->family == AF_INET) {
563  in = (struct sockaddr_in *)addrs[i].address;
564  in->sin_family = AF_INET;
565  memcpy(&in->sin_addr, addr_buf, sizeof(struct in_addr));
566  }
567  if (res_lib_cfg_get_node_addrs->family == AF_INET6) {
568  in6 = (struct sockaddr_in6 *)addrs[i].address;
569  in6->sin6_family = AF_INET6;
570  memcpy(&in6->sin6_addr, addr_buf, sizeof(struct in6_addr));
571  }
572  }
573  *num_addrs = res_lib_cfg_get_node_addrs->num_addrs;
574  errno = error = res_lib_cfg_get_node_addrs->header.error;
575 
576 error_put:
577  hdb_handle_put (&cfg_hdb, cfg_handle);
578 
579  return (error);
580 }
581 
583  corosync_cfg_handle_t handle,
584  unsigned int *local_nodeid)
585 {
586  cs_error_t error;
587  struct cfg_inst *cfg_inst;
588  struct iovec iov;
589  struct req_lib_cfg_local_get req_lib_cfg_local_get;
590  struct res_lib_cfg_local_get res_lib_cfg_local_get;
591 
592  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, handle, (void *)&cfg_inst));
593  if (error != CS_OK) {
594  return (error);
595  }
596 
597  req_lib_cfg_local_get.header.size = sizeof (struct qb_ipc_request_header);
598  req_lib_cfg_local_get.header.id = MESSAGE_REQ_CFG_LOCAL_GET;
599 
600  iov.iov_base = (void *)&req_lib_cfg_local_get;
601  iov.iov_len = sizeof (struct req_lib_cfg_local_get);
602 
603  error = qb_to_cs_error (qb_ipcc_sendv_recv (
604  cfg_inst->c,
605  &iov,
606  1,
607  &res_lib_cfg_local_get,
608  sizeof (struct res_lib_cfg_local_get), CS_IPC_TIMEOUT_MS));
609 
610  if (error != CS_OK) {
611  goto error_exit;
612  }
613 
614  error = res_lib_cfg_local_get.header.error;
615 
616  *local_nodeid = res_lib_cfg_local_get.local_nodeid;
617 
618 error_exit:
619  (void)hdb_handle_put (&cfg_hdb, handle);
620 
621  return (error);
622 }
623 
625  corosync_cfg_handle_t handle)
626 {
627  cs_error_t error;
628  struct cfg_inst *cfg_inst;
629  struct iovec iov;
630  struct req_lib_cfg_reload_config req_lib_cfg_reload_config;
631  struct res_lib_cfg_reload_config res_lib_cfg_reload_config;
632 
633  error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, handle, (void *)&cfg_inst));
634  if (error != CS_OK) {
635  return (error);
636  }
637 
638  req_lib_cfg_reload_config.header.size = sizeof (struct qb_ipc_request_header);
639  req_lib_cfg_reload_config.header.id = MESSAGE_REQ_CFG_RELOAD_CONFIG;
640 
641  iov.iov_base = (void *)&req_lib_cfg_reload_config;
642  iov.iov_len = sizeof (struct req_lib_cfg_reload_config);
643 
644  error = qb_to_cs_error (qb_ipcc_sendv_recv (
645  cfg_inst->c,
646  &iov,
647  1,
648  &res_lib_cfg_reload_config,
649  sizeof (struct res_lib_cfg_reload_config), CS_IPC_TIMEOUT_MS));
650 
651  if (error != CS_OK) {
652  goto error_exit;
653  }
654 
655  error = res_lib_cfg_reload_config.header.error;
656 
657 error_exit:
658  (void)hdb_handle_put (&cfg_hdb, handle);
659 
660  return (error);
661 }