diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c
index fd54c03fcca7f4b88832cbf321540f020f0eb33e..c17af5e928c675583d8805229255a9a499371025 100644
--- a/servers/slapd/back-meta/modify.c
+++ b/servers/slapd/back-meta/modify.c
@@ -37,6 +37,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
 	metainfo_t	*mi = ( metainfo_t * )op->o_bd->be_private;
 	metaconn_t	*mc;
 	int		rc = 0;
+	int		maperr = 1;
 	LDAPMod		**modv = NULL;
 	LDAPMod		*mods = NULL;
 	Modifications	*ml;
@@ -64,7 +65,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
 	dc.ctx = "modifyDN";
 
 	if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
-		rc = -1;
+		maperr = 0;
 		goto cleanup;
 	}
 
@@ -74,13 +75,13 @@ meta_back_modify( Operation *op, SlapReply *rs )
 	mods = ch_malloc( sizeof( LDAPMod )*i );
 	if ( mods == NULL ) {
 		rs->sr_err = LDAP_NO_MEMORY;
-		rc = -1;
+		maperr = 0;
 		goto cleanup;
 	}
 	modv = ( LDAPMod ** )ch_malloc( ( i + 1 )*sizeof( LDAPMod * ) );
 	if ( modv == NULL ) {
 		rs->sr_err = LDAP_NO_MEMORY;
-		rc = -1;
+		maperr = 0;
 		goto cleanup;
 	}
 
@@ -178,9 +179,10 @@ retry:;
 			modv, op->o_ctrls, NULL, &msgid );
 	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
 		do_retry = 0;
-		if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
+		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
 			goto retry;
 		}
+		goto done;
 
 	} else if ( rs->sr_err == LDAP_SUCCESS ) {
 		struct timeval	tv, *tvp = NULL;
@@ -197,7 +199,7 @@ retry:;
 			msgid, LDAP_MSG_ALL, tvp, &res );
 		switch ( rc ) {
 		case -1:
-			rc = -1;
+			maperr = 0;
 			break;
 
 		case 0:
@@ -205,7 +207,7 @@ retry:;
 				msgid, NULL, NULL );
 			rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
 				LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
-			rc = -1;
+			maperr = 0;
 			break;
 
 		case LDAP_RES_MODIFY:
@@ -214,17 +216,25 @@ retry:;
 			if ( rc != LDAP_SUCCESS ) {
 				rs->sr_err = rc;
 			}
-			rc = 0;
+			maperr = 1;
 			break;
 
 		default:
-			rc = -1;
+			maperr = 0;
 			ldap_msgfree( res );
 			break;
 		}
 	}
 
 cleanup:;
+	if ( maperr ) {
+		rc = meta_back_op_result( mc, op, rs, candidate );
+
+	} else {
+		send_ldap_result( op, rs );
+	}
+
+done:;
 	if ( mdn.bv_val != op->o_req_dn.bv_val ) {
 		free( mdn.bv_val );
 		BER_BVZERO( &mdn );
@@ -237,16 +247,10 @@ cleanup:;
 	free( mods );
 	free( modv );
 
-	if ( rc != -1 ) {
-		rc = meta_back_op_result( mc, op, rs, candidate );
-
-	} else {
-		send_ldap_result( op, rs );
-		rc = 0;
+	if ( mc ) {
+		meta_back_release_conn( op, mc );
 	}
 
-	meta_back_release_conn( op, mc );
-
-	return rc;
+	return rs->sr_err;
 }
 
diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c
index 0b0fcfb0edf3a22f64fd897c08dafe74745328c5..a490553b64762317e15abd0d0a816eb3b936d4d2 100644
--- a/servers/slapd/back-meta/modrdn.c
+++ b/servers/slapd/back-meta/modrdn.c
@@ -42,6 +42,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
 	dncookie	dc;
 	int		msgid;
 	int		do_retry = 1;
+	int		maperr = 1;
 
 	mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
 	if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
@@ -87,6 +88,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
 		dc.ctx = "newSuperiorDN";
 		if ( ldap_back_dn_massage( &dc, op->orr_newSup, &mnewSuperior ) ) {
 			rs->sr_err = LDAP_OTHER;
+			maperr = 0;
 			goto cleanup;
 		}
 	}
