]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
markdelfunc for lock order problem in lruhash reclaim().
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 4 Dec 2007 21:18:25 +0000 (21:18 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 4 Dec 2007 21:18:25 +0000 (21:18 +0000)
git-svn-id: file:///svn/unbound/trunk@804 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/cache/rrset.c
util/storage/lruhash.c
util/storage/lruhash.h
util/storage/slabhash.c
util/storage/slabhash.h

index 24917b1e6f29ecb7f8d635687a0680a243b6487b..d093aa8c87e3100679d98bef39a53543934ef6a4 100644 (file)
@@ -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.
index 6433863dcc062b5a3936b0e91c50b7d732e62773..14399ad7200445fbe1de6f935ff3514986d1b5a3 100644 (file)
 #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;
 }
 
index 3c85f60e040fdf179dbc35cadf6e900410c97ec3..ff16aca4ec794a38b6a928da5fe8f6b9ed448a18 100644 (file)
@@ -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);
+}
index b0a36eb6749854ed63fcd14751232df0cc805b81..7a4084a57cddce3d74b6d799e3e892d5553668d1 100644 (file)
@@ -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. ***/
 
index 8e7bb0b610f66555c081ce3ccebc3262f0a9bb41..71292d495388bd88bc5909fcbcfb68beb5394a16 100644 (file)
@@ -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; i<sl->size; i++) {
+               lruhash_setmarkdel(sl->array[i], md);
+       }
+}
index a7757bd77957e1744ec895f8212a590c6ad8095f..6fd4efb818026c7487a171f4d79a81e7ce9e888c 100644 (file)
@@ -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 {