From 6356d191a6d97483ad904fa1c8279a30564220cf Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 1 Aug 2008 14:35:47 +0200 Subject: fix broken normal deletion in caches This patch fixes the non-timer-based cache deletion. This bug affects the alarm-based approach since the backup replicas did not get the deletion event, thus, delaying the deletion. This patch introduces cache_find() to look up for a conntrack object and __cache_del_timer() to perform direct deletions by means of the pointer obtained with cache_find(). Signed-off-by: Pablo Neira Ayuso --- include/cache.h | 3 ++- src/cache.c | 62 ++++++++++++++++++++++++++++----------------------------- src/sync-mode.c | 19 +++++++++--------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/include/cache.h b/include/cache.h index 442a563..e2e2e34 100644 --- a/include/cache.h +++ b/include/cache.h @@ -82,7 +82,8 @@ struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct); struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct); struct us_conntrack *cache_update_force(struct cache *c, struct nf_conntrack *ct); int cache_del(struct cache *c, struct nf_conntrack *ct); -struct us_conntrack *cache_del_timeout(struct cache *c, struct nf_conntrack *ct, int timeout); +int __cache_del_timer(struct cache *c, struct us_conntrack *u, int timeout); +struct us_conntrack *cache_find(struct cache *c, struct nf_conntrack *ct); int cache_test(struct cache *c, struct nf_conntrack *ct); void cache_stats(const struct cache *c, int fd); struct us_conntrack *cache_get_conntrack(struct cache *, void *); diff --git a/src/cache.c b/src/cache.c index a73854f..7cd5ac7 100644 --- a/src/cache.c +++ b/src/cache.c @@ -321,7 +321,13 @@ static void __del2(struct cache *c, struct us_conntrack *u) free(p); } -static int __del(struct cache *c, struct nf_conntrack *ct) +static void __cache_del(struct cache *c, struct us_conntrack *u) +{ + del_alarm(&u->alarm); + __del2(c, u); +} + +int cache_del(struct cache *c, struct nf_conntrack *ct) { size_t size = c->h->datasize; char buf[size]; @@ -331,16 +337,7 @@ static int __del(struct cache *c, struct nf_conntrack *ct) u = (struct us_conntrack *) hashtable_test(c->h, u); if (u) { - del_alarm(&u->alarm); - __del2(c, u); - return 1; - } - return 0; -} - -int cache_del(struct cache *c, struct nf_conntrack *ct) -{ - if (__del(c, ct)) { + __cache_del(c, u); c->del_ok++; return 1; } @@ -356,33 +353,36 @@ static void __del_timeout(struct alarm_block *a, void *data) __del2(u->cache, u); } -struct us_conntrack * -cache_del_timeout(struct cache *c, struct nf_conntrack *ct, int timeout) +int +__cache_del_timer(struct cache *c, struct us_conntrack *u, int timeout) +{ + if (timeout <= 0) { + __cache_del(c, u); + return 1; + } + if (!alarm_pending(&u->alarm)) { + add_alarm(&u->alarm, timeout, 0); + /* + * increase stats even if this entry was not really + * removed yet. We do not want to make people think + * that the replication protocol does not work + * properly. + */ + c->del_ok++; + return 1; + } + return 0; +} + +struct us_conntrack *cache_find(struct cache *c, struct nf_conntrack *ct) { size_t size = c->h->datasize; char buf[size]; struct us_conntrack *u = (struct us_conntrack *) buf; - if (timeout <= 0) - cache_del(c, ct); - u->ct = ct; - u = (struct us_conntrack *) hashtable_test(c->h, u); - if (u) { - if (!alarm_pending(&u->alarm)) { - add_alarm(&u->alarm, timeout, 0); - /* - * increase stats even if this entry was not really - * removed yet. We do not want to make people think - * that the replication protocol does not work - * properly. - */ - c->del_ok++; - return u; - } - } - return NULL; + return ((struct us_conntrack *) hashtable_test(c->h, u)); } struct us_conntrack *cache_get_conntrack(struct cache *c, void *data) diff --git a/src/sync-mode.c b/src/sync-mode.c index 0f3760e..56c30af 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -407,10 +407,8 @@ static int purge_step(void *data1, void *data2) ret = nfct_query(h, NFCT_Q_GET, u->ct); if (ret == -1 && errno == ENOENT) { debug_ct(u->ct, "overrun purge resync"); - if (cache_del_timeout(STATE_SYNC(internal), - u->ct, - CONFIG(del_timeout))) - mcast_send_sync(u, NFCT_Q_DESTROY); + mcast_send_sync(u, NFCT_Q_DESTROY); + __cache_del_timer(STATE_SYNC(internal), u, CONFIG(del_timeout)); } return 0; @@ -502,15 +500,16 @@ static int event_destroy_sync(struct nf_conntrack *ct) if (!CONFIG(cache_write_through)) nfct_attr_unset(ct, ATTR_TIMEOUT); - u = cache_del_timeout(STATE_SYNC(internal), ct, CONFIG(del_timeout)); - if (u != NULL) { - mcast_send_sync(u, NFCT_Q_DESTROY); - debug_ct(ct, "internal destroy"); - return 1; - } else { + u = cache_find(STATE_SYNC(internal), ct); + if (u == NULL) { debug_ct(ct, "can't destroy"); return 0; } + + mcast_send_sync(u, NFCT_Q_DESTROY); + __cache_del_timer(STATE_SYNC(internal), u, CONFIG(del_timeout)); + debug_ct(ct, "internal destroy"); + return 1; } struct ct_mode sync_mode = { -- cgit v1.2.3