diff --git a/CHANGES b/CHANGES
index 99921383ccc63756aee8ee083c94a56ba02bfbe3..e1619a9fa125b990c875f78c470d16157ec9446b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,7 @@ OpenLDAP 2.4.20 Engineering
 	Fixed libldap uninitialized return value (ITS#6355)
 	Fixed liblutil constant (ITS#5909)
 	Added slapd handling of hex server IDs (ITS#6297)
+	Added slapd syncrepl contextCSN storing in subentry (ITS#6373)
 	Fixed slapd asserts in minimal environment (ITS#6361)
 	Fixed slapd configArgs initialization (ITS#6363)
 	Fixed slapd debug handling of LDAP_DEBUG_ANY (ITS#6324)
diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
index a646deecefb2e575354970eb662e566c281d2b7f..8ec7a52744bb89eed470126e70e9101bdb5c72d7 100644
--- a/doc/man/man5/slapd-config.5
+++ b/doc/man/man5/slapd-config.5
@@ -1614,6 +1614,11 @@ with the inner suffix must come first in the configuration file.
 You may also want to glue such databases together with the
 .B olcSubordinate
 attribute.
+.TP
+.B olcSyncUseSubentry: TRUE | FALSE
+Store the syncrepl contextCSN in a subentry instead of the context entry
+of the database. The subentry's RDN will be "cn=ldapsync". The default is
+FALSE, meaning the contextCSN is stored in the context entry.
 .HP
 .hy 0
 .B olcSyncrepl: rid=<replica ID>
diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
index 0ff35429e9b95152b43186ba71dd4fd058ebd07a..8d0e3c88cc4dd46b14bd9c0e7203f33d1b08cbef 100644
--- a/doc/man/man5/slapd.conf.5
+++ b/doc/man/man5/slapd.conf.5
@@ -1602,6 +1602,11 @@ in order to work over all of the glued databases. E.g.
 	overlay syncprov
 .fi
 .RE
+.TP
+.B sync_use_subentry 
+Store the syncrepl contextCSN in a subentry instead of the context entry
+of the database. The subentry's RDN will be "cn=ldapsync". By default
+the contextCSN is stored in the context entry.
 .HP
 .hy 0
 .B syncrepl rid=<replica ID>
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index 90cd6229261de78f65fd8f013b43a82db06a2224..dbed5f1b83a0ad7566f4368248eccf41e459673a 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -190,6 +190,7 @@ enum {
 	CFG_IX_INTLEN,
 	CFG_SYNTAX,
 	CFG_ACL_ADD,
+	CFG_SYNC_SUBENTRY,
 
 	CFG_LAST
 };
@@ -604,6 +605,10 @@ static ConfigTable config_back_cf_table[] = {
 		&config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
 			"EQUALITY distinguishedNameMatch "
 			"SYNTAX OMsDN )", NULL, NULL },
+	{ "sync_use_subentry", NULL, 0, 0, 0, ARG_ON_OFF|ARG_DB|ARG_MAGIC|CFG_SYNC_SUBENTRY,
+		&config_generic, "( OLcfgDbAt:0.19 NAME 'olcSyncUseSubentry' "
+			"DESC 'Store sync context in a subentry' "
+			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
 	{ "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
 		&syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
 			"EQUALITY caseIgnoreMatch "
@@ -815,7 +820,7 @@ static ConfigOCs cf_ocs[] = {
 		 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
 		 "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ "
 		 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
-		 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncrepl $ "
+		 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncUseSubentry $ olcSyncrepl $ "
 		 "olcTimeLimit $ olcUpdateDN $ olcUpdateRef $ olcMirrorMode $ "
 		 "olcMonitoring ) )",
 		 	Cft_Database, NULL, cfAddDatabase },
@@ -1085,6 +1090,9 @@ config_generic(ConfigArgs *c) {
 		case CFG_LASTMOD:
 			c->value_int = (SLAP_NOLASTMOD(c->be) == 0);
 			break;
+		case CFG_SYNC_SUBENTRY:
+			c->value_int = (SLAP_SYNC_SUBENTRY(c->be) != 0);
+			break;
 		case CFG_MIRRORMODE:
 			if ( SLAP_SHADOW(c->be))
 				c->value_int = (SLAP_SINGLE_SHADOW(c->be) == 0);
@@ -1197,6 +1205,7 @@ config_generic(ConfigArgs *c) {
 		case CFG_SSTR_IF_MAX:
 		case CFG_SSTR_IF_MIN:
 		case CFG_ACL_ADD:
+		case CFG_SYNC_SUBENTRY:
 			break;
 
 		/* no-ops, requires slapd restart */
@@ -1901,6 +1910,13 @@ sortval_reject:
 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_HIDDEN;
 			break;
 
+		case CFG_SYNC_SUBENTRY:
+			if (c->value_int)
+				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SYNC_SUBENTRY;
+			else
+				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SYNC_SUBENTRY;
+			break;
+
 		case CFG_SSTR_IF_MAX:
 			if (c->value_uint < index_substr_if_minlen) {
 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] );
diff --git a/servers/slapd/ctxcsn.c b/servers/slapd/ctxcsn.c
index cb828999ccfea8d971949cf05858ae5358cfcf7f..95d7ba6ed1e36dae33b7b8696fa0dfac15ea5f63 100644
--- a/servers/slapd/ctxcsn.c
+++ b/servers/slapd/ctxcsn.c
@@ -26,6 +26,8 @@
 #include "slap.h"
 #include "lutil_ldap.h"
 
+const struct berval slap_ldapsync_bv = BER_BVC("ldapsync");
+const struct berval slap_ldapsync_cn_bv = BER_BVC("cn=ldapsync");
 int slap_serverID;
 
 /* maxcsn->bv_val must point to a char buf[LDAP_LUTIL_CSNSTR_BUFSIZE] */
@@ -133,6 +135,46 @@ slap_graduate_commit_csn( Operation *op )
 	return;
 }
 
+static struct berval ocbva[] = {
+	BER_BVC("top"),
+	BER_BVC("subentry"),
+	BER_BVC("syncProviderSubentry"),
+	BER_BVNULL
+};
+
+Entry *
+slap_create_context_csn_entry(
+	Backend *be,
+	struct berval *context_csn )
+{
+	Entry* e;
+
+	struct berval bv;
+
+	e = entry_alloc();
+
+	attr_merge( e, slap_schema.si_ad_objectClass,
+		ocbva, NULL );
+	attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
+		&ocbva[1], NULL );
+	attr_merge_one( e, slap_schema.si_ad_cn,
+		(struct berval *)&slap_ldapsync_bv, NULL );
+
+	if ( context_csn ) {
+		attr_merge_one( e, slap_schema.si_ad_contextCSN,
+			context_csn, NULL );
+	}
+
+	BER_BVSTR( &bv, "{}" );
+	attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
+
+	build_new_dn( &e->e_name, &be->be_nsuffix[0],
+		(struct berval *)&slap_ldapsync_cn_bv, NULL );
+	ber_dupbv( &e->e_nname, &e->e_name );
+
+	return e;
+}
+
 void
 slap_queue_csn(
 	Operation *op,
diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c
index 2a1c565e02d3ab277c4ee2a49e962e721554480d..49a2cbe8da6e030d5274745a4259b83b69266b51 100644
--- a/servers/slapd/overlays/syncprov.c
+++ b/servers/slapd/overlays/syncprov.c
@@ -124,6 +124,7 @@ typedef struct sessionlog {
 typedef struct syncprov_info_t {
 	syncops		*si_ops;
 	BerVarray	si_ctxcsn;	/* ldapsync context */
+	struct berval	si_contextdn;
 	int		*si_sids;
 	int		si_numcsns;
 	int		si_chkops;	/* checkpointing info */
@@ -1361,6 +1362,7 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
 	SlapReply rsm = { 0 };
 	slap_callback cb = {0};
 	BackendDB be;
+
 #ifdef CHECK_CSN
 	Syntax *syn = slap_schema.si_ad_contextCSN->ad_type->sat_syntax;
 
@@ -1387,12 +1389,26 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
 		be = *on->on_info->oi_origdb;
 		opm.o_bd = &be;
 	}
-	opm.o_req_dn = opm.o_bd->be_suffix[0];
-	opm.o_req_ndn = opm.o_bd->be_nsuffix[0];
+	opm.o_req_dn = si->si_contextdn;
+	opm.o_req_ndn = si->si_contextdn;
 	opm.o_bd->bd_info = on->on_info->oi_orig;
 	opm.o_managedsait = SLAP_CONTROL_NONCRITICAL;
 	opm.o_no_schema_check = 1;
 	opm.o_bd->be_modify( &opm, &rsm );
+
+	if ( rsm.sr_err == LDAP_NO_SUCH_OBJECT &&
+		SLAP_SYNC_SUBENTRY( opm.o_bd )) {
+		const char	*text;
+		char txtbuf[SLAP_TEXT_BUFLEN];
+		size_t textlen = sizeof txtbuf;
+		Entry *e = slap_create_context_csn_entry( opm.o_bd, NULL );
+		slap_mods2entry( &mod, &e, 0, 1, &text, txtbuf, textlen);
+		opm.ora_e = e;
+		opm.o_bd->be_add( &opm, &rsm );
+		if ( e == opm.ora_e )
+			be_entry_release_w( &opm, opm.ora_e );
+	}
+
 	if ( mod.sml_next != NULL ) {
 		slap_mods_free( mod.sml_next, 1 );
 	}
@@ -1763,7 +1779,7 @@ syncprov_op_response( Operation *op, SlapReply *rs )
 			 * it will deadlock
 			 */
 			if ( op->o_tag != LDAP_REQ_ADD ||
-				!dn_match( &op->o_req_ndn, &op->o_bd->be_nsuffix[0] )) {
+				!dn_match( &op->o_req_ndn, &si->si_contextdn )) {
 				if ( si->si_chkops && si->si_numops >= si->si_chkops ) {
 					do_check = 1;
 					si->si_numops = 0;
@@ -1837,14 +1853,14 @@ syncprov_op_compare( Operation *op, SlapReply *rs )
 	syncprov_info_t		*si = on->on_bi.bi_private;
 	int rc = SLAP_CB_CONTINUE;
 
-	if ( dn_match( &op->o_req_ndn, op->o_bd->be_nsuffix ) &&
+	if ( dn_match( &op->o_req_ndn, &si->si_contextdn ) &&
 		op->oq_compare.rs_ava->aa_desc == slap_schema.si_ad_contextCSN )
 	{
 		Entry e = {0};
 		Attribute a = {0};
 
-		e.e_name = op->o_bd->be_suffix[0];
-		e.e_nname = op->o_bd->be_nsuffix[0];
+		e.e_name = si->si_contextdn;
+		e.e_nname = si->si_contextdn;
 		e.e_attrs = &a;
 
 		a.a_desc = slap_schema.si_ad_contextCSN;
@@ -2583,7 +2599,7 @@ syncprov_operational(
 		return SLAP_CB_CONTINUE;
 
 	if ( rs->sr_entry &&
-		dn_match( &rs->sr_entry->e_nname, op->o_bd->be_nsuffix )) {
+		dn_match( &rs->sr_entry->e_nname, &si->si_contextdn )) {
 
 		if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
 			ad_inlist( slap_schema.si_ad_contextCSN, rs->sr_attrs )) {
@@ -2876,7 +2892,13 @@ syncprov_db_open(
 	op->o_dn = be->be_rootdn;
 	op->o_ndn = be->be_rootndn;
 
-	rc = overlay_entry_get_ov( op, be->be_nsuffix, NULL,
+	if ( SLAP_SYNC_SUBENTRY( be )) {
+		build_new_dn( &si->si_contextdn, be->be_nsuffix,
+			(struct berval *)&slap_ldapsync_cn_bv, NULL );
+	} else {
+		si->si_contextdn = be->be_nsuffix[0];
+	}
+	rc = overlay_entry_get_ov( op, &si->si_contextdn, NULL,
 		slap_schema.si_ad_contextCSN, 0, &e, on );
 
 	if ( e ) {
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index d8a38ba801e9a421febe7df13b3894dbcf7d2ca5..0866c9f2b247f1350bb124a4a756d2e1a9933b1b 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -814,10 +814,13 @@ LDAP_SLAPD_F (ContentRule *) cr_bvfind LDAP_P((
  */
 
 LDAP_SLAPD_V( int ) slap_serverID;
+LDAP_SLAPD_V( const struct berval ) slap_ldapsync_bv;
+LDAP_SLAPD_V( const struct berval ) slap_ldapsync_cn_bv;
 LDAP_SLAPD_F (void) slap_get_commit_csn LDAP_P((
 	Operation *, struct berval *maxcsn, int *foundit ));
 LDAP_SLAPD_F (void) slap_rewind_commit_csn LDAP_P(( Operation * ));
 LDAP_SLAPD_F (void) slap_graduate_commit_csn LDAP_P(( Operation * ));
+LDAP_SLAPD_F (Entry *) slap_create_context_csn_entry LDAP_P(( Backend *, struct berval *));
 LDAP_SLAPD_F (int) slap_get_csn LDAP_P(( Operation *, struct berval *, int ));
 LDAP_SLAPD_F (void) slap_queue_csn LDAP_P(( Operation *, struct berval * ));
 
diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c
index e12a82946fad2fbc7ae0c9caa64b128f95ea5692..7e17377876d5eb3762a5032ca132f28d852732f7 100644
--- a/servers/slapd/sasl.c
+++ b/servers/slapd/sasl.c
@@ -266,7 +266,8 @@ slap_auxprop_lookup(
 	const char *user,
 	unsigned ulen)
 {
-	Operation op = {0};
+	OperationBuffer opbuf = {0};
+	Operation *op = (Operation *)&opbuf;
 	int i, doit = 0;
 	Connection *conn = NULL;
 	lookup_info sl;
@@ -286,22 +287,22 @@ slap_auxprop_lookup(
 			if ( flags & SASL_AUXPROP_AUTHZID ) {
 				if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) {
 					if ( sl.list[i].values && sl.list[i].values[0] )
-						AC_MEMCPY( &op.o_req_ndn.bv_len, sl.list[i].values[0],
-							sizeof( op.o_req_ndn.bv_len ) );
+						AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
+							sizeof( op->o_req_ndn.bv_len ) );
 				} else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) {
 					if ( sl.list[i].values )
-						op.o_req_ndn.bv_val = (char *)sl.list[i].values[0];
+						op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
 					break;
 				}
 			}
 
 			if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) {
 				if ( sl.list[i].values && sl.list[i].values[0] )
-					AC_MEMCPY( &op.o_req_ndn.bv_len, sl.list[i].values[0],
-						sizeof( op.o_req_ndn.bv_len ) );
+					AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
+						sizeof( op->o_req_ndn.bv_len ) );
 			} else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) {
 				if ( sl.list[i].values ) {
-					op.o_req_ndn.bv_val = (char *)sl.list[i].values[0];
+					op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
 					if ( !(flags & SASL_AUXPROP_AUTHZID) )
 						break;
 				}
@@ -336,30 +337,30 @@ slap_auxprop_lookup(
 
 		cb.sc_private = &sl;
 
-		op.o_bd = select_backend( &op.o_req_ndn, 1 );
+		op->o_bd = select_backend( &op->o_req_ndn, 1 );
 
-		if ( op.o_bd ) {
+		if ( op->o_bd ) {
 			/* For rootdn, see if we can use the rootpw */
-			if ( be_isroot_dn( op.o_bd, &op.o_req_ndn ) &&
-				!BER_BVISEMPTY( &op.o_bd->be_rootpw )) {
+			if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) &&
+				!BER_BVISEMPTY( &op->o_bd->be_rootpw )) {
 				struct berval cbv = BER_BVNULL;
 
 				/* If there's a recognized scheme, see if it's CLEARTEXT */
-				if ( lutil_passwd_scheme( op.o_bd->be_rootpw.bv_val )) {
-					if ( !strncasecmp( op.o_bd->be_rootpw.bv_val,
+				if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) {
+					if ( !strncasecmp( op->o_bd->be_rootpw.bv_val,
 						sc_cleartext.bv_val, sc_cleartext.bv_len )) {
 
 						/* If it's CLEARTEXT, skip past scheme spec */
-						cbv.bv_len = op.o_bd->be_rootpw.bv_len -
+						cbv.bv_len = op->o_bd->be_rootpw.bv_len -
 							sc_cleartext.bv_len;
 						if ( cbv.bv_len ) {
-							cbv.bv_val = op.o_bd->be_rootpw.bv_val +
+							cbv.bv_val = op->o_bd->be_rootpw.bv_val +
 								sc_cleartext.bv_len;
 						}
 					}
 				/* No scheme, use the whole value */
 				} else {
-					cbv = op.o_bd->be_rootpw;
+					cbv = op->o_bd->be_rootpw;
 				}
 				if ( !BER_BVISEMPTY( &cbv )) {
 					for( i = 0; sl.list[i].name; i++ ) {
@@ -380,27 +381,28 @@ slap_auxprop_lookup(
 				}
 			}
 
-			if ( op.o_bd->be_search ) {
+			if ( op->o_bd->be_search ) {
 				SlapReply rs = {REP_RESULT};
-				op.o_hdr = conn->c_sasl_bindop->o_hdr;
-				op.o_tag = LDAP_REQ_SEARCH;
-				op.o_dn = conn->c_ndn;
-				op.o_ndn = conn->c_ndn;
-				op.o_callback = &cb;
-				slap_op_time( &op.o_time, &op.o_tincr );
-				op.o_do_not_cache = 1;
-				op.o_is_auth_check = 1;
-				op.o_req_dn = op.o_req_ndn;
-				op.ors_scope = LDAP_SCOPE_BASE;
-				op.ors_deref = LDAP_DEREF_NEVER;
-				op.ors_tlimit = SLAP_NO_LIMIT;
-				op.ors_slimit = 1;
-				op.ors_filter = &generic_filter;
-				op.ors_filterstr = generic_filterstr;
+				op->o_hdr = conn->c_sasl_bindop->o_hdr;
+				op->o_controls = opbuf.ob_controls;
+				op->o_tag = LDAP_REQ_SEARCH;
+				op->o_dn = conn->c_ndn;
+				op->o_ndn = conn->c_ndn;
+				op->o_callback = &cb;
+				slap_op_time( &op->o_time, &op->o_tincr );
+				op->o_do_not_cache = 1;
+				op->o_is_auth_check = 1;
+				op->o_req_dn = op->o_req_ndn;
+				op->ors_scope = LDAP_SCOPE_BASE;
+				op->ors_deref = LDAP_DEREF_NEVER;
+				op->ors_tlimit = SLAP_NO_LIMIT;
+				op->ors_slimit = 1;
+				op->ors_filter = &generic_filter;
+				op->ors_filterstr = generic_filterstr;
 				/* FIXME: we want all attributes, right? */
-				op.ors_attrs = NULL;
+				op->ors_attrs = NULL;
 
-				op.o_bd->be_search( &op, &rs );
+				op->o_bd->be_search( op, &rs );
 			}
 		}
 	}
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 18e11a6e588270b8cb9c4f41669ba8fb7ccdd74a..ef9c40f7b91665c74a16bdba18bab8790695912b 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1804,6 +1804,7 @@ struct BackendDB {
 #define SLAP_DBFLAG_SHADOW_MASK		(SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SINGLE_SHADOW|SLAP_DBFLAG_SYNC_SHADOW|SLAP_DBFLAG_SLURP_SHADOW)
 #define SLAP_DBFLAG_CLEAN		0x10000U /* was cleanly shutdown */
 #define SLAP_DBFLAG_ACL_ADD		0x20000U /* check attr ACLs on adds */
+#define SLAP_DBFLAG_SYNC_SUBENTRY	0x40000U /* use subentry for context */
 	slap_mask_t	be_flags;
 #define SLAP_DBFLAGS(be)			((be)->be_flags)
 #define SLAP_NOLASTMOD(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_NOLASTMOD)
@@ -1830,6 +1831,7 @@ struct BackendDB {
 #define SLAP_MULTIMASTER(be)			(!SLAP_SINGLE_SHADOW(be))
 #define SLAP_DBCLEAN(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_CLEAN)
 #define SLAP_DBACL_ADD(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_ACL_ADD)
+#define SLAP_SYNC_SUBENTRY(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_SYNC_SUBENTRY)
 
 	slap_mask_t	be_restrictops;		/* restriction operations */
 #define SLAP_RESTRICT_OP_ADD		0x0001U
diff --git a/servers/slapd/slapadd.c b/servers/slapd/slapadd.c
index 4159d8ff42ef2258a9382913ec48a2d0e2db95dc..a57511eb7384423c2006f0f88b40ab83f8d84bf1 100644
--- a/servers/slapd/slapadd.c
+++ b/servers/slapd/slapadd.c
@@ -438,10 +438,32 @@ slapadd( int argc, char **argv )
 	}
 
 	if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) {
-		ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix );
+		struct berval ctxdn;
+		if ( SLAP_SYNC_SUBENTRY( be )) {
+			build_new_dn( &ctxdn, &be->be_nsuffix[0],
+				(struct berval *)&slap_ldapsync_cn_bv, NULL );
+		} else {
+			ctxdn = be->be_nsuffix[0];
+		}
+		ctxcsn_id = be->be_dn2id_get( be, &ctxdn );
 		if ( ctxcsn_id == NOID ) {
-			fprintf( stderr, "%s: context entry is missing\n", progname );
-			rc = EXIT_FAILURE;
+			if ( SLAP_SYNC_SUBENTRY( be )) {
+				ctxcsn_e = slap_create_context_csn_entry( be, NULL );
+				for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+					if ( maxcsn[ sid ].bv_len ) {
+						attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN,
+							&maxcsn[ sid ], NULL );
+					}
+				}
+				ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+				if ( ctxcsn_id == NOID ) {
+					fprintf( stderr, "%s: couldn't create context entry\n", progname );
+					rc = EXIT_FAILURE;
+				}
+			} else {
+				fprintf( stderr, "%s: context entry is missing\n", progname );
+				rc = EXIT_FAILURE;
+			}
 		} else {
 			ctxcsn_e = be->be_entry_get( be, ctxcsn_id );
 			if ( ctxcsn_e != NULL ) {
diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c
index 22496b66b3825f246c2f5f7a5f75bb097aafa2ae..e0982518243d04b101ec0efea0e863ddd22ffb8c 100644
--- a/servers/slapd/syncrepl.c
+++ b/servers/slapd/syncrepl.c
@@ -70,6 +70,7 @@ typedef struct syncinfo_s {
 	struct berval		si_logbase;
 	struct berval		si_filterstr;
 	struct berval		si_logfilterstr;
+	struct berval		si_contextdn;
 	int			si_scope;
 	int			si_attrsonly;
 	char			*si_anfile;
@@ -119,7 +120,7 @@ static int syncrepl_entry(
 					Modifications**,int, struct berval*,
 					struct berval *cookieCSN );
 static int syncrepl_updateCookie(
-					syncinfo_t *, Operation *, struct berval *,
+					syncinfo_t *, Operation *,
 					struct sync_cookie * );
 static struct berval * slap_uuidstr_from_normalized(
 					struct berval *, struct berval *, void * );
@@ -458,8 +459,8 @@ check_syncprov(
 	 */
 	a.a_desc = slap_schema.si_ad_contextCSN;
 	e.e_attrs = &a;
-	e.e_name = op->o_bd->be_suffix[0];
-	e.e_nname = op->o_bd->be_nsuffix[0];
+	e.e_name = si->si_contextdn;
+	e.e_nname = si->si_contextdn;
 	at[0].an_name = a.a_desc->ad_cname;
 	at[0].an_desc = a.a_desc;
 	BER_BVZERO( &at[1].an_name );
@@ -627,7 +628,7 @@ do_syncrep1(
 				BerVarray csn = NULL;
 				void *ctx = op->o_tmpmemctx;
 
-				op->o_req_ndn = op->o_bd->be_nsuffix[0];
+				op->o_req_ndn = si->si_contextdn;
 				op->o_req_dn = op->o_req_ndn;
 
 				/* try to read stored contextCSN */
@@ -753,7 +754,6 @@ do_syncrep2(
 			err = LDAP_SUCCESS;
 	ber_len_t	len;
 
-	struct berval	*psub;
 	Modifications	*modlist = NULL;
 
 	int				match, m;
@@ -775,8 +775,6 @@ do_syncrep2(
 
 	Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2 %s\n", si->si_ridtxt, 0, 0 );
 
-	psub = &si->si_be->be_nsuffix[0];
-
 	slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie );
 
 	if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
@@ -873,7 +871,7 @@ do_syncrep2(
 				if ( ( rc = syncrepl_message_to_op( si, op, msg ) ) == LDAP_SUCCESS &&
 					syncCookie.ctxcsn )
 				{
-					rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
+					rc = syncrepl_updateCookie( si, op, &syncCookie );
 				} else switch ( rc ) {
 					case LDAP_ALREADY_EXISTS:
 					case LDAP_NO_SUCH_OBJECT:
@@ -893,7 +891,7 @@ do_syncrep2(
 					syncstate, &syncUUID, syncCookie.ctxcsn ) ) == LDAP_SUCCESS &&
 					syncCookie.ctxcsn )
 				{
-					rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
+					rc = syncrepl_updateCookie( si, op, &syncCookie );
 				}
 			}
 			ldap_controls_free( rctrls );
@@ -1013,7 +1011,7 @@ do_syncrep2(
 			}
 			if ( syncCookie.ctxcsn && match < 0 && err == LDAP_SUCCESS )
 			{
-				rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
+				rc = syncrepl_updateCookie( si, op, &syncCookie );
 			}
 			if ( err == LDAP_SUCCESS
 				&& si->si_logstate == SYNCLOG_FALLBACK ) {
@@ -1174,7 +1172,7 @@ do_syncrep2(
 
 					if ( syncCookie.ctxcsn )
 					{
-						rc = syncrepl_updateCookie( si, op, psub, &syncCookie);
+						rc = syncrepl_updateCookie( si, op, &syncCookie);
 					}
 				} 
 
@@ -1330,6 +1328,12 @@ do_syncrepl(
 		} else {
 			si->si_wbe = be;
 		}
+		if ( SLAP_SYNC_SUBENTRY( si->si_wbe )) {
+			build_new_dn( &si->si_contextdn, &si->si_wbe->be_nsuffix[0],
+				(struct berval *)&slap_ldapsync_cn_bv, NULL );
+		} else {
+			si->si_contextdn = si->si_wbe->be_nsuffix[0];
+		}
 	}
 	if ( !si->si_schemachecking )
 		op->o_no_schema_check = 1;
@@ -2957,7 +2961,6 @@ static int
 syncrepl_updateCookie(
 	syncinfo_t *si,
 	Operation *op,
-	struct berval *pdn,
 	struct sync_cookie *syncCookie )
 {
 	Backend *be = op->o_bd;
@@ -3048,8 +3051,8 @@ syncrepl_updateCookie(
 	cb.sc_private = si;
 
 	op->o_callback = &cb;
-	op->o_req_dn = op->o_bd->be_suffix[0];
-	op->o_req_ndn = op->o_bd->be_nsuffix[0];
+	op->o_req_dn = si->si_contextdn;
+	op->o_req_ndn = si->si_contextdn;
 
 	/* update contextCSN */
 	op->o_dont_replicate = 1;
@@ -3057,6 +3060,20 @@ syncrepl_updateCookie(
 	op->orm_modlist = &mod;
 	op->orm_no_opattrs = 1;
 	rc = op->o_bd->be_modify( op, &rs_modify );
+
+	if ( rs_modify.sr_err == LDAP_NO_SUCH_OBJECT &&
+		SLAP_SYNC_SUBENTRY( op->o_bd )) {
+		const char	*text;
+		char txtbuf[SLAP_TEXT_BUFLEN];
+		size_t textlen = sizeof txtbuf;
+		Entry *e = slap_create_context_csn_entry( op->o_bd, NULL );
+		rc = slap_mods2entry( &mod, &e, 0, 1, &text, txtbuf, textlen);
+		op->ora_e = e;
+		rc = op->o_bd->be_add( op, &rs_modify );
+		if ( e == op->ora_e )
+			be_entry_release_w( op, op->ora_e );
+	}
+
 	op->orm_no_opattrs = 0;
 	op->o_dont_replicate = 0;
 
@@ -3695,6 +3712,9 @@ syncinfo_free( syncinfo_t *sie, int free_all )
 		if ( sie->si_logbase.bv_val ) {
 			ch_free( sie->si_logbase.bv_val );
 		}
+		if ( SLAP_SYNC_SUBENTRY( sie->si_be )) {
+			ch_free( sie->si_contextdn.bv_val );
+		}
 		if ( sie->si_attrs ) {
 			int i = 0;
 			while ( sie->si_attrs[i] != NULL ) {