@@ -98,6 +100,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
 	dc.ctx = "modrDN";
 	if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
 		rs->sr_err = LDAP_OTHER;
+		maperr = 0;
 		goto cleanup;
 	}
 
@@ -108,9 +111,10 @@ retry:;
 			op->o_ctrls, NULL, &msgid );
 	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
 		do_retry = 0;
-		if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
+		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
 			goto retry;
 		}
+		goto done;
 
 	} else if ( rs->sr_err == LDAP_SUCCESS ) {
 		struct timeval	tv, *tvp = NULL;
@@ -126,6 +130,7 @@ retry:;
 		rs->sr_err = LDAP_OTHER;
 		rc = ldap_result( mc->mc_conns[ candidate ].msc_ld,
 			msgid, LDAP_MSG_ALL, tvp, &res );
+		maperr = 0;
 		switch ( rc ) {
 		case -1:
 			break;
@@ -143,6 +148,7 @@ retry:;
 			if ( rc != LDAP_SUCCESS ) {
 				rs->sr_err = rc;
 			}
+			maperr = 1;
 			break;
 
 		default:
@@ -152,6 +158,14 @@ retry:;
 	}
 
 cleanup:;
+	if ( maperr ) {
+		meta_back_op_result( mc, op, rs, candidate );
+
+	} else {
+		send_ldap_result( op, rs );
+	}
+
+done:;
 	if ( mdn.bv_val != op->o_req_dn.bv_val ) {
 		free( mdn.bv_val );
 		BER_BVZERO( &mdn );
@@ -164,14 +178,10 @@ cleanup:;
 		BER_BVZERO( &mnewSuperior );
 	}
 
-	if ( rs->sr_err == LDAP_SUCCESS ) {
-		meta_back_op_result( mc, op, rs, candidate );
-	} else {
-		send_ldap_result( op, rs );
+	if ( mc ) {
+		meta_back_release_conn( op, mc );
 	}
 
-	meta_back_release_conn( op, mc );
-
 	return rs->sr_err;
 }
 
diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c
index 668f8c94473707c29bf48f551afafcba9e9eff5b..edbf6550ea6b0bd9902d65be35197a79b1e9f9f1 100644
--- a/servers/slapd/back-meta/search.c
+++ b/servers/slapd/back-meta/search.c
@@ -416,7 +416,7 @@ really_bad:;
 				if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
 					candidates[ i ].sr_type = REP_RESULT;
 
-					if ( meta_back_retry( op, rs, mc, i, LDAP_BACK_DONTSEND ) ) {
+					if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
 						switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
 						{
 						case META_SEARCH_CANDIDATE:
@@ -427,6 +427,12 @@ really_bad:;
 							goto finish;
 						}
 					}
+
+					savepriv = op->o_private;
+					op->o_private = (void *)i;
+					send_ldap_result( op, rs );
+					op->o_private = savepriv;
+					goto finish;
 				}
 
 				/*
@@ -468,7 +474,10 @@ really_bad:;
 				}
 				op->o_private = savepriv;
 
+				/* don't wait any longer... */
 				gotit = 1;
+				tv.tv_sec = 0;
+				tv.tv_usec = 0;
 
 #if 0
 				/*
@@ -574,16 +583,16 @@ really_bad:;
 				 * back-meta would need to merge them
 				 * consistently (think of pagedResults...)
 				 */
