Currently exec_exit_fn doesn't allow the possibility to continue work at
a later time. Service engines can deadlock if they block (pacemaker
specifically). To avoid this situation, we allow exec_exit_fn to return
-1 when it has work it needs to continue. When it is done, it returns 0
and will be unloaded.
Still a work in progress (ie individual service engine unload doesn't
work from corosync-cfgtool).
Regards
-steve
Index: exec/service.c
===================================================================
--- exec/service.c (revision 2517)
+++ exec/service.c (working copy)
@@ -249,88 +249,91 @@
static int service_priority_max(void)
{
- int lpc = 0, max = 0;
- for(; lpc < SERVICE_HANDLER_MAXIMUM_COUNT; lpc++) {
- if(ais_service[lpc] != NULL && ais_service[lpc]->priority > max) {
- max = ais_service[lpc]->priority;
+ int lpc = 0, max = 0;
+ for(; lpc < SERVICE_HANDLER_MAXIMUM_COUNT; lpc++) {
+ if(ais_service[lpc] != NULL && ais_service[lpc]->priority > max) {
+ max = ais_service[lpc]->priority;
+ }
}
- }
- return max;
+ return max;
}
-extern unsigned int corosync_service_unlink_priority (struct corosync_api_v1 *corosync_api, int priority)
+/*
+ * use the force
+ */
+static unsigned int
+corosync_service_unlink_priority (
+ struct corosync_api_v1 *corosync_api,
+ int lowest_priority,
+ int *current_priority,
+ int *current_service_engine)
{
- char *service_name;
- unsigned int *service_ver;
unsigned short *service_id;
hdb_handle_t object_service_handle;
hdb_handle_t object_find_handle;
- int p = service_priority_max();
- int lpc = 0;
+ hdb_handle_t *found_service_handle;
- if(priority == 0) {
- log_printf(LOGSYS_LEVEL_NOTICE, "Unloading all corosync components\n");
- } else {
- log_printf(LOGSYS_LEVEL_NOTICE, "Unloading corosync components up to (and including) priority %d\n", priority);
- }
+ for(; *current_priority >= lowest_priority; *current_priority = *current_priority - 1) {
+ for(*current_service_engine = 0;
+ *current_service_engine < SERVICE_HANDLER_MAXIMUM_COUNT;
+ *current_service_engine = *current_service_engine + 1) {
- for( ; p >= priority; p--) {
- for(lpc = 0; lpc < SERVICE_HANDLER_MAXIMUM_COUNT; lpc++) {
- if(ais_service[lpc] == NULL || ais_service[lpc]->priority != p) {
- continue;
- }
+ if(ais_service[*current_service_engine] == NULL ||
+ ais_service[*current_service_engine]->priority != *current_priority) {
+ continue;
+ }
- /* unload
- *
- * If we had a pointer to the objdb entry, we'd not need to go looking again...
- */
- corosync_api->object_find_create (
- object_internal_configuration_handle,
- "service", strlen ("service"), &object_find_handle);
+ /*
+ * find service object in object database by service id
+ * and unload it if possible.
+ *
+ * If the service engine's exec_exit_fn returns -1 indicating
+ * it was busy, this function returns -1 and can be called again
+ * at a later time (usually via the schedwrk api).
+ */
+ corosync_api->object_find_create (
+ object_internal_configuration_handle,
+ "service", strlen ("service"), &object_find_handle);
- while(corosync_api->object_find_next (
- object_find_handle, &object_service_handle) == 0) {
+ while (corosync_api->object_find_next (
+ object_find_handle, &object_service_handle) == 0) {
- int res = corosync_api->object_key_get (
- object_service_handle,
- "service_id", strlen ("service_id"), (void *)&service_id, NULL);
+ int res = corosync_api->object_key_get (
+ object_service_handle,
+ "service_id", strlen ("service_id"),
+ (void *)&service_id, NULL);
- service_name = NULL;
- if(res == 0 && *service_id == ais_service[lpc]->id) {
- hdb_handle_t *found_service_handle;
- corosync_api->object_key_get (
- object_service_handle,
- "name", strlen ("name"), (void *)&service_name, NULL);
+ if (res == 0 && *service_id ==
+ ais_service[*current_service_engine]->id) {
- corosync_api->object_key_get (
- object_service_handle,
- "ver", strlen ("ver"), (void *)&service_ver, NULL);
+ if (ais_service[*service_id]->exec_exit_fn) {
+ res = ais_service[*service_id]->exec_exit_fn ();
+ if (res == -1) {
+ corosync_api->object_find_destroy (object_find_handle);
+ return (-1);
+ }
+ }
+ log_printf(LOGSYS_LEVEL_NOTICE,
+ "Unloading corosync component: %s\n",
+ ais_service[*current_service_engine]->name);
- res = corosync_api->object_key_get (
- object_service_handle,
- "handle", strlen ("handle"), (void *)&found_service_handle, NULL);
+ ais_service[*current_service_engine] = NULL;
- res = corosync_api->object_key_get (
- object_service_handle,
- "service_id", strlen ("service_id"), (void *)&service_id, NULL);
+ res = corosync_api->object_key_get (
+ object_service_handle,
+ "handle", strlen ("handle"),
+ (void *)&found_service_handle,
+ NULL);
- log_printf(LOGSYS_LEVEL_NOTICE, "Unloading corosync component: %s v%u\n",
- service_name, *service_ver);
+ lcr_ifact_release (*found_service_handle);
- if (ais_service[*service_id]->exec_exit_fn) {
- ais_service[*service_id]->exec_exit_fn ();
+ corosync_api->object_destroy (object_service_handle);
+ break;
+ }
}
- ais_service[*service_id] = NULL;
- lcr_ifact_release (*found_service_handle);
-
- corosync_api->object_destroy (object_service_handle);
- break;
- }
+ corosync_api->object_find_destroy (object_find_handle);
}
-
- corosync_api->object_find_destroy (object_find_handle);
- }
}
return 0;
}
@@ -345,7 +348,9 @@
unsigned short *service_id;
unsigned int *found_service_ver;
hdb_handle_t object_find_handle;
+ hdb_handle_t *found_service_handle;
char *name_sufix;
+ int res;
name_sufix = strrchr (service_name, '_');
if (name_sufix)
@@ -398,21 +403,43 @@
* If service found and linked exit it
*/
if (service_ver != *found_service_ver) {
- continue;
+ continue;
}
corosync_api->object_key_get (
- object_service_handle,
- "service_id", strlen ("service_id"),
- (void *)&service_id, NULL);
+ object_service_handle,
+ "service_id", strlen ("service_id"),
+ (void *)&service_id, NULL);
if(service_id != NULL
- && *service_id > 0
- && *service_id < SERVICE_HANDLER_MAXIMUM_COUNT
- && ais_service[*service_id] != NULL) {
+ && *service_id > 0
+ && *service_id < SERVICE_HANDLER_MAXIMUM_COUNT
+ && ais_service[*service_id] != NULL) {
- corosync_api->object_find_destroy (object_find_handle);
- return corosync_service_unlink_priority (corosync_api, ais_service[*service_id]->priority);
+ corosync_api->object_find_destroy (object_find_handle);
+
+ if (ais_service[*service_id]->exec_exit_fn) {
+ res = ais_service[*service_id]->exec_exit_fn ();
+ if (res == -1) {
+ return (-1);
+ }
+ }
+
+ log_printf(LOGSYS_LEVEL_NOTICE,
+ "Unloading corosync component: %s\n",
+ ais_service[*service_id]->name);
+
+ ais_service[*service_id] = NULL;
+
+ res = corosync_api->object_key_get (
+ object_service_handle,
+ "handle", strlen ("handle"),
+ (void *)&found_service_handle,
+ NULL);
+
+ lcr_ifact_release (*found_service_handle);
+
+ corosync_api->object_destroy (object_service_handle);
}
}
@@ -424,7 +451,25 @@
extern unsigned int corosync_service_unlink_all (
struct corosync_api_v1 *corosync_api)
{
- return corosync_service_unlink_priority (corosync_api, 0);
+ static int current_priority = 0;
+ static int current_service_engine = 0;
+ static int called = 0;
+ int res;
+
+ if (called == 0) {
+ log_printf(LOGSYS_LEVEL_NOTICE,
+ "Unloading all corosync components.\n");
+ current_priority = service_priority_max ();
+ called = 1;
+ }
+
+ res = corosync_service_unlink_priority (
+ corosync_api,
+ 0,
+ ¤t_priority,
+ ¤t_service_engine);
+
+ return (res);
}
/*
Index: exec/service.h
===================================================================
--- exec/service.h (revision 2517)
+++ exec/service.h (working copy)
@@ -47,13 +47,6 @@
unsigned int service_ver);
/*
- * Unlink and exit a service based on service priority
- */
-extern unsigned int corosync_service_unlink_priority (
- struct corosync_api_v1 *corosync_api,
- int priority);
-
-/*
* Unlink and exit a service
*/
extern unsigned int corosync_service_unlink_and_exit (
Index: exec/main.c
===================================================================
--- exec/main.c (revision 2517)
+++ exec/main.c (working copy)
@@ -158,20 +158,44 @@
corosync_state_dump ();
}
-/*
- * TODO this function needs some love
- */
+static int shutdown_request_handler (const void *data) {
+ int res;
+
+ res = corosync_service_unlink_all (api);
+ if (res == 0) {
+ poll_stop (0);
+ totempg_finalize ();
+ coroipcs_ipc_exit ();
+
+ corosync_exit_error (AIS_DONE_EXIT);
+ }
+ return (res);
+}
+
+static hdb_handle_t shutdown_request_handle;
+
void corosync_shutdown_request (void)
{
+ static int called = 0;
+ if (called) {
+ printf ("called shutdown request twice\n");
+ return;
+ }
+ if (called == 0) {
+ called = 1;
+ }
+
if (api) {
- corosync_service_unlink_all (api);
+ api->schedwrk_create (&shutdown_request_handle,
+ shutdown_request_handler,
+ NULL);
+ } else {
+ poll_stop (0);
+ totempg_finalize ();
+ coroipcs_ipc_exit ();
+
+ corosync_exit_error (AIS_DONE_EXIT);
}
-
- poll_stop (0);
- totempg_finalize ();
- coroipcs_ipc_exit ();
-
- corosync_exit_error (AIS_DONE_EXIT);
}
static void sigquit_handler (int num)
_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais