]> git.sur5r.net Git - openldap/commitdiff
ITS#6660
authorQuanah Gibson-Mount <quanah@openldap.org>
Tue, 4 Jan 2011 19:28:20 +0000 (19:28 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Tue, 4 Jan 2011 19:28:20 +0000 (19:28 +0000)
CHANGES
servers/slapd/back-bdb/cache.c
servers/slapd/back-bdb/proto-bdb.h

diff --git a/CHANGES b/CHANGES
index 04e64c08da619dc9197319af29a2ecaa9a5388b3..ca91ce3f93d503cf75126eb58e8761c0489db223 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -38,6 +38,7 @@ OpenLDAP 2.4.24 Engineering
        Fixed slapd syncrepl unitialized return code (ITS#6719)
        Fixed slapd-bdb hasSubordinates generation (ITS#6712)
        Fixed slapd-bdb entry cache delete failure (ITS#6577)
+       Fixed slapd-bdb entry cache leak on multi-core systems (ITS#6660)
        Fixed slapd-bdb error propogation to overlays (ITS#6633)
        Fixed slapd-ldap debug output of timeout (ITS#6721)
        Fixed slapd-ldap DNSSRV referral chaining (ITS#6565)
index a42db5c5a20cace55b8d41d309ae599368dbc3aa..df2de17a6092c06745ec3b98f8b0e6c41bb4a09b 100644 (file)
@@ -265,9 +265,8 @@ bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
        int free = 0;
 
        ei = e->e_private;
-       if ( ei &&
-               ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) &&
-               ( bdb_cache_entryinfo_trylock( ei ) == 0 )) {
+       if ( ei && ( ei->bei_state & CACHE_ENTRY_NOT_CACHED )) {
+               bdb_cache_entryinfo_lock( ei );
                if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) {
                        /* Releasing the entry can only be done when
                         * we know that nobody else is using it, i.e we
@@ -968,6 +967,7 @@ load1:
                        if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) {
                                load = 1;
                                (*eip)->bei_state |= CACHE_ENTRY_LOADING;
+                               flag |= ID_CHKPURGE;
                        }
 
                        if ( !load ) {
@@ -976,12 +976,9 @@ load1:
                                 * another thread is currently loading it.
                                 */
                                if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) {
-                                       (*eip)->bei_state &= ~CACHE_ENTRY_NOT_CACHED;
-                                       ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
-                                       ++bdb->bi_cache.c_cursize;
-                                       ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
+                                       (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED;
+                                       flag |= ID_CHKPURGE;
                                }
-                               flag &= ~ID_NOCACHE;
                        }
 
                        if ( flag & ID_LOCKED ) {
@@ -1007,21 +1004,24 @@ load1:
                                                        ldap_pvt_thread_yield();
                                                bdb_fix_dn( ep, 0 );
 #endif
+                                               bdb_cache_entryinfo_lock( *eip );
+
                                                (*eip)->bei_e = ep;
 #ifdef SLAP_ZONE_ALLOC
                                                (*eip)->bei_zseq = *((ber_len_t *)ep - 2);
 #endif
                                                ep = NULL;
-                                               bdb_cache_lru_link( bdb, *eip );
-                                               if (( flag & ID_NOCACHE ) &&
-                                                       ( bdb_cache_entryinfo_trylock( *eip ) == 0 )) {
+                                               if ( flag & ID_NOCACHE ) {
                                                        /* Set the cached state only if no other thread
                                                         * found the info while we were loading the entry.
                                                         */
-                                                       if ( (*eip)->bei_finders == 1 )
+                                                       if ( (*eip)->bei_finders == 1 ) {
                                                                (*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED;
-                                                       bdb_cache_entryinfo_unlock( *eip );
+                                                               flag ^= ID_CHKPURGE;
+                                                       }
                                                }
+                                               bdb_cache_entryinfo_unlock( *eip );
+                                               bdb_cache_lru_link( bdb, *eip );
                                        }
                                        if ( rc == 0 ) {
                                                /* If we succeeded, downgrade back to a readlock. */
@@ -1077,9 +1077,9 @@ load1:
        if ( rc == 0 ) {
                int purge = 0;
 
-               if (( load && !( flag & ID_NOCACHE )) || bdb->bi_cache.c_eimax ) {
+               if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) {
                        ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
-                       if ( load && !( flag & ID_NOCACHE )) {
+                       if ( flag & ID_CHKPURGE ) {
                                bdb->bi_cache.c_cursize++;
                                if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
                                        purge = 1;
@@ -1533,6 +1533,36 @@ bdb_cache_release_all( Cache *cache )
 }
 
 #ifdef LDAP_DEBUG
+static void
+bdb_lru_count( Cache *cache )
+{
+       EntryInfo       *e;
+       int ei = 0, ent = 0, nc = 0;
+
+       for ( e = cache->c_lrutail; ; ) {
+               ei++;
+               if ( e->bei_e ) {
+                       ent++;
+                       if ( e->bei_state & CACHE_ENTRY_NOT_CACHED )
+                               nc++;
+                       fprintf( stderr, "ei %d entry %p dn %s\n", ei, e->bei_e, e->bei_e->e_name.bv_val );
+               }
+               e = e->bei_lrunext;
+               if ( e == cache->c_lrutail )
+                       break;
+       }
+       fprintf( stderr, "counted %d entryInfos and %d entries, %d notcached\n",
+               ei, ent, nc );
+       ei = 0;
+       for ( e = cache->c_lrutail; ; ) {
+               ei++;
+               e = e->bei_lruprev;
+               if ( e == cache->c_lrutail )
+                       break;
+       }
+       fprintf( stderr, "counted %d entryInfos (on lruprev)\n", ei );
+}
+
 #ifdef SLAPD_UNUSED
 static void
 bdb_lru_print( Cache *cache )
index b0243553a233d2305819711830daa161ae0191e7..a321dca0b77e3960c57eaae6257728b62c894ac5 100644 (file)
@@ -547,6 +547,7 @@ int bdb_cache_find_ndn(
 #define        ID_LOCKED       1
 #define        ID_NOCACHE      2
 #define        ID_NOENTRY      4
+#define        ID_CHKPURGE     8
 int bdb_cache_find_id(
        Operation *op,
        DB_TXN  *tid,