Commit c48f56db authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Fix slapd directoryString exact index normalization bug

    Fix back-bdb bdb_cache_find_entry* retry bug
    Fix back-bdb log message bug
    Fix back-bdb group/atttribute txn code
    Updated slapadd to complain about holes in the DIT
parent 1e300bba
OpenLDAP 2.1 Change Log
OpenLDAP 2.1.14 Engineering
Fix slapd directoryString exact index normalization bug
Fix back-bdb bdb_cache_find_entry* retry bug
Fix back-bdb log message bug
Fix back-bdb group/atttribute txn code
Updated slapadd to complain about holes in the DIT
Documentation
Misc man page updates
OpenLDAP 2.1.13 Release
Fixed back-bdb group ACL deadlock bug (ITS#2195)
Fixed back-bdb passwd hang bug (ITS#2122)
......@@ -29,8 +38,9 @@ OpenLDAP 2.1.13 Release
Build Environment
Check back-bdb requirement for BDB 4.1
Removed configure flags for deprecated features
Misc man page updates
Updated test suite
Documentation
Misc man page updates
OpenLDAP 2.1.12 Release
Build Environment
......
......@@ -325,6 +325,7 @@ done:;
}
d2 = ch_malloc(sizeof(AttributeDescription) + dlen);
d2->ad_next = NULL;
d2->ad_type = desc.ad_type;
d2->ad_flags = desc.ad_flags;
d2->ad_cname.bv_len = desc.ad_type->sat_cname.bv_len;
......
......@@ -99,6 +99,7 @@ retry: /* transaction retry */
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
......@@ -134,6 +135,7 @@ retry: /* transaction retry */
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/*
......@@ -216,13 +218,13 @@ retry: /* transaction retry */
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE, NULL );
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_add: no write access to parent\n", 0, 0, 0 );
......@@ -316,13 +318,13 @@ retry: /* transaction retry */
p = NULL;
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_add: no write access to parent\n", 0, 0, 0 );
......@@ -379,13 +381,13 @@ retry: /* transaction retry */
rc = access_allowed( be, conn, op, e,
entry, NULL, ACL_WRITE, NULL );
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_add: no write access to entry\n", 0, 0, 0 );
......
......@@ -97,13 +97,19 @@ bdb_attribute(
} else {
dn2entry_retry:
/* can we find entry */
rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0, locker, &lock );
rc = bdb_dn2entry_r( be, txn, entry_ndn, &e, NULL, 0, locker, &lock );
switch( rc ) {
case DB_NOTFOUND:
case 0:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
/* the txn must abort and retry */
if ( txn ) {
boi->boi_err = rc;
return LDAP_BUSY;
}
ldap_pvt_thread_yield();
goto dn2entry_retry;
default:
boi->boi_err = rc;
......
......@@ -157,6 +157,7 @@ struct bdb_op_info {
DB_TXN* boi_txn;
u_int32_t boi_err;
u_int32_t boi_locker;
int boi_acl_cache;
};
#define DB_OPEN(db, file, name, type, flags, mode) \
......
......@@ -794,7 +794,7 @@ try_again:
/*
* entry is deleted or not fully created yet
*/
if ( state != CACHE_ENTRY_READY ) {
if ( state != CACHE_ENTRY_READY && state != CACHE_ENTRY_COMMITTED ) {
assert(state != CACHE_ENTRY_UNDEFINED);
/* free cache read lock */
......@@ -889,7 +889,7 @@ try_again:
/*
* entry is deleted or not fully created yet
*/
if ( state != CACHE_ENTRY_READY ) {
if ( state != CACHE_ENTRY_READY && state != CACHE_ENTRY_COMMITTED ) {
assert(state != CACHE_ENTRY_UNDEFINED);
......
......@@ -70,6 +70,7 @@ retry: /* transaction retry */
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
......@@ -106,6 +107,7 @@ retry: /* transaction retry */
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
if ( !be_issuffix( be, ndn ) ) {
......@@ -162,13 +164,13 @@ retry: /* transaction retry */
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
p = NULL;
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( !rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: no write access to parent\n", 0, 0, 0 );
......@@ -195,13 +197,13 @@ retry: /* transaction retry */
p = NULL;
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( !rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: no access to parent\n", 0, 0, 0 );
......@@ -298,13 +300,13 @@ retry: /* transaction retry */
rc = access_allowed( be, conn, op, e,
entry, NULL, ACL_WRITE, NULL );
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( !rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: no write access to entry\n", 0, 0, 0 );
......
......@@ -107,11 +107,21 @@ bdb_group(
} else {
dn2entry_retry:
/* can we find group entry */
rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0, locker, &lock );
rc = bdb_dn2entry_r( be, txn, gr_ndn, &e, NULL, 0, locker, &lock );
if( rc ) {
if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED )
goto dn2entry_retry;
boi->boi_err = rc;
if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) {
if ( txn ) {
/* must let owning txn abort, but our result
* is still inconclusive, so don't let it
* get cached.
*/
op->o_do_not_cache = 1;
return( 1 );
}
ldap_pvt_thread_yield();
goto dn2entry_retry;
}
if ( free_lock_id ) {
LOCK_ID_FREE ( bdb->bi_dbenv, locker );
}
......@@ -206,8 +216,10 @@ dn2entry_retry:
group_oc_name, group_at_name, 0 );
#endif
if( value_find_ex( group_at, SLAP_MR_VALUE_NORMALIZED_MATCH,
attr->a_vals, op_ndn ) != LDAP_SUCCESS ) {
if( value_find_ex( group_at,
SLAP_MR_VALUE_NORMALIZED_MATCH,
attr->a_vals, op_ndn ) != LDAP_SUCCESS )
{
#ifdef NEW_LOGGING
LDAP_LOG( BACK_BDB, DETAIL1,
"bdb_group: \"%s\" not in \"%s\": %s\n",
......
......@@ -204,6 +204,18 @@ int bdb_entry_return(
if( (void *) e->e_attrs != (void *) (e+1)) {
attrs_free( e->e_attrs );
}
#ifdef SLAP_NVALUES
else {
/* nvals are not contiguous with the rest. oh well. */
Attribute *a;
for (a = e->e_attrs; a; a=a->a_next) {
if (a->a_nvals) {
ber_bvarray_free( a->a_nvals );
a->a_nvals = NULL;
}
}
}
#endif
#ifndef BDB_HIER
/* See if the DNs were changed by modrdn */
......
......@@ -210,7 +210,7 @@ int bdb_modify_internal(
for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
rc = bdb_index_values( be, tid, ap->a_desc, ap->a_vals,
e->e_id, SLAP_INDEX_DELETE_OP );
e->e_id, SLAP_INDEX_DELETE_OP );
if ( rc != LDAP_SUCCESS ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
......@@ -233,7 +233,7 @@ int bdb_modify_internal(
for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
if (ap->a_flags & SLAP_ATTR_IXADD) {
rc = bdb_index_values( be, tid, ap->a_desc, ap->a_vals,
e->e_id, SLAP_INDEX_ADD_OP );
e->e_id, SLAP_INDEX_ADD_OP );
if ( rc != LDAP_SUCCESS ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
......@@ -319,6 +319,7 @@ retry: /* transaction retry */
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
......@@ -351,6 +352,7 @@ retry: /* transaction retry */
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/* get entry */
......@@ -449,6 +451,9 @@ retry: /* transaction retry */
"bdb_modify: modify failed (%d)\n",
rc, 0, 0 );
#endif
if ( (rc == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
rc = opinfo.boi_err;
}
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
......
......@@ -108,6 +108,7 @@ retry: /* transaction retry */
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
......@@ -141,6 +142,7 @@ retry: /* transaction retry */
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/* get entry */
......@@ -191,13 +193,13 @@ retry: /* transaction retry */
/* check write on old entry */
rc = access_allowed( be, conn, op, e, entry, NULL, ACL_WRITE, NULL );
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"==>bdb_modrdn: no access to entry\n", 0, 0, 0 );
......@@ -277,6 +279,12 @@ retry: /* transaction retry */
children, NULL, ACL_WRITE, NULL );
if ( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rc = LDAP_INSUFFICIENT_ACCESS;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
......@@ -329,6 +337,12 @@ retry: /* transaction retry */
p = NULL;
if ( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rc = LDAP_INSUFFICIENT_ACCESS;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
......@@ -468,6 +482,12 @@ retry: /* transaction retry */
NULL, ACL_WRITE, NULL );
if( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"==>bdb_modrdn: no wr to newSup children\n", 0, 0, 0 );
......@@ -531,6 +551,12 @@ retry: /* transaction retry */
np = NULL;
if ( ! rc ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rc = LDAP_INSUFFICIENT_ACCESS;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
......@@ -621,15 +647,6 @@ retry: /* transaction retry */
goto return_results;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_modrdn: new ndn=%s does not exist\n", new_ndn.bv_val, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_modrdn: new ndn=%s does not exist\n",
new_ndn.bv_val, 0, 0 );
#endif
/* Get attribute type and attribute value of our new rdn, we will
* need to add that to our new entry
*/
......@@ -745,6 +762,9 @@ retry: /* transaction retry */
&text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
if ( ( rc == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
rc = opinfo.boi_err;
}
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
......
......@@ -29,63 +29,17 @@ bdb_hasSubordinates(
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int rc;
DB_TXN *ltid = NULL;
struct bdb_op_info opinfo;
assert( e );
assert( hasSubordinates );
if( 0 ) {
retry: /* transaction retry */
#if 0
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
}
#endif
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"=> bdb_hasSubordinates: retrying...\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE, "==> bdb_hasSubordinates: retrying...\n",
0, 0, 0 );
#endif
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
if( rc != 0 ) {
rc = LDAP_OTHER;
goto return_results;
}
ldap_pvt_thread_yield();
}
/* begin transaction */
rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, bdb->bi_db_opflags );
if ( rc != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"=> bdb_hasSubordinates: txn_begin failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_hasSubordinates: txn_begin failed: %s (%d)\n",
db_strerror( rc ), rc, 0 );
#endif
rc = LDAP_OTHER;
return rc;
}
opinfo.boi_bdb = be;
opinfo.boi_txn = ltid;
opinfo.boi_locker = TXN_ID ( ltid );
opinfo.boi_err = 0;
op->o_private = &opinfo;
rc = bdb_dn2id_children( be, ltid, &e->e_nname, 0 );
retry:
rc = bdb_dn2id_children( be, NULL, &e->e_nname, 0 );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
ldap_pvt_thread_yield();
goto retry;
case 0:
......@@ -110,18 +64,6 @@ retry: /* transaction retry */
rc = LDAP_OTHER;
}
return_results:
if ( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
ldap_pvt_thread_yield();
TXN_CHECKPOINT( bdb->bi_dbenv,
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
}
if ( ltid != NULL ) {
TXN_ABORT( ltid );
op->o_private = NULL;
}
return rc;
}
......
......@@ -122,6 +122,7 @@ retry: /* transaction retry */
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
*text = "internal error";
......@@ -155,6 +156,7 @@ retry: /* transaction retry */
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/* get entry */
......@@ -221,6 +223,9 @@ retry: /* transaction retry */
rc = bdb_modify_internal( be, conn, op, ltid,
&ml, e, text, textbuf, textlen );
if ( (rc == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
rc = opinfo.boi_err;
}
switch(rc) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
......
......@@ -84,7 +84,6 @@ bdb_search(
u_int32_t locker = 0;
DB_LOCK lock;
struct bdb_op_info opinfo;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
......@@ -136,12 +135,6 @@ bdb_search(
return rc;
}
opinfo.boi_bdb = be;
opinfo.boi_txn = NULL;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
op->o_private = &opinfo;
if ( nbase->bv_len == 0 ) {
/* DIT root special case */
e = (Entry *) &slap_entry_root;
......@@ -809,10 +802,10 @@ id2entry_retry:
} else {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: %ld does match filter\n", (long) id, 0, 0);
"bdb_search: %ld does not match filter\n", (long) id, 0, 0);
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: %ld does match filter\n",
"bdb_search: %ld does not match filter\n",
(long) id, 0, 0 );
#endif
}
......
......@@ -15,6 +15,16 @@
static DBC *cursor = NULL;
static DBT key, data;
typedef struct dn_id {
ID id;
struct berval dn;
} dn_id;
#define HOLE_SIZE 4096
dn_id hbuf[HOLE_SIZE], *holes = hbuf;
unsigned nhmax = HOLE_SIZE;
unsigned nholes;
int bdb_tool_entry_open(
BackendDB *be, int mode )
{
......@@ -46,6 +56,16 @@ int bdb_tool_entry_close(
cursor = NULL;
}
if( nholes ) {
unsigned i;
fprintf( stderr, "Error, entries missing!\n");
for (i=0; i<nholes; i++) {
fprintf(stderr, " entry %d: %s\n",
holes[i].id, holes[i].dn.bv_val, 0);
}