* during a purge operation.
  */
 static void
-bdb_cache_lru_link( Cache *cache, EntryInfo *ei )
+bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei )
 {
        /* Insert into circular LRU list */
-       ldap_pvt_thread_mutex_lock( &cache->c_lru_mutex );
-       ei->bei_lruprev = cache->c_lrutail;
-       if ( cache->c_lrutail ) {
-               ei->bei_lrunext = cache->c_lrutail->bei_lrunext;
-               cache->c_lrutail->bei_lrunext = ei;
+       ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
+       ei->bei_lruprev = bdb->bi_cache.c_lrutail;
+       if ( bdb->bi_cache.c_lrutail ) {
+               ei->bei_lrunext = bdb->bi_cache.c_lrutail->bei_lrunext;
+               bdb->bi_cache.c_lrutail->bei_lrunext = ei;
                if ( ei->bei_lrunext )
                        ei->bei_lrunext->bei_lruprev = ei;
        } else {
                ei->bei_lrunext = ei->bei_lruprev = ei;
-               cache->c_lruhead = ei;
+               bdb->bi_cache.c_lruhead = ei;
        }
-       cache->c_lrutail = ei;
-       ldap_pvt_thread_mutex_unlock( &cache->c_lru_mutex );
+       bdb->bi_cache.c_lrutail = ei;
+       ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
 }
 
 #ifdef NO_THREADS
                ei->bei_parent->bei_ckids++;
 #endif
        }
-       bdb_cache_lru_link( &bdb->bi_cache, ei2 );
 
        *res = ei2;
        return 0;
                                ein->bei_ckids++;
                                bdb_cache_entryinfo_unlock( ein );
                        }
-               } else {
-                       bdb_cache_lru_link( &bdb->bi_cache, ein );
                }
 
                /* If this is the first time, save this node
 }
 #endif
 
+#define LRU_DEL( c, e ) do { \
+       if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lrunext; \
+       if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \
+       e->bei_lrunext->bei_lruprev = e->bei_lruprev; \
+       e->bei_lruprev->bei_lrunext = e->bei_lrunext; \
+} while ( 0 )
+
 static void
 bdb_cache_lru_purge( struct bdb_info *bdb )
 {
        int i, count, islocked, tests;
 
        /* Don't bother if we can't get the lock */
-       if ( ldap_pvt_thread_mutex_trylock( &bdb->bi_cache.c_lru_mutex ) )
+       if ( ldap_pvt_thread_mutex_trylock( &bdb->bi_cache.c_lru_mutex ) ) {
+               bdb->bi_cache.c_purging = 0;
                return;
+       }
 
        if ( bdb->bi_cache.c_cursize <= bdb->bi_cache.c_maxsize ) {
                ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
+               bdb->bi_cache.c_purging = 0;
                return;
        }
 
                                        islocked = 0;
                                }
                                /* Leave node on LRU list for a future pass */
+                       } else {
+                               LRU_DEL( &bdb->bi_cache, elru );
                        }
                }
 
 
        bdb->bi_cache.c_lruhead = elnext;
        ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
+       bdb->bi_cache.c_purging = 0;
 }
 
 EntryInfo *
                                                (*eip)->bei_zseq = *((ber_len_t *)ep - 2);
 #endif
                                                ep = NULL;
+                                               bdb_cache_lru_link( bdb, *eip );
                                        }
                                        if ( rc == 0 ) {
                                                /* If we succeeded, downgrade back to a readlock. */
                if ( load ) {
                        ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
                        bdb->bi_cache.c_cursize++;
-                       if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize )
+                       if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize &&
+                               !bdb->bi_cache.c_purging ) {
                                purge = 1;
+                               bdb->bi_cache.c_purging = 1;
+                       }
                        ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
                }
                if ( purge )
        ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
        ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
        ++bdb->bi_cache.c_cursize;
-       if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize )
+       if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize &&
+               !bdb->bi_cache.c_purging ) {
                purge = 1;
+               bdb->bi_cache.c_purging = 1;
+       }
        ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
 
        if ( purge )
 
        if ( rc == 0 ){
                /* lru */
-               if ( e == cache->c_lruhead ) cache->c_lruhead = e->bei_lrunext;
-               if ( e == cache->c_lrutail ) cache->c_lrutail = e->bei_lruprev;
-
-               if ( e->bei_lrunext ) e->bei_lrunext->bei_lruprev = e->bei_lruprev;
-               if ( e->bei_lruprev ) e->bei_lruprev->bei_lrunext = e->bei_lrunext;
+               LRU_DEL( cache, e );
 
                if ( e->bei_e ) {
                        ldap_pvt_thread_mutex_lock( &cache->c_count_mutex );