-				if ( ldap_parse_result( msc->msc_ld,
+				rs->sr_err = ldap_parse_result( msc->msc_ld,
 							res,
 							&candidates[ i ].sr_err,
 							(char **)&candidates[ i ].sr_matched,
 							NULL /* (char **)&candidates[ i ].sr_text */ ,
 							&references,
 							NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
-							1 ) != LDAP_SUCCESS )
-				{
-					res = NULL;
+							1 );
+				res = NULL;
+				if ( rs->sr_err != LDAP_SUCCESS ) {
 					ldap_get_option( msc->msc_ld,
 							LDAP_OPT_ERROR_NUMBER,
 							&rs->sr_err );
@@ -592,10 +601,6 @@ really_bad:;
 					goto really_bad;
 				}
 
-				rs->sr_err = candidates[ i ].sr_err;
-				sres = slap_map_api2result( rs );
-				res = NULL;
-
 				/* massage matchedDN if need be */
 				if ( candidates[ i ].sr_matched != NULL ) {
 #ifndef LDAP_NULL_IS_NULL
@@ -671,13 +676,21 @@ really_bad:;
 				rs->sr_err = candidates[ i ].sr_err;
 				sres = slap_map_api2result( rs );
 
-				snprintf( buf, sizeof( buf ),
-					"%s meta_back_search[%ld] "
-					"match=\"%s\" err=%ld\n",
-					op->o_log_prefix, i,
-					candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
-					(long) candidates[ i ].sr_err );
-				Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 );
+				if ( StatslogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
+					snprintf( buf, sizeof( buf ),
+						"%s meta_back_search[%ld] "
+						"match=\"%s\" err=%ld",
+						op->o_log_prefix, i,
+						candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
+						(long) candidates[ i ].sr_err );
+					if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
+						Debug( LDAP_DEBUG_TRACE, "%s.\n", buf, 0, 0 );
+
+					} else {
+						Debug( LDAP_DEBUG_ANY, "%s (%s).\n",
+							buf, ldap_err2string( candidates[ i ].sr_err ), 0 );
+					}
+				}
 
 				switch ( sres ) {
 				case LDAP_NO_SUCH_OBJECT:
@@ -697,6 +710,26 @@ really_bad:;
 					is_ok++;
 					break;
 
+				case LDAP_SIZELIMIT_EXCEEDED:
+					/* if a target returned sizelimitExceeded
+					 * and the entry count is equal to the
+					 * proxy's limit, the target would have
+					 * returned more, and the error must be
+					 * propagated to the client; otherwise,
+					 * the target enforced a limit lower
+					 * than what requested by the proxy;
+					 * ignore it */
+					if ( rs->sr_nentries == op->ors_slimit
+						|| META_BACK_ONERR_STOP( mi ) )
+					{
+						savepriv = op->o_private;
+						op->o_private = (void *)i;
+						send_ldap_result( op, rs );
+						op->o_private = savepriv;
+						goto finish;
+					}
+					break;
+
 				default:
 					if ( META_BACK_ONERR_STOP( mi ) ) {
 						savepriv = op->o_private;
@@ -743,13 +776,11 @@ really_bad:;
 			}
 		}
 
+		/* if no entry was found during this loop,
+		 * set a minimal timeout */
 		if ( gotit == 0 ) {
 			LDAP_BACK_TV_SET( &tv );
                         ldap_pvt_thread_yield();
-
-		} else {
-			tv.tv_sec = 0;
-			tv.tv_usec = 0;
 		}
 	}
 
@@ -903,7 +934,9 @@ finish:;
 		}
 	}
 
-	meta_back_release_conn( op, mc );
+	if ( mc ) {
+		meta_back_release_conn( op, mc );
+	}
 
 	return rs->sr_err;
 }
@@ -1158,6 +1191,7 @@ next_attr:;
 	rs->sr_entry = &ent;
 	rs->sr_attrs = op->ors_attrs;
 	rs->sr_flags = 0;
+	rs->sr_err = LDAP_SUCCESS;
 	rc = send_search_entry( op, rs );
 	switch ( rc ) {
 	case LDAP_UNAVAILABLE: