From: Martin Willi Date: Tue, 22 Sep 2009 12:32:52 +0000 (+0200) Subject: Segment manipulation in HA sync is thread save X-Git-Tag: 4.4.0~85 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3d672d4b0a7e995a949d6306b01fa9c30d5a12bb;p=thirdparty%2Fstrongswan.git Segment manipulation in HA sync is thread save --- diff --git a/src/charon/plugins/ha_sync/ha_sync_segments.c b/src/charon/plugins/ha_sync/ha_sync_segments.c index 90897a3d6f..017c058daf 100644 --- a/src/charon/plugins/ha_sync/ha_sync_segments.c +++ b/src/charon/plugins/ha_sync/ha_sync_segments.c @@ -15,6 +15,7 @@ #include "ha_sync_segments.h" +#include #include typedef u_int32_t u32; @@ -36,6 +37,11 @@ struct private_ha_sync_segments_t { */ ha_sync_segments_t public; + /** + * read/write lock for segment manipulation + */ + rwlock_t *lock; + /** * Init value for jhash */ @@ -121,6 +127,8 @@ static void enable_disable(private_ha_sync_segments_t *this, u_int segment, enumerator_t *enumerator; u_int i, limit; + this->lock->write_lock(this->lock); + if (segment == 0 || segment <= this->segment_count) { if (segment) @@ -160,6 +168,8 @@ static void enable_disable(private_ha_sync_segments_t *this, u_int segment, log_segments(this, enable, segment); } + + this->lock->unlock(this->lock); } /** @@ -213,10 +223,12 @@ static void resync(private_ha_sync_segments_t *this, u_int segment) ike_sa_id_t *id; u_int16_t mask = bit_of(segment); + list = linked_list_create(); + this->lock->read_lock(this->lock); + if (segment > 0 && segment <= this->segment_count && (this->active & mask)) { this->active &= ~mask; - list = linked_list_create(); DBG1(DBG_CFG, "resyncing HA sync segment %d", segment); @@ -234,29 +246,30 @@ static void resync(private_ha_sync_segments_t *this, u_int segment) } } enumerator->destroy(enumerator); + } + this->lock->unlock(this->lock); - while (list->remove_last(list, (void**)&id) == SUCCESS) + while (list->remove_last(list, (void**)&id) == SUCCESS) + { + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); + id->destroy(id); + if (ike_sa) { - ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); - id->destroy(id); - if (ike_sa) + DBG1(DBG_CFG, "resyncing IKE_SA"); + if (ike_sa->rekey(ike_sa) != DESTROY_ME) { - DBG1(DBG_CFG, "resyncing IKE_SA"); - if (ike_sa->rekey(ike_sa) != DESTROY_ME) + if (rekey_children(ike_sa) != DESTROY_ME) { - if (rekey_children(ike_sa) != DESTROY_ME) - { - charon->ike_sa_manager->checkin( - charon->ike_sa_manager, ike_sa); - continue; - } + charon->ike_sa_manager->checkin( + charon->ike_sa_manager, ike_sa); + continue; } - charon->ike_sa_manager->checkin_and_destroy( - charon->ike_sa_manager, ike_sa); } + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); } - list->destroy(list); } + list->destroy(list); } /** @@ -264,6 +277,7 @@ static void resync(private_ha_sync_segments_t *this, u_int segment) */ static void destroy(private_ha_sync_segments_t *this) { + this->lock->destroy(this->lock); free(this); } @@ -282,6 +296,7 @@ ha_sync_segments_t *ha_sync_segments_create() this->public.resync = (void(*)(ha_sync_segments_t*, u_int segment))resync; this->public.destroy = (void(*)(ha_sync_segments_t*))destroy; + this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); this->initval = 0; this->active = 0; this->segment_count = lib->settings->get_int(lib->settings,