ITS#9584 bconfig: protect cf entries with rwlock

Since not all config writes pause the server, must prevent
searches from seeing intermediate states.
This commit is contained in:
Howard Chu 2022-02-03 00:49:52 +00:00 committed by Quanah Gibson-Mount
parent 868c7953d7
commit 62bf31e966

View File

@ -76,6 +76,7 @@ typedef struct {
BackendDB cb_db; /* underlying database */
int cb_got_ldif;
int cb_use_ldif;
ldap_pvt_thread_rdwr_t cb_rwlock;
} CfBackInfo;
static CfBackInfo cfBackInfo;
@ -5761,6 +5762,8 @@ config_back_add( Operation *op, SlapReply *rs )
if ( slap_pause_server() < 0 )
dopause = 0;
ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
/* Strategy:
* 1) check for existence of entry
* 2) check for sibling renumbering
@ -5825,6 +5828,7 @@ config_back_add( Operation *op, SlapReply *rs )
}
out2:;
ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
if ( dopause )
slap_unpause_server();
@ -6341,6 +6345,7 @@ config_back_modify( Operation *op, SlapReply *rs )
if ( slap_pause_server() < 0 )
do_pause = 0;
}
ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
/* Strategy:
* 1) perform the Modify on the cached Entry.
@ -6384,6 +6389,7 @@ config_back_modify( Operation *op, SlapReply *rs )
}
}
ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
if ( do_pause )
slap_unpause_server();
out:
@ -6551,6 +6557,8 @@ config_back_modrdn( Operation *op, SlapReply *rs )
if ( slap_pause_server() < 0 )
dopause = 0;
ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
if ( ce->ce_type == Cft_Schema ) {
req_modrdn_s modr = op->oq_modrdn;
struct berval rdn;
@ -6629,6 +6637,8 @@ config_back_modrdn( Operation *op, SlapReply *rs )
}
}
ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
if ( dopause )
slap_unpause_server();
out:
@ -6691,6 +6701,8 @@ config_back_delete( Operation *op, SlapReply *rs )
if ( slap_pause_server() < 0 )
dopause = 0;
ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
if ( ce->ce_type == Cft_Overlay ){
overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi, op );
} else if ( ce->ce_type == Cft_Misc ) {
@ -6709,8 +6721,7 @@ config_back_delete( Operation *op, SlapReply *rs )
if ( !oc_at ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "objectclass not found";
if ( dopause ) slap_unpause_server();
goto out;
goto out2;
}
for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) {
co.co_name = &oc_at->a_nvals[i];
@ -6727,8 +6738,7 @@ config_back_delete( Operation *op, SlapReply *rs )
/* FIXME: We should return a helpful error message
* here */
}
if ( dopause ) slap_unpause_server();
goto out;
goto out2;
}
break;
}
@ -6736,8 +6746,7 @@ config_back_delete( Operation *op, SlapReply *rs )
if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
rs->sr_text = "Cannot delete config or frontend database";
if ( dopause ) slap_unpause_server();
goto out;
goto out2;
}
if ( ce->ce_be->bd_info->bi_db_close ) {
ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL );
@ -6798,6 +6807,8 @@ config_back_delete( Operation *op, SlapReply *rs )
ce->ce_entry->e_private=NULL;
entry_free(ce->ce_entry);
ch_free(ce);
out2:
ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
if ( dopause ) slap_unpause_server();
} else {
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
@ -6820,6 +6831,7 @@ config_back_search( Operation *op, SlapReply *rs )
cfb = (CfBackInfo *)op->o_bd->be_private;
ldap_pvt_thread_rdwr_rlock( &cfb->cb_rwlock );
ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
if ( !ce ) {
if ( last )
@ -6854,6 +6866,7 @@ config_back_search( Operation *op, SlapReply *rs )
}
out:
ldap_pvt_thread_rdwr_runlock( &cfb->cb_rwlock );
send_ldap_result( op, rs );
return rs->sr_err;
}
@ -7590,6 +7603,8 @@ config_back_db_destroy( BackendDB *be, ConfigReply *cr )
ch_free( cfdir.bv_val );
ldap_pvt_thread_rdwr_destroy( &cfb->cb_rwlock );
ldap_avl_free( CfOcTree, NULL );
if ( cfb->cb_db.bd_info ) {
@ -7624,6 +7639,8 @@ config_back_db_init( BackendDB *be, ConfigReply* cr )
ber_dupbv( &dn, &be->be_rootdn );
ber_bvarray_add( &be->be_nsuffix, &dn );
ldap_pvt_thread_rdwr_init( &cfb->cb_rwlock );
/* Hide from namingContexts */
SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;