From 634cca7f0d2749d63e79cea60b8f02b44fcd15d4 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Tue, 29 Jan 2002 17:27:20 +0000 Subject: [PATCH] Add GIANT rwlock! This should resolve nasty concurrency issues. --- servers/slapd/back-ldbm/add.c | 53 +++++++++-------------------- servers/slapd/back-ldbm/back-ldbm.h | 4 +-- servers/slapd/back-ldbm/bind.c | 7 +++- servers/slapd/back-ldbm/compare.c | 6 ++++ servers/slapd/back-ldbm/delete.c | 16 ++++----- servers/slapd/back-ldbm/entry.c | 2 +- servers/slapd/back-ldbm/init.c | 8 ++--- servers/slapd/back-ldbm/modify.c | 5 +++ servers/slapd/back-ldbm/modrdn.c | 14 ++++---- servers/slapd/back-ldbm/nextid.c | 8 ----- servers/slapd/back-ldbm/passwd.c | 7 +++- servers/slapd/back-ldbm/referral.c | 7 ++++ servers/slapd/back-ldbm/search.c | 7 ++++ 13 files changed, 70 insertions(+), 74 deletions(-) diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index 997e969f1d..9baac81065 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -27,7 +27,6 @@ ldbm_back_add( struct ldbminfo *li = (struct ldbminfo *) be->be_private; struct berval pdn; Entry *p = NULL; - int rootlock = 0; int rc; ID id = NOID; const char *text = NULL; @@ -42,12 +41,12 @@ ldbm_back_add( Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0); #endif - /* nobody else can add until we lock our parent */ - ldap_pvt_thread_mutex_lock(&li->li_add_mutex); + /* grab giant lock for writing */ + ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock); if ( ( rc = dn2id( be, &e->e_nname, &id ) ) || id != NOID ) { /* if (rc) something bad happened to ldbm cache */ - ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); send_ldap_result( conn, op, rc ? LDAP_OPERATIONS_ERROR : LDAP_ALREADY_EXISTS, NULL, NULL, NULL, NULL ); @@ -57,7 +56,7 @@ ldbm_back_add( rc = entry_schema_check( be, e, NULL, &text, textbuf, textlen ); if ( rc != LDAP_SUCCESS ) { - ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, @@ -68,7 +67,6 @@ ldbm_back_add( text, 0, 0 ); #endif - send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); return( -1 ); @@ -94,8 +92,6 @@ ldbm_back_add( char *matched_dn = NULL; BerVarray refs; - ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); - if ( matched != NULL ) { matched_dn = ch_strdup( matched->e_dn ); refs = is_entry_referral( matched ) @@ -108,6 +104,8 @@ ldbm_back_add( NULL, &e->e_name, LDAP_SCOPE_DEFAULT ); } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); + #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, "ldbm_back_add: Parent of (%s) does not exist.\n", @@ -127,14 +125,12 @@ ldbm_back_add( return -1; } - /* don't need the add lock anymore */ - ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); - if ( ! access_allowed( be, conn, op, p, children, NULL, ACL_WRITE ) ) { /* free parent and writer lock */ cache_return_entry_w( &li->li_cache, p ); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, @@ -148,7 +144,6 @@ ldbm_back_add( send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, "no write access to parent", NULL, NULL ); - return -1; } @@ -157,6 +152,7 @@ ldbm_back_add( /* free parent and writer lock */ cache_return_entry_w( &li->li_cache, p ); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, @@ -182,6 +178,7 @@ ldbm_back_add( /* free parent and writer lock */ cache_return_entry_w( &li->li_cache, p ); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, @@ -214,7 +211,7 @@ ldbm_back_add( p = NULL; if ( ! rc ) { - ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, @@ -236,7 +233,7 @@ ldbm_back_add( } } else { - ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, @@ -256,14 +253,6 @@ ldbm_back_add( return -1; } } - - /* - * no parent, acquire the root write lock - * and release the add lock. - */ - ldap_pvt_thread_mutex_lock(&li->li_root_mutex); - rootlock = 1; - ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); } if ( next_id( be, &e->e_id ) ) { @@ -272,20 +261,16 @@ ldbm_back_add( cache_return_entry_w( &li->li_cache, p ); } - if ( rootlock ) { - /* release root lock */ - ldap_pvt_thread_mutex_unlock(&li->li_root_mutex); - } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, - "ldbm_back_add: next_id failed.\n" )); + "ldbm_back_add: next_id failed.\n" )); #else Debug( LDAP_DEBUG_ANY, "ldbm_add: next_id failed\n", 0, 0, 0 ); #endif - send_ldap_result( conn, op, LDAP_OTHER, NULL, "next_id add failed", NULL, NULL ); @@ -303,10 +288,7 @@ ldbm_back_add( cache_return_entry_w( &li->li_cache, p ); } - if ( rootlock ) { - /* release root lock */ - ldap_pvt_thread_mutex_unlock(&li->li_root_mutex); - } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_ERR, @@ -392,16 +374,13 @@ return_results:; cache_return_entry_w( &li->li_cache, p ); } - if ( rootlock ) { - /* release root lock */ - ldap_pvt_thread_mutex_unlock(&li->li_root_mutex); - } - if ( rc ) { /* in case of error, writer lock is freed * and entry's private data is destroyed */ cache_return_entry_w( &li->li_cache, e ); } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); + return( rc ); } diff --git a/servers/slapd/back-ldbm/back-ldbm.h b/servers/slapd/back-ldbm/back-ldbm.h index a1072adc74..c74d84c408 100644 --- a/servers/slapd/back-ldbm/back-ldbm.h +++ b/servers/slapd/back-ldbm/back-ldbm.h @@ -125,10 +125,8 @@ typedef struct ldbm_dbcache { #define MAXDBCACHE 128 struct ldbminfo { + ldap_pvt_thread_rdwr_t li_giant_rwlock; ID li_nextid; - ldap_pvt_thread_mutex_t li_nextid_mutex; - ldap_pvt_thread_mutex_t li_root_mutex; - ldap_pvt_thread_mutex_t li_add_mutex; int li_mode; slap_mask_t li_defaultmask; char *li_directory; diff --git a/servers/slapd/back-ldbm/bind.c b/servers/slapd/back-ldbm/bind.c index a6ab1c5e29..ddadbad7b1 100644 --- a/servers/slapd/back-ldbm/bind.c +++ b/servers/slapd/back-ldbm/bind.c @@ -50,9 +50,11 @@ ldbm_back_bind( Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn->bv_val, 0, 0); #endif - dn = ndn; + /* grab giant lock for reading */ + ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); + /* get entry with reader lock */ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) { char *matched_dn = NULL; @@ -72,6 +74,8 @@ ldbm_back_bind( NULL, dn, LDAP_SCOPE_DEFAULT ); } + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); + /* allow noauth binds */ rc = 1; if ( method == LDAP_AUTH_SIMPLE ) { @@ -263,6 +267,7 @@ ldbm_back_bind( return_results:; /* free entry and reader lock */ cache_return_entry_r( &li->li_cache, e ); + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); /* front end with send result on success (rc==0) */ return( rc ); diff --git a/servers/slapd/back-ldbm/compare.c b/servers/slapd/back-ldbm/compare.c index b3494b4964..b5ca4f6618 100644 --- a/servers/slapd/back-ldbm/compare.c +++ b/servers/slapd/back-ldbm/compare.c @@ -33,6 +33,9 @@ ldbm_back_compare( int rc; int manageDSAit = get_manageDSAit( op ); + /* grab giant lock for reading */ + ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); + /* get entry with reader lock */ if ( (e = dn2entry_r( be, ndn, &matched )) == NULL ) { char *matched_dn = NULL; @@ -49,6 +52,8 @@ ldbm_back_compare( NULL, dn, LDAP_SCOPE_DEFAULT ); } + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); + send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); @@ -115,5 +120,6 @@ ldbm_back_compare( return_results:; cache_return_entry_r( &li->li_cache, e ); + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); return( rc ); } diff --git a/servers/slapd/back-ldbm/delete.c b/servers/slapd/back-ldbm/delete.c index a3b5ebe902..874fe4f156 100644 --- a/servers/slapd/back-ldbm/delete.c +++ b/servers/slapd/back-ldbm/delete.c @@ -29,7 +29,6 @@ ldbm_back_delete( Entry *matched; struct berval pdn; Entry *e, *p = NULL; - int rootlock = 0; int rc = -1; int manageDSAit = get_manageDSAit( op ); AttributeDescription *children = slap_schema.si_ad_children; @@ -41,6 +40,9 @@ ldbm_back_delete( Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn->bv_val, 0, 0); #endif + /* grab giant lock for writing */ + ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock); + /* get entry with writer lock */ if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) { char *matched_dn = NULL; @@ -66,6 +68,8 @@ ldbm_back_delete( NULL, dn, LDAP_SCOPE_DEFAULT ); } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); + send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); @@ -196,9 +200,6 @@ ldbm_back_delete( goto return_results; } } - - ldap_pvt_thread_mutex_lock(&li->li_root_mutex); - rootlock = 1; } /* delete from dn2id mapping */ @@ -248,13 +249,10 @@ return_results:; cache_return_entry_w( &li->li_cache, p ); } - if ( rootlock ) { - /* release root lock */ - ldap_pvt_thread_mutex_unlock(&li->li_root_mutex); - } - /* free entry and writer lock */ cache_return_entry_w( &li->li_cache, e ); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); + return rc; } diff --git a/servers/slapd/back-ldbm/entry.c b/servers/slapd/back-ldbm/entry.c index 28267e39fb..f018d2b129 100644 --- a/servers/slapd/back-ldbm/entry.c +++ b/servers/slapd/back-ldbm/entry.c @@ -31,8 +31,8 @@ ldbm_back_entry_release_rw( if ( slapMode == SLAP_SERVER_MODE ) { /* free entry and reader or writer lock */ cache_return_entry_rw( &li->li_cache, e, rw ); + } else { - entry_free( e ); } diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c index 1fe1335666..1c1af991f8 100644 --- a/servers/slapd/back-ldbm/init.c +++ b/servers/slapd/back-ldbm/init.c @@ -172,10 +172,8 @@ ldbm_back_db_init( li->li_dbshutdown = 0; /* initialize various mutex locks & condition variables */ - ldap_pvt_thread_mutex_init( &li->li_root_mutex ); - ldap_pvt_thread_mutex_init( &li->li_add_mutex ); + ldap_pvt_thread_rdwr_init( &li->li_giant_rwlock ); ldap_pvt_thread_mutex_init( &li->li_cache.c_mutex ); - ldap_pvt_thread_mutex_init( &li->li_nextid_mutex ); ldap_pvt_thread_mutex_init( &li->li_dbcache_mutex ); ldap_pvt_thread_cond_init( &li->li_dbcache_cv ); @@ -225,10 +223,8 @@ ldbm_back_db_destroy( free( li->li_directory ); attr_index_destroy( li->li_attrs ); - ldap_pvt_thread_mutex_destroy( &li->li_root_mutex ); - ldap_pvt_thread_mutex_destroy( &li->li_add_mutex ); + ldap_pvt_thread_rdwr_destroy( &li->li_giant_rwlock ); ldap_pvt_thread_mutex_destroy( &li->li_cache.c_mutex ); - ldap_pvt_thread_mutex_destroy( &li->li_nextid_mutex ); ldap_pvt_thread_mutex_destroy( &li->li_dbcache_mutex ); ldap_pvt_thread_cond_destroy( &li->li_dbcache_cv ); diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index c7978238a2..6948d2ffd8 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -297,6 +297,8 @@ ldbm_back_modify( Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0); #endif + /* grab giant lock for writing */ + ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock); /* acquire and lock entry */ if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) { @@ -314,6 +316,7 @@ ldbm_back_modify( NULL, dn, LDAP_SCOPE_DEFAULT ); } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); @@ -370,9 +373,11 @@ ldbm_back_modify( NULL, NULL, NULL, NULL ); cache_return_entry_w( &li->li_cache, e ); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); return( 0 ); error_return:; cache_return_entry_w( &li->li_cache, e ); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); return( -1 ); } diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c index 195fa4d434..f2e2dfb6d6 100644 --- a/servers/slapd/back-ldbm/modrdn.c +++ b/servers/slapd/back-ldbm/modrdn.c @@ -88,6 +88,9 @@ ldbm_back_modrdn( ? newSuperior->bv_val : "NULL", 0 ); #endif + /* grab giant lock for writing */ + ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock); + /* get entry with writer lock */ if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) { char* matched_dn = NULL; @@ -104,6 +107,8 @@ ldbm_back_modrdn( NULL, dn, LDAP_SCOPE_DEFAULT ); } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); + send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); @@ -262,9 +267,6 @@ ldbm_back_modrdn( } } - ldap_pvt_thread_mutex_lock(&li->li_root_mutex); - rootlock = 1; - #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_INFO, "ldbm_back_modrdn: (%s) no parent, locked root.\n", e->e_dn )); @@ -804,11 +806,6 @@ return_results: cache_return_entry_w( &li->li_cache, p ); } - if ( rootlock ) { - /* release root writer lock */ - ldap_pvt_thread_mutex_unlock(&li->li_root_mutex); - } - /* free entry and writer lock */ cache_return_entry_w( &li->li_cache, e ); if ( rc == MUST_DESTROY ) { @@ -817,5 +814,6 @@ return_results: * the entry must be freed */ entry_free( e ); } + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); return( rc ); } diff --git a/servers/slapd/back-ldbm/nextid.c b/servers/slapd/back-ldbm/nextid.c index 2bdcde3871..80f6f0f61f 100644 --- a/servers/slapd/back-ldbm/nextid.c +++ b/servers/slapd/back-ldbm/nextid.c @@ -102,11 +102,8 @@ next_id_get( Backend *be, ID *idp ) *idp = NOID; - ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex ); - if ( li->li_nextid == NOID ) { if ( ( rc = next_id_read( be, idp ) ) ) { - ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); return( rc ); } li->li_nextid = *idp; @@ -114,7 +111,6 @@ next_id_get( Backend *be, ID *idp ) *idp = li->li_nextid; - ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); return( rc ); } @@ -124,11 +120,8 @@ next_id( Backend *be, ID *idp ) struct ldbminfo *li = (struct ldbminfo *) be->be_private; int rc = 0; - ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex ); - if ( li->li_nextid == NOID ) { if ( ( rc = next_id_read( be, idp ) ) ) { - ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); return( rc ); } li->li_nextid = *idp; @@ -139,6 +132,5 @@ next_id( Backend *be, ID *idp ) rc = -1; } - ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); return( rc ); } diff --git a/servers/slapd/back-ldbm/passwd.c b/servers/slapd/back-ldbm/passwd.c index 1f04c48555..8ad0948f09 100644 --- a/servers/slapd/back-ldbm/passwd.c +++ b/servers/slapd/back-ldbm/passwd.c @@ -31,7 +31,7 @@ ldbm_back_exop_passwd( ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - int rc; + int rc, locked=0; Entry *e = NULL; struct berval hash = { 0, NULL }; @@ -108,8 +108,12 @@ ldbm_back_exop_passwd( goto done; } + /* grab giant lock for writing */ + ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock); + e = dn2entry_w( be, &ndn, NULL ); if( e == NULL ) { + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); *text = "could not locate authorization entry"; rc = LDAP_NO_SUCH_OBJECT; goto done; @@ -173,6 +177,7 @@ ldbm_back_exop_passwd( done: if( e != NULL ) { cache_return_entry_w( &li->li_cache, e ); + ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock); } if( hash.bv_val != NULL ) { diff --git a/servers/slapd/back-ldbm/referral.c b/servers/slapd/back-ldbm/referral.c index 05d51e0919..48bb7886cc 100644 --- a/servers/slapd/back-ldbm/referral.c +++ b/servers/slapd/back-ldbm/referral.c @@ -38,6 +38,9 @@ ldbm_back_referrals( return rc; } + /* grab giant lock for reading */ + ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); + /* get entry with reader lock */ e = dn2entry_r( be, ndn, &matched ); if ( e == NULL ) { @@ -70,6 +73,8 @@ ldbm_back_referrals( NULL, dn, LDAP_SCOPE_DEFAULT ); } + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); + if( refs != NULL ) { /* send referrals */ send_ldap_result( conn, op, rc = LDAP_REFERRAL, @@ -117,5 +122,7 @@ ldbm_back_referrals( } cache_return_entry_r( &li->li_cache, e ); + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); + return rc; } diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index c80359f8c6..c61b921ac6 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -64,6 +64,8 @@ ldbm_back_search( Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0); #endif + /* grab giant lock for reading */ + ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); if ( nbase->bv_len == 0 ) { /* DIT root special case */ @@ -116,6 +118,8 @@ ldbm_back_search( NULL, base, scope ); } + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); + send_ldap_result( conn, op, err, matched_dn.bv_val, text, refs, NULL ); @@ -135,6 +139,7 @@ ldbm_back_search( refs = NULL; cache_return_entry_r( &li->li_cache, e ); + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_INFO, @@ -506,6 +511,8 @@ loop_continue: rc = 0; done: + ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); + if( candidates != NULL ) idl_free( candidates ); -- 2.39.2