From: Wouter Wijngaards Date: Tue, 4 Dec 2007 21:18:25 +0000 (+0000) Subject: markdelfunc for lock order problem in lruhash reclaim(). X-Git-Tag: release-0.9~132 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2dbc83d5ae01f79d52a3740fc05b7798c21e2b9a;p=thirdparty%2Funbound.git markdelfunc for lock order problem in lruhash reclaim(). git-svn-id: file:///svn/unbound/trunk@804 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 24917b1e6..d093aa8c8 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -16,6 +16,8 @@ - hardening, if error reply with rcode=0 (noerror) send servfail. - fixup same (*var) error in find_rrset in msgparse, was harmless. - check return value of evtimer_add(). + - fixup lockorder in lruhash_reclaim(), building up a list of locked + entries one at a time. Instead they are removed and unlocked. 3 December 2007: Wouter - changed checkconf/ to smallapp/ to make room for more support tools. diff --git a/services/cache/rrset.c b/services/cache/rrset.c index 6433863dc..14399ad72 100644 --- a/services/cache/rrset.c +++ b/services/cache/rrset.c @@ -47,6 +47,14 @@ #include "util/regional.h" #include "util/alloc.h" +/** mark rrset to be deleted */ +static void +rrset_markdel(void* key) +{ + struct ub_packed_rrset_key* r = (struct ub_packed_rrset_key*)key; + r->id = 0; +} + struct rrset_cache* rrset_cache_create(struct config_file* cfg, struct alloc_cache* alloc) { @@ -57,6 +65,7 @@ struct rrset_cache* rrset_cache_create(struct config_file* cfg, struct rrset_cache *r = (struct rrset_cache*)slabhash_create(slabs, startarray, maxmem, ub_rrset_sizefunc, ub_rrset_compare, ub_rrset_key_delete, rrset_data_delete, alloc); + slabhash_setmarkdel(&r->table, &rrset_markdel); return r; } diff --git a/util/storage/lruhash.c b/util/storage/lruhash.c index 3c85f60e0..ff16aca4e 100644 --- a/util/storage/lruhash.c +++ b/util/storage/lruhash.c @@ -205,6 +205,10 @@ reclaim_space(struct lruhash* table, struct lruhash_entry** list) *list = d; lock_rw_wrlock(&d->lock); table->space_used -= table->sizefunc(d->key, d->data); + if(table->markdelfunc) + /* TODO fptr_wlist it */ + (*table->markdelfunc)(d->key); + lock_rw_unlock(&d->lock); lock_quick_unlock(&bin->lock); } } @@ -341,7 +345,7 @@ lruhash_insert(struct lruhash* table, hashvalue_t hash, while(reclaimlist) { struct lruhash_entry* n = reclaimlist->overflow_next; void* d = reclaimlist->data; - (*table->delkeyfunc)(reclaimlist->key, cb_arg, 1); + (*table->delkeyfunc)(reclaimlist->key, cb_arg, 0); (*table->deldatafunc)(d, cb_arg); reclaimlist = n; } @@ -395,10 +399,14 @@ lruhash_remove(struct lruhash* table, hashvalue_t hash, void* key) table->space_used -= (*table->sizefunc)(entry->key, entry->data); lock_quick_unlock(&table->lock); lock_rw_wrlock(&entry->lock); + if(table->markdelfunc) + /* TODO fptr wlist it */ + (*table->markdelfunc)(entry->key); + lock_rw_unlock(&entry->lock); lock_quick_unlock(&bin->lock); /* finish removal */ d = entry->data; - (*table->delkeyfunc)(entry->key, table->cb_arg, 1); + (*table->delkeyfunc)(entry->key, table->cb_arg, 0); (*table->deldatafunc)(d, table->cb_arg); } @@ -414,7 +422,11 @@ bin_clear(struct lruhash* table, struct lruhash_bin* bin) lock_rw_wrlock(&p->lock); np = p->overflow_next; d = p->data; - (*table->delkeyfunc)(p->key, table->cb_arg, 1); + if(table->markdelfunc) + /* TODO fptr wlist it */ + (*table->markdelfunc)(p->key); + lock_rw_unlock(&p->lock); + (*table->delkeyfunc)(p->key, table->cb_arg, 0); (*table->deldatafunc)(d, table->cb_arg); p = np; } @@ -491,3 +503,11 @@ lruhash_get_mem(struct lruhash* table) s += lock_get_mem(&table->lock); return s; } + +void +lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_t md) +{ + lock_quick_lock(&table->lock); + table->markdelfunc = md; + lock_quick_unlock(&table->lock); +} diff --git a/util/storage/lruhash.h b/util/storage/lruhash.h index b0a36eb67..7a4084a57 100644 --- a/util/storage/lruhash.h +++ b/util/storage/lruhash.h @@ -141,6 +141,10 @@ typedef void (*lruhash_delkeyfunc_t)(void*, void*, int); /** old data is deleted. This function is called: func(data, userarg). */ typedef void (*lruhash_deldatafunc_t)(void*, void*); +/** mark a key as pending to be deleted (and not to be used by anyone). + * called: func(key) */ +typedef void (*lruhash_markdelfunc_t)(void*); + /** * Hash table that keeps LRU list of entries. */ @@ -155,6 +159,8 @@ struct lruhash { lruhash_delkeyfunc_t delkeyfunc; /** how to delete data. */ lruhash_deldatafunc_t deldatafunc; + /** how to mark a key pending deletion */ + lruhash_markdelfunc_t markdelfunc; /** user argument for user functions */ void* cb_arg; @@ -294,6 +300,11 @@ struct lruhash_entry* lruhash_lookup(struct lruhash* table, hashvalue_t hash, */ void lru_touch(struct lruhash* table, struct lruhash_entry* entry); +/** + * Set the markdelfunction (or NULL) + */ +void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_t md); + /************************* Internal functions ************************/ /*** these are only exposed for unit tests. ***/ diff --git a/util/storage/slabhash.c b/util/storage/slabhash.c index 8e7bb0b61..71292d495 100644 --- a/util/storage/slabhash.c +++ b/util/storage/slabhash.c @@ -202,3 +202,11 @@ void test_slabhash_deldata(void* data, void* ATTR_UNUSED(arg)) { deldata((struct slabhash_testdata*)data); } + +void slabhash_setmarkdel(struct slabhash* sl, lruhash_markdelfunc_t md) +{ + size_t i; + for(i=0; isize; i++) { + lruhash_setmarkdel(sl->array[i], md); + } +} diff --git a/util/storage/slabhash.h b/util/storage/slabhash.h index a7757bd77..6fd4efb81 100644 --- a/util/storage/slabhash.h +++ b/util/storage/slabhash.h @@ -167,6 +167,13 @@ size_t slabhash_get_mem(struct slabhash* table); */ struct lruhash* slabhash_gettable(struct slabhash* table, hashvalue_t hash); +/** + * Set markdel function + * @param table: slabbed hash table. + * @param md: markdel function ptr. + */ +void slabhash_setmarkdel(struct slabhash* table, lruhash_markdelfunc_t md); + /* --- test representation --- */ /** test structure contains test key */ struct slabhash_testkey {