diff --git a/CHANGES b/CHANGES index b7747cb593c6cd8959f6af6cedfe08c99a0fca6b..f4eb816084a032accc832abeec8a130eea82275b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ OpenLDAP 2.4 Change Log OpenLDAP 2.4.24 Engineering + Fixed slapd-bdb entry cache delete failure (ITS#6577) OpenLDAP 2.4.23 Release (2010/06/30) Fixed libldap to return server's error code (ITS#6569) diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 4b40c9ec17730574a7319981b9c001956b965253..9fd2912371c41d9abeaf014f64911813ad37e46d 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -492,7 +492,6 @@ retry: /* transaction retry */ return_results: success = rs->sr_err; send_ldap_result( op, rs ); - slap_graduate_commit_csn( op ); if( ltid != NULL ) { TXN_ABORT( ltid ); @@ -517,10 +516,11 @@ return_results: } } + slap_graduate_commit_csn( op ); + if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); } - return rs->sr_err; } diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index 5e0d7bfde3869fb8883e7006bd26ab9cd5e07a11..39a7d290c8db3752d3c0ca193d32d4902c344b48 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -442,7 +442,7 @@ bdb_cache_find_ndn( ei.bei_parent = eip; ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp ); if ( !ei2 ) { - DB_LOCK lock; + DBC *cursor; int len = ei.bei_nrdn.bv_len; if ( BER_BVISEMPTY( ndn )) { @@ -458,12 +458,12 @@ bdb_cache_find_ndn( BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s", ei.bei_nrdn.bv_val ); - lock.mode = DB_LOCK_NG; - rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &lock ); + cursor = NULL; + rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &cursor ); if (rc) { bdb_cache_entryinfo_lock( eip ); eip->bei_finders--; - bdb_cache_entry_db_unlock( bdb, &lock ); + if ( cursor ) cursor->c_close( cursor ); *res = eip; return rc; } @@ -477,22 +477,24 @@ bdb_cache_find_ndn( /* add_internal left eip and c_rwlock locked */ eip->bei_finders--; ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); - bdb_cache_entry_db_unlock( bdb, &lock ); + if ( cursor ) cursor->c_close( cursor ); if ( rc ) { *res = eip; return rc; } - } else if ( ei2->bei_state & CACHE_ENTRY_DELETED ) { + } + bdb_cache_entryinfo_lock( ei2 ); + if ( ei2->bei_state & CACHE_ENTRY_DELETED ) { /* In the midst of deleting? Give it a chance to * complete. */ + bdb_cache_entryinfo_unlock( ei2 ); bdb_cache_entryinfo_unlock( eip ); ldap_pvt_thread_yield(); bdb_cache_entryinfo_lock( eip ); *res = eip; return DB_NOTFOUND; } - bdb_cache_entryinfo_lock( ei2 ); bdb_cache_entryinfo_unlock( eip ); eip = ei2; diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index 0ea30714ae62ab0c6d8c71c7400a7e64a93a3292..dc7132bb8e72d8111f3538cba8b85bf71ce2d131 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -23,32 +23,6 @@ #include "idl.h" #include "lutil.h" -#define bdb_dn2id_lock BDB_SYMBOL(dn2id_lock) - -static int -bdb_dn2id_lock( struct bdb_info *bdb, struct berval *dn, - int rw, DB_TXN *txn, DB_LOCK *lock ) -{ - int rc; - DBT lockobj; - int db_rw; - - if (!txn) - return 0; - - if (rw) - db_rw = DB_LOCK_WRITE; - else - db_rw = DB_LOCK_READ; - - lockobj.data = dn->bv_val; - lockobj.size = dn->bv_len; - - rc = LOCK_GET(bdb->bi_dbenv, TXN_ID(txn), DB_LOCK_NOWAIT, - &lockobj, db_rw, lock); - return rc; -} - #ifndef BDB_HIER int bdb_dn2id_add( @@ -195,10 +169,6 @@ bdb_dn2id_delete( AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len ); ptr.bv_val[ptr.bv_len] = '\0'; - /* We hold this lock until the TXN completes */ - rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, txn, &lock ); - if ( rc ) goto done; - /* delete it */ rc = db->del( db, txn, &key, 0 ); if( rc != 0 ) { @@ -281,11 +251,10 @@ bdb_dn2id( struct berval *dn, EntryInfo *ei, DB_TXN *txn, - DB_LOCK *lock ) + DBC **cursor ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; - DBC *cursor; int rc; DBT key, data; ID nid; @@ -304,18 +273,11 @@ bdb_dn2id( data.ulen = sizeof(ID); data.flags = DB_DBT_USERMEM; - rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); - if ( rc ) goto func_leave; - - rc = bdb_dn2id_lock( bdb, dn, 0, txn, lock ); - if ( rc ) goto nolock; + rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags ); /* fetch it */ - rc = cursor->c_get( cursor, &key, &data, DB_SET ); - -nolock: - cursor->c_close( cursor ); -func_leave: + if ( !rc ) + rc = (*cursor)->c_get( *cursor, &key, &data, DB_SET ); if( rc != 0 ) { Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n", @@ -682,10 +644,6 @@ hdb_dn2id_delete( rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); if ( rc ) goto func_leave; - /* We hold this lock until the TXN completes */ - rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, txn, &lock ); - if ( rc ) goto nolock; - /* Delete our ID from the parent's list */ rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE ); if ( rc == 0 ) { @@ -707,7 +665,6 @@ hdb_dn2id_delete( rc = cursor->c_del( cursor, 0 ); } -nolock: cursor->c_close( cursor ); func_leave: op->o_tmpfree( d, op->o_tmpmemctx ); @@ -745,12 +702,11 @@ hdb_dn2id( struct berval *in, EntryInfo *ei, DB_TXN *txn, - DB_LOCK *lock ) + DBC **cursor ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; DBT key, data; - DBC *cursor; int rc = 0, nrlen; diskNode *d; char *ptr; @@ -776,7 +732,7 @@ hdb_dn2id( data.dlen = data.ulen; data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; - rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); + rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags ); if ( rc ) return rc; d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx ); @@ -788,10 +744,7 @@ hdb_dn2id( *ptr = '\0'; data.data = d; - rc = bdb_dn2id_lock( bdb, in, 0, txn, lock ); - if ( rc ) goto func_leave; - - rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE ); + rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE ); if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] || strncmp( d->nrdn, in->bv_val, nrlen ))) { rc = DB_NOTFOUND; @@ -808,13 +761,11 @@ hdb_dn2id( /* FIXME: do we need to lock the parent * entryinfo? Seems safe... */ - cursor->c_count( cursor, &dkids, 0 ); + (*cursor)->c_count( *cursor, &dkids, 0 ); ei->bei_parent->bei_dkids = dkids; } } -func_leave: - cursor->c_close( cursor ); op->o_tmpfree( d, op->o_tmpmemctx ); if( rc != 0 ) { Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: get failed: %s (%d)\n", diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index 72d7f80336bc6b5ccbd1053c9252f5ef358f692f..b0243553a233d2305819711830daa161ae0191e7 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -106,7 +106,7 @@ int bdb_dn2id( struct berval *dn, EntryInfo *ei, DB_TXN *txn, - DB_LOCK *lock ); + DBC **cursor ); int bdb_dn2id_add( Operation *op,