From: Howard Chu Date: Tue, 7 Oct 2008 00:40:52 +0000 (+0000) Subject: ITS#5728 release entries before send_ldap_ber() X-Git-Url: https://git.sur5r.net/?p=openldap;a=commitdiff_plain;h=cfc8c67523837451fe2810755bf5e5cbf791ddac ITS#5728 release entries before send_ldap_ber() --- diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 4a22fa00dd..ba0c477f70 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -212,18 +212,22 @@ struct bdb_info { struct bdb_lock_info { struct bdb_lock_info *bli_next; - ID bli_id; DB_LOCK bli_lock; + ID bli_id; + int bli_flag; }; +#define BLI_DONTFREE 1 struct bdb_op_info { BackendDB* boi_bdb; DB_TXN* boi_txn; + struct bdb_lock_info *boi_locks; /* used when no txn */ u_int32_t boi_err; u_int32_t boi_locker; - int boi_acl_cache; - struct bdb_lock_info *boi_locks; /* used when no txn */ + char boi_acl_cache; + char boi_flag; }; +#define BOI_DONTFREE 1 #define DB_OPEN(db, file, name, type, flags, mode) \ ((db)->open)(db, file, name, type, flags, mode) diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index 7a964bf6c2..88f2cfabbe 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -271,12 +271,17 @@ int bdb_entry_release( bdb_cache_return_entry_rw( bdb->bi_dbenv, &bdb->bi_cache, e, rw, &bli->bli_lock ); prev->bli_next = bli->bli_next; - op->o_tmpfree( bli, op->o_tmpmemctx ); + /* Cleanup, or let caller know we unlocked */ + if (bli->bli_flag & BLI_DONTFREE) + bli->bli_flag = 0; + else + op->o_tmpfree( bli, op->o_tmpmemctx ); break; } } if ( !boi->boi_locks ) { - op->o_tmpfree( boi, op->o_tmpmemctx ); + if ( !(boi->boi_flag & BOI_DONTFREE)) + op->o_tmpfree( boi, op->o_tmpmemctx ); op->o_private = NULL; } } diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index c11439ef60..19393c5261 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -837,6 +837,14 @@ fetch_entry_retry: op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE ); + /* free reader lock */ +#ifdef SLAP_ZONE_ALLOC + slap_zn_runlock(bdb->bi_cache.c_zctx, e); +#endif + bdb_cache_return_entry_r( bdb->bi_dbenv, + &bdb->bi_cache, e , &lock ); + e = NULL; + send_search_reference( op, rs ); ber_bvarray_free( rs->sr_ref ); @@ -870,14 +878,55 @@ fetch_entry_retry: } if (e) { + struct bdb_op_info bois, *boi2; + struct bdb_lock_info blis; + + /* Must set lockinfo so that entry_release will work */ + if (!opinfo) { + boi2 = &bois; + op->o_private = boi2; + bois.boi_bdb = op->o_bd; + bois.boi_txn = NULL; + bois.boi_locker = locker; + bois.boi_err = 0; + bois.boi_locks = &blis; + blis.bli_next = NULL; + bois.boi_flag = BOI_DONTFREE; + } else { + boi2 = opinfo; + blis.bli_next = boi2->boi_locks; + boi2->boi_locks = &blis; + } + blis.bli_id = e->e_id; + blis.bli_lock = lock; + blis.bli_flag = BLI_DONTFREE; + /* safe default */ rs->sr_attrs = op->oq_search.rs_attrs; rs->sr_operational_attrs = NULL; rs->sr_ctrls = NULL; - rs->sr_flags = 0; + rs->sr_flags = REP_ENTRY_MUSTRELEASE; rs->sr_err = LDAP_SUCCESS; rs->sr_err = send_search_entry( op, rs ); + /* send_search_entry will usually free it. + * an overlay might leave its own copy here; + * bli_flag will be 0 if lock was already released. + */ + if ( blis.bli_flag ) { +#ifdef SLAP_ZONE_ALLOC + slap_zn_runlock(bdb->bi_cache.c_zctx, e); +#endif + bdb_cache_return_entry_r(bdb->bi_dbenv, + &bdb->bi_cache, e, &lock); + op->o_private = opinfo; + if ( opinfo ) { + opinfo->boi_locks = blis.bli_next; + } + } + rs->sr_entry = NULL; + e = NULL; + switch ( rs->sr_err ) { case LDAP_SUCCESS: /* entry sent ok */ break; @@ -885,13 +934,6 @@ fetch_entry_retry: break; case LDAP_UNAVAILABLE: case LDAP_SIZELIMIT_EXCEEDED: -#ifdef SLAP_ZONE_ALLOC - slap_zn_runlock(bdb->bi_cache.c_zctx, e); -#endif - bdb_cache_return_entry_r(bdb->bi_dbenv, - &bdb->bi_cache, e, &lock); - e = NULL; - rs->sr_entry = NULL; if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) { rs->sr_ref = rs->sr_v2ref; send_ldap_result( op, rs );