From mboxrd@z Thu Jan 1 00:00:00 1970 From: lhh@sourceware.org Date: 19 Apr 2007 18:05:37 -0000 Subject: [Cluster-devel] cluster/rgmanager ChangeLog src/daemons/groups ... Message-ID: <20070419180537.28847.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: cluster Branch: RHEL5 Changes by: lhh at sourceware.org 2007-04-19 19:05:37 Modified files: rgmanager : ChangeLog rgmanager/src/daemons: groups.c rg_state.c Log message: Apply patch from Andrey Mirkin to fix 237144 Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/ChangeLog.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.31.2.1&r2=1.31.2.2 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/groups.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.25.2.3&r2=1.25.2.4 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/rg_state.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.24.2.5&r2=1.24.2.6 --- cluster/rgmanager/ChangeLog 2007/04/12 17:23:05 1.31.2.1 +++ cluster/rgmanager/ChangeLog 2007/04/19 18:05:36 1.31.2.2 @@ -1,3 +1,9 @@ +2007-04-19 Lon Hohberger + * src/daemons/groups.c, rg_state.c: Apply patch from Andrey + Mirkin to fix bug #237144; prevents exclusive services from + being accidentally (or intentionally) being started on the + same node + 2007-04-12 Lon Hohberger * src/daemons/main.c: Fix watchdog race condition causing reboot; patch from Andrey Mirkin; bugzilla #236204 --- cluster/rgmanager/src/daemons/groups.c 2007/03/20 17:09:11 1.25.2.3 +++ cluster/rgmanager/src/daemons/groups.c 2007/04/19 18:05:37 1.25.2.4 @@ -20,6 +20,7 @@ //#define DEBUG #include #include +#include #include #include #include @@ -138,6 +139,105 @@ } +int +count_resource_groups_local(cman_node_t *mp) +{ + resource_t *res; + resource_node_t *node; + char rgname[64], *val; + rg_state_t st; + + mp->cn_svccount = 0; + mp->cn_svcexcl = 0; + + pthread_rwlock_rdlock(&resource_lock); + + list_do(&_tree, node) { + + res = node->rn_resource; + + res_build_name(rgname, sizeof(rgname), res); + + if (get_rg_state_local(rgname, &st) < 0) { + continue; + } + + if (st.rs_state != RG_STATE_STARTED && + st.rs_state != RG_STATE_STARTING) + continue; + + if (mp->cn_nodeid != st.rs_owner) + continue; + + ++mp->cn_svccount; + + val = res_attr_value(res, "exclusive"); + if (val && ((!strcmp(val, "yes") || + (atoi(val)>0))) ) { + ++mp->cn_svcexcl; + } + + } while (!list_done(&_tree, node)); + + pthread_rwlock_unlock(&resource_lock); + return 0; +} + + +int +have_exclusive_resources(void) +{ + resource_t *res; + char *val; + + pthread_rwlock_rdlock(&resource_lock); + + list_do(&_resources, res) { + val = res_attr_value(res, "exclusive"); + if (val && ((!strcmp(val, "yes") || + (atoi(val)>0))) ) { + pthread_rwlock_unlock(&resource_lock); + return 1; + } + + } while (!list_done(&_resources, res)); + + pthread_rwlock_unlock(&resource_lock); + + return 0; +} + + +int +check_exclusive_resources(cluster_member_list_t *membership, char *svcName) +{ + cman_node_t *mp; + int exclusive, count; + resource_t *res; + char *val; + + mp = memb_id_to_p(membership, my_id()); + assert(mp); + count_resource_groups_local(mp); + exclusive = mp->cn_svcexcl; + count = mp->cn_svccount; + pthread_rwlock_rdlock(&resource_lock); + res = find_root_by_ref(&_resources, svcName); + if (!res) { + pthread_rwlock_unlock(&resource_lock); + return RG_EFAIL; + } + val = res_attr_value(res, "exclusive"); + pthread_rwlock_unlock(&resource_lock); + if (exclusive || (count && val && + (!strcmp(val, "yes") || (atoi(val)>0)))) { + return RG_YES; + } + + return 0; +} + + /** Find the best target node for a service *besides* the current service owner. Takes into account: --- cluster/rgmanager/src/daemons/rg_state.c 2007/03/20 17:09:11 1.24.2.5 +++ cluster/rgmanager/src/daemons/rg_state.c 2007/04/19 18:05:37 1.24.2.6 @@ -48,6 +48,8 @@ void get_recovery_policy(char *rg_name, char *buf, size_t buflen); int check_depend_safe(char *servicename); int group_migratory(char *servicename, int lock); +int have_exclusive_resources(void); +int check_exclusive_resources(cluster_member_list_t *membership, char *svcName); int @@ -687,6 +689,10 @@ ret = 1; break; } + if (req == RG_START_RECOVER) { + ret = 1; + break; + } clulog(LOG_DEBUG, "Not starting disabled RG %s\n", svcName); @@ -1463,6 +1469,7 @@ } +pthread_mutex_t exclusive_mutex = PTHREAD_MUTEX_INITIALIZER; /** * handle_start_req - Handle a generic start request from a user or during * service manager boot. @@ -1478,6 +1485,7 @@ { int ret, tolerance = FOD_BEST; cluster_member_list_t *membership = member_list(); + int need_check = have_exclusive_resources(); /* * When a service request is from a user application (eg, clusvcadm), @@ -1493,6 +1501,18 @@ free_member_list(membership); return RG_EFAIL; } + if (need_check) { + pthread_mutex_lock(&exclusive_mutex); + ret = check_exclusive_resources(membership, svcName); + if (ret != 0) { + free_member_list(membership); + pthread_mutex_unlock(&exclusive_mutex); + if (ret > 0) + goto relocate; + else + return RG_EFAIL; + } + } free_member_list(membership); /* Check for dependency. We cannot start unless our @@ -1505,6 +1525,8 @@ * mask here - so that we can try all nodes if necessary. */ ret = svc_start(svcName, req); + if (need_check) + pthread_mutex_unlock(&exclusive_mutex); /* If services are locked, return the error @@ -1544,6 +1566,7 @@ return RG_EABORT; } +relocate: /* * OK, it failed to start - but succeeded to stop. Now, * we should relocate the service. @@ -1581,6 +1604,7 @@ int x; uint32_t me = my_id(); cluster_member_list_t *membership = member_list(); + int need_check = have_exclusive_resources(); /* XXX ok, so we need to say "should I start this if I was the only cluster member online */ @@ -1601,10 +1625,23 @@ free_member_list(membership); return RG_EFAIL; } + if (need_check) { + pthread_mutex_lock(&exclusive_mutex); + if (check_exclusive_resources(membership, svcName) != 0) { + free_member_list(membership); + pthread_mutex_unlock(&exclusive_mutex); + return RG_EFAIL; + } + } free_member_list(membership); - if (svc_start(svcName, req) == 0) + if (svc_start(svcName, req) == 0) { + if (need_check) + pthread_mutex_unlock(&exclusive_mutex); return 0; + } + if (need_check) + pthread_mutex_unlock(&exclusive_mutex); if (svc_stop(svcName, RG_STOP_RECOVER) == 0) return RG_EFAIL;