diff --git a/SOURCES/slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch b/SOURCES/slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch
new file mode 100644
index 0000000..eafbedd
--- /dev/null
+++ b/SOURCES/slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch
@@ -0,0 +1,207 @@
+From 2df48b57adb666112cab22e62750dd984fc7450a Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Wed, 23 Dec 2015 14:57:03 +0200
+Subject: [PATCH 05/12] slapi-nis: populate data trees asynchronously after
+ LDAP server startup
+
+Currently slapi-nis design assumes the map cache is populated by
+scanning the original trees on plugin start up. This has few
+consequences:
+   - LDAP server cannot serve LDAP clients until all plugins are
+     initialized
+
+   - slapi-nis cannot ask SSSD to resolve external identities at
+     this point as SSSD will need to talk to the LDAP server which
+     is at this point not listening for connections. SSSD will put
+     whole IPA domain into offline and always will respond
+     with negative result
+
+To solve these issues, schedule tree scan after LDAP server startup.
+The problem here is that it is not possible to reliably detect when
+389-ds starts to listen to the incoming connections. However, it is
+possible to schedule an event into 389-ds event queue that will run
+shortly after start of the event loop. Given that the call back function
+which is registered to be called is called within the event loop thread,
+one can fire off another thread and wait in the thread function some
+time until the LDAP server is ready for connections.
+
+The time interval is something that would depend on a specific
+deployment profile but experiments show that having 5 seconds delay
+should be enough as event queue is created just before starting the
+listeners.
+---
+ src/back-shr.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++---------
+ src/plug-sch.c |   4 +--
+ 2 files changed, 96 insertions(+), 18 deletions(-)
+
+diff --git a/src/back-shr.c b/src/back-shr.c
+index c68640a..36ecc0b 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -664,40 +664,56 @@ backend_shr_get_vattr_sdnlist(struct plugin_state *state,
+ 	return ret;
+ }
+ 
+-/* Scan for the list of configured groups and sets. */
+-void
+-backend_shr_startup(struct plugin_state *state,
+-		    Slapi_PBlock *parent_pb,
+-		    const char *filter)
++struct backend_shr_data_init_cbdata {
++	Slapi_PBlock *parent_pb;
++	struct plugin_state *state;
++	const char *filter;
++};
++
++#define PLUGIN_SCAN_DELAY 5
++
++static void
++backend_shr_data_initialize_thread_cb(void *arg)
+ {
+-	Slapi_PBlock *pb;
++	struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
++	Slapi_PBlock *pb = NULL;
+ 	struct backend_set_config_entry_add_cbdata set_cbdata;
++	int result = 0;
++	if (cbdata == NULL) {
++		return;
++	}
++
++	/* Scan may require consulting SSSD for external identities
++	 * therefore, we need to make sure the scan starts after ns-slapd
++	 * started to serve LDAP clients. There is no a signal for this,
++	 * so we just wait some time. */
++	DS_Sleep(PR_SecondsToInterval(PLUGIN_SCAN_DELAY));
+ 
+-	backend_update_params(parent_pb, state);
++	backend_update_params(cbdata->parent_pb, cbdata->state);
+ 
+ 	slapi_log_error(SLAPI_LOG_PLUGIN,
+-			state->plugin_desc->spd_id,
++			cbdata->state->plugin_desc->spd_id,
+ 			"searching under \"%s\" for configuration\n",
+-			state->plugin_base);
+-	pb = wrap_pblock_new(parent_pb);
++			cbdata->state->plugin_base);
++	pb = wrap_pblock_new(cbdata->parent_pb);
+ 	slapi_search_internal_set_pb(pb,
+-				     state->plugin_base,
++				     cbdata->state->plugin_base,
+ 				     LDAP_SCOPE_ONELEVEL,
+-				     filter,
++				     cbdata->filter,
+ 				     NULL, FALSE,
+ 				     NULL,
+ 				     NULL,
+-				     state->plugin_identity,
++				     cbdata->state->plugin_identity,
+ 				     0);
+ 	if (map_wrlock() != 0) {
+ 		slapi_log_error(SLAPI_LOG_PLUGIN,
+-				state->plugin_desc->spd_id,
++				cbdata->state->plugin_desc->spd_id,
+ 				"failed to search under \"%s\" for "
+ 				"configuration: failed to acquire a lock\n",
+-				state->plugin_base);
++				cbdata->state->plugin_base);
+ 		goto done_with_lock;
+ 	}
+-	set_cbdata.state = state;
++	set_cbdata.state = cbdata->state;
+ 	set_cbdata.pb = pb;
+ 	slapi_search_internal_callback_pb(pb, &set_cbdata,
+ 					  NULL,
+@@ -706,6 +722,68 @@ backend_shr_startup(struct plugin_state *state,
+ 	map_unlock();
+ done_with_lock:
+ 	slapi_pblock_destroy(pb);
++        if (cbdata) {
++		slapi_ch_free((void**)&cbdata);
++        }
++}
++
++static void
++backend_shr_data_initialize_thread(time_t when, void *arg)
++{
++	struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
++	PRThread *thread = NULL;
++
++	/* start data import as a separate thread */
++	thread = PR_CreateThread(PR_USER_THREAD, backend_shr_data_initialize_thread_cb,
++			(void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
++			PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
++	if (thread == NULL) {
++		slapi_log_error(SLAPI_LOG_FATAL,
++				cbdata->state->plugin_desc->spd_id,
++				"unable to create compatibility tree scan thread!\n");
++	} else {
++		slapi_log_error(SLAPI_LOG_FATAL,
++				cbdata->state->plugin_desc->spd_id,
++				"%s tree scan will start in about %d seconds!\n",
++				cbdata->state->plugin_desc->spd_id, PLUGIN_SCAN_DELAY);
++	}
++
++}
++
++/* Scan for the list of configured groups and sets. */
++void
++backend_shr_startup(struct plugin_state *state,
++		    Slapi_PBlock *parent_pb,
++		    const char *filter)
++{
++	struct backend_shr_data_init_cbdata *cbdata = NULL;
++
++	cbdata = (struct backend_shr_data_init_cbdata *) 
++		 slapi_ch_malloc(sizeof(struct backend_shr_data_init_cbdata));
++
++	if (cbdata == NULL) {
++		slapi_log_error(SLAPI_LOG_FATAL,
++				state->plugin_desc->spd_id,
++				"failed to create a task for populating "
++				"compatibility tree\n");
++		return;
++	}
++
++	cbdata->state = state;
++	cbdata->parent_pb = parent_pb;
++	cbdata->filter = filter;
++
++	/* Schedule running a callback that will create a thread */
++	slapi_eq_once(backend_shr_data_initialize_thread,
++		      cbdata, PR_SecondsToInterval(PLUGIN_SCAN_DELAY));
++
++	slapi_log_error(SLAPI_LOG_FATAL,
++			cbdata->state->plugin_desc->spd_id,
++			"scheduled %s tree scan in about %d seconds after the server startup!\n",
++			state->plugin_desc->spd_id, PLUGIN_SCAN_DELAY);
++
++	return;
++
+ }
+ 
+ /* Process a set configuration directory entry.  Pull out the group and set
+diff --git a/src/plug-sch.c b/src/plug-sch.c
+index f132e6d..95a4fd8 100644
+--- a/src/plug-sch.c
++++ b/src/plug-sch.c
+@@ -109,8 +109,6 @@ plugin_startup(Slapi_PBlock *pb)
+ 			state->plugin_base ? "\"" : "",
+ 			state->plugin_base ? state->plugin_base : "NULL",
+ 			state->plugin_base ? "\"" : "");
+-	/* Populate the tree of fake entries. */
+-	backend_startup(pb, state);
+ 	state->pam_lock = wrap_new_rwlock();
+ 	backend_nss_init_context((struct nss_ops_ctx**) &state->nss_context);
+ 	if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
+@@ -123,6 +121,8 @@ plugin_startup(Slapi_PBlock *pb)
+ 	wrap_rwlock_wrlock(state->cached_entries_lock);
+ 	state->cached_entries = PL_NewHashTable(0, PL_HashString, PL_CompareStrings, PL_CompareValues, 0, 0);
+ 	wrap_rwlock_unlock(state->cached_entries_lock);
++	/* Populate the tree of fake entries. */
++	backend_startup(pb, state);
+ 	/* Note that the plugin is ready to go. */
+ 	slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id,
+ 			"plugin startup completed\n");
+-- 
+2.5.0
+
diff --git a/SOURCES/slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch b/SOURCES/slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch
new file mode 100644
index 0000000..efdacae
--- /dev/null
+++ b/SOURCES/slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch
@@ -0,0 +1,84 @@
+From 52beb5e79905712a8aaabf19e52e654fc4648a94 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Fri, 15 Jan 2016 16:16:00 +0200
+Subject: [PATCH 06/12] nss: force lower case for memberUid attribute as per
+ RFC2307
+
+When memberUid attribute is generated, it has to be normalized or
+otherwise searches for members against groups in compat tree will fail.
+slapi-nis already normalizes elements of a search filter that mention
+memberUid attribute values but the original memberUid value should be
+normalized as well.
+---
+ src/back-sch-nss.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/src/back-sch-nss.c b/src/back-sch-nss.c
+index 16d4164..702590c 100644
+--- a/src/back-sch-nss.c
++++ b/src/back-sch-nss.c
+@@ -246,8 +246,8 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd,
+ 		return NULL;
+ 	}
+ 
+-	dn = backend_build_dn("uid", pwd->pw_name, container_sdn);
+-	if (dn == NULL) {
++	name = (char *) slapi_utf8StrToLower((unsigned char *) pwd->pw_name);
++	if (name == NULL) {
+ 		slapi_log_error(SLAPI_LOG_FATAL,
+ 				cbdata->state->plugin_desc->spd_id,
+ 				"error building DN for uid=%s,%s skipping\n",
+@@ -256,12 +256,22 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd,
+ 		return NULL;
+ 	}
+ 
++	dn = backend_build_dn("uid", name, container_sdn);
++	if (dn == NULL) {
++		slapi_log_error(SLAPI_LOG_FATAL,
++				cbdata->state->plugin_desc->spd_id,
++				"error building DN for uid=%s,%s skipping\n",
++				name, container_sdn);
++		slapi_entry_free(entry);
++		return NULL;
++	}
++
+ 	slapi_entry_add_string(entry,
+ 			       "objectClass", "top");
+ 	slapi_entry_add_string(entry,
+ 			       "objectClass", "posixAccount");
+ 	slapi_entry_add_string(entry,
+-			       "uid", pwd->pw_name);
++			       "uid", name);
+ 	slapi_entry_attr_set_uint(entry,
+ 				 "uidNumber", pwd->pw_uid);
+ 	slapi_entry_attr_set_uint(entry,
+@@ -286,6 +296,7 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd,
+ 	}
+ 
+ 	slapi_entry_set_dn(entry, dn);
++	slapi_ch_free_string(&name);
+ 
+ #ifdef HAVE_SSS_NSS_IDMAP
+ 	rc = sss_nss_getsidbyid(pwd->pw_uid, &sid_str, &id_type);
+@@ -520,6 +531,7 @@ backend_make_group_entry_from_nsswitch_group(struct group *grp,
+ 	Slapi_Entry *entry;
+ 	int rc, i;
+ 	char *dn = NULL;
++	char *name = NULL;
+ #ifdef HAVE_SSS_NSS_IDMAP
+ 	enum sss_id_type id_type;
+ 	char *sid_str;
+@@ -551,7 +563,9 @@ backend_make_group_entry_from_nsswitch_group(struct group *grp,
+ 
+ 	if (grp->gr_mem) {
+ 		for (i=0; grp->gr_mem[i]; i++) {
+-			slapi_entry_add_string(entry, "memberUid", grp->gr_mem[i]);
++			name = (char *) slapi_utf8StrToLower((unsigned char*) grp->gr_mem[i]);
++			slapi_entry_add_string(entry, "memberUid", name);
++			slapi_ch_free_string(&name);
+ 		}
+ 	}
+ 
+-- 
+2.5.0
+
diff --git a/SOURCES/slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch b/SOURCES/slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch
new file mode 100644
index 0000000..6ddaa28
--- /dev/null
+++ b/SOURCES/slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch
@@ -0,0 +1,195 @@
+From d1b87904462e890a855ac9d3b68ed02e089450d8 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Wed, 23 Dec 2015 15:04:40 +0200
+Subject: [PATCH 07/12] slapi-nis: add support to resolve external members of
+ IPA groups
+
+FreeIPA allows to include external (non-LDAP) members into POSIX groups.
+To define external members, an attribute ipaExternalMember is set to
+the list of references to external members. Currently both FreeIPA and
+SSSD support only references done with SIDs (Security Identifiers) from
+the forests trusted by FreeIPA.
+
+Resolving external members of FreeIPA groups requires resolving SIDs to
+user and group names. However, since this resolution is already
+implemented by SSSD for the group in question, slapi-nis can use the
+fact that there is non-empty ipaExternalMember attribute's value to
+trigger lookup of the FreeIPA group via SSSD and then copy over
+memberUid attribute value set.
+
+This logic requires that ipaExternalMember attribute value is present in
+the entry to be put into the map cache. Thus, an additional
+configuration is needed for the groups container:
+
+schema-compat-entry-attribute: ipaexternalmember=%deref_r("member","ipaexternalmember")
+
+Note that resolving external members of IPA groups requires to use
+version of slapi-nis that populates the map cache after LDAP server
+startup, as SSSD needs to talk back to the LDAP server in the process of
+resolving external group members and that is not possible at the time
+when slapi-nis plugin starts up as the LDAP server is not yet listenting
+for incoming connections at that point.
+---
+ doc/ipa/sch-ipa.txt |  15 +++++++
+ src/back-sch.c      | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 127 insertions(+)
+
+diff --git a/doc/ipa/sch-ipa.txt b/doc/ipa/sch-ipa.txt
+index 106e6cc..eb6238a 100644
+--- a/doc/ipa/sch-ipa.txt
++++ b/doc/ipa/sch-ipa.txt
+@@ -81,6 +81,21 @@ and groups from trusted domains. No additional configuration is needed.
+ ipa-adtrust-install, however, will not set the minimal numeric id for user or
+ group.
+ 
++Additionally, group area configuration should include following two attributes to
++allow resolving external members of IPA groups:
++
++schema-compat-entry-attribute: ipaexternalmember=%deref_r("member","ipaexternalmember")
++schema-compat-entry-attribute: objectclass=ipaexternalgroup
++
++When 'ipaExternalMember' attribute is present in the group entry generated by
++Schema Compatibility plugin, the plugin will attempt to retrieve the group
++members from SSSD daemon. If group has non-empty list of members, these new
++members will replace the original ones as they will include both IPA and external
++group members.
++
++SSSD greater than 1.13.3 is required to produce correct behavior due to bug
++https://fedorahosted.org/sssd/ticket/2522
++
+ == Authentication of the trusted domains' users ==
+ 
+ When the Schema Compatibility Plugin is configured to expose users from trusted
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 98542c5..04fe667 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -419,6 +419,115 @@ backend_set_operational_attributes(Slapi_Entry *e,
+ 	}
+ }
+ 
++#ifdef USE_NSSWITCH
++#define IPA_ATTR_EXTERNAL_MEMBER "ipaExternalMember"
++#define IPA_ATTR_MEMBERUID "memberUid"
++static void
++backend_set_process_external_members(Slapi_PBlock *pb,
++				   Slapi_Entry *e,
++				   struct plugin_state *state,
++				   struct backend_set_data *data)
++{
++	Slapi_Attr *attr = NULL;
++	Slapi_ValueSet *valueset = NULL;
++	bool_t is_attr_exists, is_group_exists;
++	struct backend_staged_search staged = {0, };
++	struct backend_search_cbdata cbdata = {0, };
++	char *plugin_id = state->plugin_desc->spd_id;
++
++	is_attr_exists = slapi_entry_attr_find(e, IPA_ATTR_EXTERNAL_MEMBER, &attr) == 0;
++
++	if (!is_attr_exists || attr == NULL) {
++		return;
++	}
++
++	/* There are external members in this entry, do group lookup via SSSD
++	 * and update entry's memberUid attribute */
++
++	staged.name = slapi_entry_attr_get_charptr(e, "cn");
++	staged.type = SCH_NSSWITCH_GROUP;
++	staged.search_members = FALSE;
++	staged.is_id = FALSE;
++	staged.is_sid = FALSE;
++	staged.container_sdn = (char*) slapi_sdn_get_dn(data->container_sdn);
++	staged.entries = NULL;
++	staged.count = 0;
++	cbdata.nsswitch_buffer_len = MAX(16384, MAX(sysconf(_SC_GETPW_R_SIZE_MAX), sysconf(_SC_GETGR_R_SIZE_MAX)));
++	cbdata.nsswitch_buffer = malloc(cbdata.nsswitch_buffer_len);
++	cbdata.state = state;
++	cbdata.staged = &staged;
++
++	slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
++			"refreshing group membership for group \"%s\"\n", staged.name);
++
++	do {
++		/* This group must exist because it exists in the original tree
++		 * but as dirsrv was restarted, SSSD might still consider its domain offline. */
++		is_group_exists = backend_retrieve_from_nsswitch(&staged, &cbdata);
++		if (!is_group_exists) {
++			slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
++					"group \"%s\" does not exist because SSSD is offline.",
++					staged.name);
++			if (state->ready_to_serve == 0) {
++				/* Only wait for SSSD when we populate the original set */
++				slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
++						"waiting for SSSD to become online...");
++				DS_Sleep(PR_SecondsToInterval(35));
++			} else {
++				break;
++			}
++		}
++	} while (!is_group_exists);
++
++	if (staged.entries != NULL && staged.entries[0] != NULL) {
++			attr = NULL;
++			if (slapi_entry_attr_find(staged.entries[0], IPA_ATTR_MEMBERUID, &attr) == 0) {
++#if 0
++				/* Debug output of original and updated memberUid values */
++				char **ary1, **ary2;
++				ary1 = slapi_entry_attr_get_charray(e, "memberUid");
++				ary2 = slapi_entry_attr_get_charray(staged.entries[0], "memberUid");
++
++				slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
++						"original group \"%s\":\n", staged.name);
++				for (int i = 0; ary1 && ary1[i] != NULL; ++i) {
++					slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
++							"\t> %s\n", ary1[i]);
++				}
++				slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
++						"new group \"%s\":\n", staged.name);
++				for (int i = 0; ary2 && ary2[i] != NULL; ++i) {
++					slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
++							"\t> %s\n", ary2[i]);
++				}
++				slapi_ch_array_free(ary2);
++				slapi_ch_array_free(ary1);
++#endif
++
++				(void)slapi_attr_get_valueset(attr, &valueset);
++
++				if (slapi_entry_attr_find(e, IPA_ATTR_MEMBERUID, &attr) == 0) {
++					(void) slapi_entry_attr_delete(e, IPA_ATTR_MEMBERUID);
++				}
++				(void) slapi_entry_add_valueset(e, IPA_ATTR_MEMBERUID, valueset);
++				slapi_valueset_free(valueset);
++			} else {
++				slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
++						"group \"%s\" doesn't have memberUid attribute\n", staged.name);
++			}
++			slapi_entry_free(staged.entries[0]);
++	}
++
++	if (staged.entries != NULL) {
++		free(staged.entries);
++	}
++
++	(void)slapi_entry_attr_delete(e, IPA_ATTR_EXTERNAL_MEMBER);
++	free(cbdata.nsswitch_buffer);
++	slapi_ch_free_string(&staged.name);
++}
++#endif
++
+ /* Given a map-entry directory entry, determine a key, a value, and extra data
+  * to be stored in the map cache, and add them to the map cache. */
+ static void
+@@ -613,6 +722,9 @@ backend_set_entry_from(Slapi_PBlock *pb, enum backend_entry_source source,
+ 		slapi_entry_add_string(entry,
+ 				       "objectClass", "extensibleObject");
+ 	}
++#ifdef USE_NSSWITCH
++	backend_set_process_external_members(pb, entry, data->common.state, data);
++#endif
+ 	/* Clean up the entry by doing a round trip through the LDIF parser. */
+ 	ldif = slapi_entry2str(entry, &len);
+ 	slapi_entry_free(entry);
+-- 
+2.5.0
+
diff --git a/SOURCES/slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch b/SOURCES/slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch
new file mode 100644
index 0000000..ec47383
--- /dev/null
+++ b/SOURCES/slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch
@@ -0,0 +1,150 @@
+From 594fcb2320033d01cfe2b8121793d431d1017987 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Fri, 15 Jan 2016 16:39:12 +0200
+Subject: [PATCH 08/12] slapi-nis: process requests only when initialization
+ completed
+
+Initializing map cache may take time. Skip slapi-nis lookups untli
+the map cache is ready.
+---
+ src/back-sch.c | 23 ++++++++++++++++++++++-
+ src/back-shr.c | 20 ++++++++++++++++++++
+ src/plugin.h   |  1 +
+ 3 files changed, 43 insertions(+), 1 deletion(-)
+
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 04fe667..871734c 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -1609,7 +1609,7 @@ backend_search_cb(Slapi_PBlock *pb)
+ {
+ 	struct backend_search_cbdata cbdata;
+ 	struct backend_staged_search *staged, *next;
+-	int i;
++	int i, isroot;
+ 
+ 	if (wrap_get_call_level() > 0) {
+ 		return 0;
+@@ -1621,6 +1621,19 @@ backend_search_cb(Slapi_PBlock *pb)
+ 		/* The plugin was not actually started. */
+ 		return 0;
+ 	}
++	if (cbdata.state->ready_to_serve == 0) {
++		/* No data to serve yet */
++		return 0;
++	}
++
++	slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
++
++	if (slapi_op_internal(pb) || (slapi_is_ldapi_conn(pb) && isroot)) {
++		/* The plugin should not engage in internal searches of other
++		 * plugins or ldapi+cn=DM */
++		return 0;
++	}
++
+ 	slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &cbdata.target);
+ 	slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &cbdata.scope);
+ 	slapi_pblock_get(pb, SLAPI_SEARCH_SIZELIMIT, &cbdata.sizelimit);
+@@ -2018,6 +2031,10 @@ backend_write_cb(Slapi_PBlock *pb, struct plugin_state *state)
+ 	if (wrap_get_call_level() > 0) {
+ 		return 0;
+ 	}
++	if (state->ready_to_serve == 0) {
++		/* No data to serve yet */
++		return 0;
++	}
+ 
+ 	wrap_inc_call_level();
+ 	if (map_rdlock() == 0) {
+@@ -2125,6 +2142,10 @@ backend_bind_cb(Slapi_PBlock *pb)
+ 	}
+ 
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
++	if (state->ready_to_serve == 0) {
++		/* No data to serve yet */
++		return 0;
++	}
+ 	/* The code below handles three separate facts:
+ 	 * 1. For NSSWITCH-discovered users PAM is responsible for authentication.
+ 	 *    We want to run PAM auth without any slapi-nis lock taken to avoid
+diff --git a/src/back-shr.c b/src/back-shr.c
+index 36ecc0b..131365d 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -725,6 +725,8 @@ done_with_lock:
+         if (cbdata) {
+ 		slapi_ch_free((void**)&cbdata);
+         }
++
++	PR_AtomicSet(&state->ready_to_serve, 1);
+ }
+ 
+ static void
+@@ -769,6 +771,7 @@ backend_shr_startup(struct plugin_state *state,
+ 		return;
+ 	}
+ 
++	PR_AtomicSet(&state->ready_to_serve, 0);
+ 	cbdata->state = state;
+ 	cbdata->parent_pb = parent_pb;
+ 	cbdata->filter = filter;
+@@ -1798,6 +1801,11 @@ backend_shr_add_cb(Slapi_PBlock *pb)
+ 		/* The plugin was not actually started. */
+ 		return 0;
+ 	}
++	if (cbdata.state->ready_to_serve == 0) {
++		/* No data yet, ignore */
++		return 0;
++	}
++
+ 	slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e);
+ 	slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn);
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &rc);
+@@ -2208,6 +2216,10 @@ backend_shr_modify_cb(Slapi_PBlock *pb)
+ 		/* The plugin was not actually started. */
+ 		return 0;
+ 	}
++	if (cbdata.state->ready_to_serve == 0) {
++		/* No data yet, ignore */
++		return 0;
++	}
+ 	slapi_pblock_get(pb, SLAPI_MODIFY_TARGET, &dn);
+ 	slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &cbdata.mods);
+ 	slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e_pre);
+@@ -2410,6 +2422,10 @@ backend_shr_modrdn_cb(Slapi_PBlock *pb)
+ 		/* The plugin was not actually started. */
+ 		return 0;
+ 	}
++	if (cbdata.state->ready_to_serve == 0) {
++		/* No data yet, ignore */
++		return 0;
++	}
+ 	slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e_pre);
+ 	slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e_post);
+ 
+@@ -2549,6 +2565,10 @@ backend_shr_delete_cb(Slapi_PBlock *pb)
+ 		/* The plugin was not actually started. */
+ 		return 0;
+ 	}
++	if (cbdata.state->ready_to_serve == 0) {
++		/* No data yet, ignore */
++		return 0;
++	}
+ 	slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e);
+ 	slapi_pblock_get(pb, SLAPI_DELETE_TARGET, &dn);
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &rc);
+diff --git a/src/plugin.h b/src/plugin.h
+index 429e291..7a89ac7 100644
+--- a/src/plugin.h
++++ b/src/plugin.h
+@@ -33,6 +33,7 @@ struct plugin_state {
+ 	Slapi_ComponentId *plugin_identity;
+ 	Slapi_PluginDesc *plugin_desc;
+ 	unsigned int use_be_txns: 1;
++	PRInt32 ready_to_serve;
+ 
+ 	/* NIS-specific data. */
+ 	struct wrapped_thread *tid;
+-- 
+2.5.0
+
diff --git a/SOURCES/slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch b/SOURCES/slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch
new file mode 100644
index 0000000..85544b9
--- /dev/null
+++ b/SOURCES/slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch
@@ -0,0 +1,105 @@
+From 3aaf4941fc17df388c43776eda6d41f62017a143 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Fri, 15 Jan 2016 17:17:23 +0200
+Subject: [PATCH 09/12] slapi-nis: serialize map cache initialization
+
+Serialize process of initiliazing map cache to avoid locking the
+directory server backends.
+---
+ src/back-shr.c | 55 +++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 18 deletions(-)
+
+diff --git a/src/back-shr.c b/src/back-shr.c
+index 131365d..0157582 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -678,49 +678,68 @@ backend_shr_data_initialize_thread_cb(void *arg)
+ 	struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
+ 	Slapi_PBlock *pb = NULL;
+ 	struct backend_set_config_entry_add_cbdata set_cbdata;
+-	int result = 0;
++	int result = 0, i = 0;
++	Slapi_Entry **entries = NULL;
++	struct plugin_state *state = NULL;
++
+ 	if (cbdata == NULL) {
+ 		return;
+ 	}
+ 
++	state = cbdata->state;
++
+ 	/* Scan may require consulting SSSD for external identities
+ 	 * therefore, we need to make sure the scan starts after ns-slapd
+ 	 * started to serve LDAP clients. There is no a signal for this,
+ 	 * so we just wait some time. */
+ 	DS_Sleep(PR_SecondsToInterval(PLUGIN_SCAN_DELAY));
+ 
+-	backend_update_params(cbdata->parent_pb, cbdata->state);
++	backend_update_params(cbdata->parent_pb, state);
+ 
+ 	slapi_log_error(SLAPI_LOG_PLUGIN,
+-			cbdata->state->plugin_desc->spd_id,
++			state->plugin_desc->spd_id,
+ 			"searching under \"%s\" for configuration\n",
+-			cbdata->state->plugin_base);
++			state->plugin_base);
+ 	pb = wrap_pblock_new(cbdata->parent_pb);
+ 	slapi_search_internal_set_pb(pb,
+-				     cbdata->state->plugin_base,
++				     state->plugin_base,
+ 				     LDAP_SCOPE_ONELEVEL,
+ 				     cbdata->filter,
+ 				     NULL, FALSE,
+ 				     NULL,
+ 				     NULL,
+-				     cbdata->state->plugin_identity,
++				     state->plugin_identity,
+ 				     0);
+-	if (map_wrlock() != 0) {
+-		slapi_log_error(SLAPI_LOG_PLUGIN,
+-				cbdata->state->plugin_desc->spd_id,
++	wrap_inc_call_level();
++	set_cbdata.state = state;
++	set_cbdata.pb = pb;
++
++	/* Do a search and collect found entries to avoid locking the backends */
++	if (slapi_search_internal_pb(pb) == 0) {
++		if (map_wrlock() != 0) {
++			slapi_log_error(SLAPI_LOG_PLUGIN,
++				state->plugin_desc->spd_id,
+ 				"failed to search under \"%s\" for "
+ 				"configuration: failed to acquire a lock\n",
+-				cbdata->state->plugin_base);
+-		goto done_with_lock;
++				state->plugin_base);
++			goto done_with_lock;
++		}
++		slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
++		if (result == 0) {
++			slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
++			for (i = 0; entries[i] != NULL; i++) {
++				backend_set_config_entry_add_cb(entries[i], &set_cbdata);
++			}
++		}
++		map_unlock();
++		slapi_free_search_results_internal(pb);
+ 	}
+-	set_cbdata.state = cbdata->state;
+-	set_cbdata.pb = pb;
+-	slapi_search_internal_callback_pb(pb, &set_cbdata,
+-					  NULL,
+-					  backend_set_config_entry_add_cb,
+-					  NULL);
+-	map_unlock();
++	slapi_log_error(SLAPI_LOG_FATAL,
++			state->plugin_desc->spd_id,
++			"Finished plugin initialization.\n");
++
+ done_with_lock:
++	wrap_dec_call_level();
+ 	slapi_pblock_destroy(pb);
+         if (cbdata) {
+ 		slapi_ch_free((void**)&cbdata);
+-- 
+2.5.0
+
diff --git a/SOURCES/slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch b/SOURCES/slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch
new file mode 100644
index 0000000..0c125c3
--- /dev/null
+++ b/SOURCES/slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch
@@ -0,0 +1,80 @@
+From 5eaad9c4c218d9a59f6930a29f5bee54235c4fab Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Tue, 19 Jan 2016 07:37:46 +0200
+Subject: [PATCH 10/12] nis: lock out accounts if nsAccountLock is TRUE
+
+Add a rule that adds two bang characters in front of the password.
+
+When the password algorithm is defined as CRYPT and NIS is used to
+authenticate users on other systems, there is no way to disable or lock
+accounts. Traditional convention has been to put two bang (exclamation)
+characters in front of the password, creating an impossible password
+hash. This effectively locks the user account, preventing
+authentication.
+
+All UNIX systems agree that for encrypted passwords presence of a
+character which cannot be part of CRYPT password scheme renders
+impossible to login to system with such password. However, not all
+systems have meaning of locked accounts and even how these locked
+accounts express themselves.
+
+There is certain controversy in what could be used to indicate locked
+accounts:
+ - GNU/Linux systems expect '!' as first character of the password field
+ - FreeBSD expects '*LOCKED*' string at start of the password field
+ - Various Solaris versions expect '*LOCK*' string at start of the
+   password field
+ - NetBSD has no meaning of locked passwords via content of password field
+
+Given that it is impossible to serve NIS maps with encrypted passwords
+in a different way to different clients, standardize on '!!' scheme as
+traditional among UNIX administrators.
+
+Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1298478
+---
+ src/defs-nis.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/src/defs-nis.c b/src/defs-nis.c
+index 3d2b9e9..ad0e7dc 100644
+--- a/src/defs-nis.c
++++ b/src/defs-nis.c
+@@ -52,17 +52,17 @@ static struct configuration {
+ 	{"passwd.byname", config_exact, FALSE, NULL,
+ 	 "(objectClass=posixAccount)",
+ 	 "%{uid}", NULL,
+-	 "%{uid}:%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL,
++	 "%{uid}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL,
+ 	 ":\r\n"},
+ 	{"passwd.byuid", config_exact, FALSE, NULL,
+ 	 "(objectClass=posixAccount)",
+ 	 "%{uidNumber}", NULL,
+-	 "%{uid}:%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL,
++	 "%{uid}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL,
+ 	 ":\r\n"},
+ 	{"shadow.byname", config_exact, TRUE, NULL,
+ 	 "(objectClass=shadowAccount)",
+ 	 "%{uid}", NULL,
+-	 "%{uid}:%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{shadowLastChange:-}:%{shadowMin:-}:%{shadowMax:-}:%{shadowWarning:-}:%{shadowInactive:-}:%{shadowExpire:-}:%{shadowFlag:-}", NULL,
++	 "%{uid}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{shadowLastChange:-}:%{shadowMin:-}:%{shadowMax:-}:%{shadowWarning:-}:%{shadowInactive:-}:%{shadowExpire:-}:%{shadowFlag:-}", NULL,
+ 	 ":\r\n"},
+ 	{"passwd.adjunct.byname", config_exact, TRUE, NULL,
+ 	 "(objectClass=shadowAccount)",
+@@ -72,12 +72,12 @@ static struct configuration {
+ 	{"group.byname", config_exact, FALSE, NULL,
+ 	 "(objectClass=posixGroup)",
+ 	 "%{cn}", NULL,
+-	 "%{cn}:%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL,
++	 "%{cn}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL,
+ 	 ":,\r\n"},
+ 	{"group.bygid", config_exact, FALSE, NULL,
+ 	 "(objectClass=posixGroup)",
+ 	 "%{gidNumber}", NULL,
+-	 "%{cn}:%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL,
++	 "%{cn}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL,
+ 	 ":,\r\n"},
+ 	{"netgroup", config_exact, FALSE, NULL,
+ 	 "(objectClass=nisNetgroup)",
+-- 
+2.5.0
+
diff --git a/SOURCES/slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch b/SOURCES/slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch
new file mode 100644
index 0000000..302beba
--- /dev/null
+++ b/SOURCES/slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch
@@ -0,0 +1,117 @@
+From 00468e8eebd455ab4e41d4d86772fb5f8a745d0a Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Thu, 21 Jan 2016 19:16:30 +0200
+Subject: [PATCH 11/12] idviews: bind with original DN if ID view does not
+ override uid attribute
+
+With ID Views in FreeIPA one can override different kinds of attributes,
+including the uid. When uid attribute is overriden, LDAP BINDs with
+DNs using new (overridden) uid are properly modified to reference the
+original (non-overridden) object.
+
+However, when uid attribute is not overridden, slapi-nis did mistakenly
+avoided to build a reference to the original object without ID view.
+This resulted in inability to do LDAP BIND as overriden DN with original
+uid attribute.
+
+Fix the issue by always processing a DN after removing ID view reference
+from it, whether RDN value (uid) was replaced or not.
+
+Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1301300
+---
+ src/back-sch-idview.c |  4 ++--
+ src/back-sch.c        | 24 ++++++++++++------------
+ 2 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/src/back-sch-idview.c b/src/back-sch-idview.c
+index 8ffab91..8842906 100644
+--- a/src/back-sch-idview.c
++++ b/src/back-sch-idview.c
+@@ -311,7 +311,7 @@ idview_replace_bval_by_override(const char *bval_usage, const char *attr_name,
+ 	}
+ 
+ 	attr_val = slapi_value_new_berval(bval);
+-	slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id,
++	slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
+ 			"Searching for an override of the %s %s with %s=%*s from the overrides\n.",
+ 			bval_usage, attr_name, attr_name, (int) bval->bv_len, bval->bv_val);
+ 
+@@ -347,7 +347,7 @@ idview_replace_bval_by_override(const char *bval_usage, const char *attr_name,
+ 					slapi_ber_bvdone(bval);
+ 					slapi_ber_bvcpy(bval, slapi_value_get_berval(anchor_val));
+ 					anchor_override_found = TRUE;
+-					slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id,
++					slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
+ 							"Overriding the %s %s with %s=%*s from the override %s\n.",
+ 							bval_usage, attr_name, IPA_IDVIEWS_ATTR_ANCHORUUID,
+ 							(int) bval->bv_len, bval->bv_val,
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 871734c..9a0e96b 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -465,13 +465,13 @@ backend_set_process_external_members(Slapi_PBlock *pb,
+ 		 * but as dirsrv was restarted, SSSD might still consider its domain offline. */
+ 		is_group_exists = backend_retrieve_from_nsswitch(&staged, &cbdata);
+ 		if (!is_group_exists) {
+-			slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
+-					"group \"%s\" does not exist because SSSD is offline.",
++			slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
++					"group \"%s\" does not exist because SSSD is offline.\n",
+ 					staged.name);
+ 			if (state->ready_to_serve == 0) {
+ 				/* Only wait for SSSD when we populate the original set */
+-				slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
+-						"waiting for SSSD to become online...");
++				slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
++						"waiting for SSSD to become online...\n");
+ 				DS_Sleep(PR_SecondsToInterval(35));
+ 			} else {
+ 				break;
+@@ -1609,15 +1609,15 @@ backend_search_cb(Slapi_PBlock *pb)
+ {
+ 	struct backend_search_cbdata cbdata;
+ 	struct backend_staged_search *staged, *next;
+-	int i, isroot;
++	int i, isroot, ret;
+ 
+ 	if (wrap_get_call_level() > 0) {
+ 		return 0;
+ 	}
+ 	memset(&cbdata, 0, sizeof(cbdata));
+ 	cbdata.pb = pb;
+-	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
+-	if (cbdata.state->plugin_base == NULL) {
++	ret = slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
++	if ((ret == -1) || (cbdata.state->plugin_base == NULL)) {
+ 		/* The plugin was not actually started. */
+ 		return 0;
+ 	}
+@@ -1626,9 +1626,9 @@ backend_search_cb(Slapi_PBlock *pb)
+ 		return 0;
+ 	}
+ 
+-	slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
++	ret = slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
+ 
+-	if (slapi_op_internal(pb) || (slapi_is_ldapi_conn(pb) && isroot)) {
++	if ((ret == -1) || (slapi_op_internal(pb) || (slapi_is_ldapi_conn(pb) && isroot))) {
+ 		/* The plugin should not engage in internal searches of other
+ 		 * plugins or ldapi+cn=DM */
+ 		return 0;
+@@ -1959,10 +1959,10 @@ backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char **
+ 					if (res == 1) {
+ 						slapi_rdn_remove_index(rdn, 1);
+ 						slapi_rdn_add(rdn, "uid", bval.bv_val);
+-						slapi_sdn_free(&cbdata.target_dn);
+-						cbdata.target_dn = slapi_sdn_set_rdn(scbdata.target_dn, rdn);
+-						map_data_foreach_map(cbdata.state, NULL, backend_locate_cb, &cbdata);
+ 					}
++					slapi_sdn_free(&cbdata.target_dn);
++					cbdata.target_dn = slapi_sdn_set_rdn(scbdata.target_dn, rdn);
++					map_data_foreach_map(cbdata.state, NULL, backend_locate_cb, &cbdata);
+ 					slapi_ber_bvdone(&bval);
+ 					slapi_rdn_free(&rdn);
+ 					idview_free_overrides(&scbdata);
+-- 
+2.5.0
+
diff --git a/SOURCES/slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch b/SOURCES/slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch
new file mode 100644
index 0000000..2b5f6fc
--- /dev/null
+++ b/SOURCES/slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch
@@ -0,0 +1,145 @@
+From 43ea9a5c6cf7f2022f1e586bb4514564fd7826cb Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Tue, 26 Apr 2016 12:44:56 +0300
+Subject: [PATCH 1/4] wrap: add wrapped mutex support
+
+---
+ src/wrap.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/wrap.h |  6 +++++
+ 2 files changed, 96 insertions(+)
+
+diff --git a/src/wrap.c b/src/wrap.c
+index c89638f..f8056a4 100644
+--- a/src/wrap.c
++++ b/src/wrap.c
+@@ -79,6 +79,18 @@ struct wrapped_rwlock {
+ #endif
+ };
+ 
++struct wrapped_mutex {
++#if defined(USE_SLAPI_LOCKS)
++	Slapi_Mutex *mutex;
++#elif defined(USE_PTHREAD_LOCKS)
++	pthread_mutex_t mutex;
++#elif defined(USE_NSPR_LOCKS)
++	PRLock *mutex;
++#else
++#error "Unknown thread-safe locking model!"
++#endif
++};
++
+ #ifdef USE_NSPR_THREADS
+ static void
+ wrap_pthread_starter(void *p)
+@@ -169,6 +181,84 @@ wrap_thread_stopfd(struct wrapped_thread *t)
+ 	return ret;
+ }
+ 
++struct wrapped_mutex *
++wrap_new_mutex(void)
++{
++	struct wrapped_mutex *mutex;
++	mutex = malloc(sizeof(*mutex));
++	if (mutex == NULL) {
++		return NULL;
++	}
++#ifdef USE_SLAPI_LOCKS
++	mutex->mutex = slapi_new_mutex();
++	if (mutex->mutex == NULL) {
++		free(mutex);
++		return NULL;
++	}
++#endif
++#ifdef USE_PTHREAD_LOCKS
++	if (pthread_mutex_init(&mutex->mutex, NULL) != 0) {
++		free(mutex);
++		return NULL;
++	}
++#endif
++#ifdef USE_NSPR_LOCKS
++	mutex->mutex = PR_NewLock();
++	if (mutex->mutex == NULL) {
++		free(mutex);
++		return NULL;
++	}
++#endif
++	return mutex;
++}
++
++void
++wrap_free_mutex(struct wrapped_mutex *mutex)
++{
++#ifdef USE_SLAPI_LOCKS
++	slapi_destroy_mutex(mutex->mutex);
++#endif
++#ifdef USE_PTHREAD_LOCKS
++	pthread_mutex_destroy(&mutex->mutex);
++#endif
++#ifdef USE_NSPR_LOCKS
++	PR_DestroyLock(mutex->mutex);
++#endif
++	free(mutex);
++}
++
++int
++wrap_mutex_lock(struct wrapped_mutex *mutex)
++{
++#ifdef USE_SLAPI_LOCKS
++	slapi_lock_mutex(mutex->mutex);
++        return 0;
++#endif
++#ifdef USE_PTHREAD_LOCKS
++	return pthread_mutex_lock(&mutex->mutex);
++#endif
++#ifdef USE_NSPR_LOCKS
++	PR_Lock(mutex->mutex);
++	return 0;
++#endif
++}
++
++int
++wrap_mutex_unlock(struct wrapped_mutex *mutex)
++{
++#ifdef USE_SLAPI_LOCKS
++	return slapi_unlock_mutex(mutex->mutex);
++#endif
++#ifdef USE_PTHREAD_LOCKS
++	return pthread_mutex_unlock(&mutex->mutex);
++#endif
++#ifdef USE_NSPR_LOCKS
++	PR_Unlock(mutex->mutex);
++	return 0;
++#endif
++}
++
++
+ struct wrapped_rwlock *
+ wrap_new_rwlock(void)
+ {
+diff --git a/src/wrap.h b/src/wrap.h
+index 71bd326..2b797f7 100644
+--- a/src/wrap.h
++++ b/src/wrap.h
+@@ -23,6 +23,7 @@
+ #define wrap_h
+ 
+ struct wrapped_thread;
++struct wrapped_mutex;
+ struct wrapped_rwlock;
+ 
+ struct wrapped_thread * wrap_start_thread(void * (*fn)(struct wrapped_thread *),
+@@ -31,6 +32,11 @@ void *wrap_stop_thread(struct wrapped_thread *t);
+ void *wrap_thread_arg(struct wrapped_thread *t);
+ int wrap_thread_stopfd(struct wrapped_thread *t);
+ 
++struct wrapped_mutex *wrap_new_mutex(void);
++void wrap_free_mutex(struct wrapped_mutex *mutex);
++int wrap_mutex_lock(struct wrapped_mutex *mutex);
++int wrap_mutex_unlock(struct wrapped_mutex *mutex);
++
+ struct wrapped_rwlock *wrap_new_rwlock(void);
+ void wrap_free_rwlock(struct wrapped_rwlock *rwlock);
+ int wrap_rwlock_rdlock(struct wrapped_rwlock *rwlock);
+-- 
+2.7.4
+
diff --git a/SOURCES/slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch b/SOURCES/slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch
new file mode 100644
index 0000000..22550e0
--- /dev/null
+++ b/SOURCES/slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch
@@ -0,0 +1,268 @@
+From c5e89132f2ee017aa026f7b8009a2976b627fa3a Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Tue, 26 Apr 2016 13:00:44 +0300
+Subject: [PATCH 2/4] backend: support backend shutdown for priming thread
+ cancellation
+
+Launching a separate thread to populate map cache has a side effect that
+the thread could be scheduled to execute over a shutdown time. If LDAP server
+received the request to shutdown, we need to stop processing the
+original source and shut the priming thread.
+
+Resolves: rhbz#1327197
+---
+ src/back-shr.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++----------
+ src/back-shr.h |   1 +
+ src/backend.h  |   1 +
+ src/plugin.h   |   3 ++
+ 4 files changed, 92 insertions(+), 17 deletions(-)
+
+diff --git a/src/back-shr.c b/src/back-shr.c
+index 0157582..7842e05 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -665,25 +665,34 @@ backend_shr_get_vattr_sdnlist(struct plugin_state *state,
+ }
+ 
+ struct backend_shr_data_init_cbdata {
+-	Slapi_PBlock *parent_pb;
+ 	struct plugin_state *state;
+ 	const char *filter;
+ };
+ 
+ #define PLUGIN_SCAN_DELAY 5
+ 
+-static void
+-backend_shr_data_initialize_thread_cb(void *arg)
++static void *
++backend_shr_data_initialize_thread_cb(struct wrapped_thread *t)
+ {
+-	struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
++	struct backend_shr_data_init_cbdata *cbdata = wrap_thread_arg(t);
+ 	Slapi_PBlock *pb = NULL;
+ 	struct backend_set_config_entry_add_cbdata set_cbdata;
+ 	int result = 0, i = 0;
+ 	Slapi_Entry **entries = NULL;
+ 	struct plugin_state *state = NULL;
+ 
++	/* We have to be cautious here as the thread can be executed after
++	 * the plugin received a shutdown request, thus a number of checks here. */
++	if (slapi_is_shutting_down()) {
++		return NULL;
++	}
++
+ 	if (cbdata == NULL) {
+-		return;
++		return NULL;
++	}
++
++	if ((cbdata->state == NULL) || (cbdata->state->plugin_base == NULL)) {
++		return NULL;
+ 	}
+ 
+ 	state = cbdata->state;
+@@ -694,13 +703,23 @@ backend_shr_data_initialize_thread_cb(void *arg)
+ 	 * so we just wait some time. */
+ 	DS_Sleep(PR_SecondsToInterval(PLUGIN_SCAN_DELAY));
+ 
+-	backend_update_params(cbdata->parent_pb, state);
++	if (slapi_is_shutting_down()) {
++		return NULL;
++	}
++
++	if (state->plugin_base == NULL) {
++		return NULL;
++	}
++
++	pb = wrap_pblock_new(NULL);
++	backend_update_params(pb, state);
++	slapi_pblock_destroy(pb);
+ 
+ 	slapi_log_error(SLAPI_LOG_PLUGIN,
+ 			state->plugin_desc->spd_id,
+ 			"searching under \"%s\" for configuration\n",
+ 			state->plugin_base);
+-	pb = wrap_pblock_new(cbdata->parent_pb);
++	pb = wrap_pblock_new(NULL);
+ 	slapi_search_internal_set_pb(pb,
+ 				     state->plugin_base,
+ 				     LDAP_SCOPE_ONELEVEL,
+@@ -717,10 +736,10 @@ backend_shr_data_initialize_thread_cb(void *arg)
+ 	/* Do a search and collect found entries to avoid locking the backends */
+ 	if (slapi_search_internal_pb(pb) == 0) {
+ 		if (map_wrlock() != 0) {
+-			slapi_log_error(SLAPI_LOG_PLUGIN,
++			slapi_log_error(SLAPI_LOG_FATAL,
+ 				state->plugin_desc->spd_id,
+ 				"failed to search under \"%s\" for "
+-				"configuration: failed to acquire a lock\n",
++				"configuration: failed to acquire a write lock to a map\n",
+ 				state->plugin_base);
+ 			goto done_with_lock;
+ 		}
+@@ -728,6 +747,11 @@ backend_shr_data_initialize_thread_cb(void *arg)
+ 		if (result == 0) {
+ 			slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ 			for (i = 0; entries[i] != NULL; i++) {
++				/* We may be scheduled to run over shutdown time, exit early */
++				if (slapi_is_shutting_down()) {
++					map_unlock();
++					goto done_with_lock;
++				}
+ 				backend_set_config_entry_add_cb(entries[i], &set_cbdata);
+ 			}
+ 		}
+@@ -746,6 +770,7 @@ done_with_lock:
+         }
+ 
+ 	PR_AtomicSet(&state->ready_to_serve, 1);
++        return NULL;
+ }
+ 
+ static void
+@@ -754,11 +779,28 @@ backend_shr_data_initialize_thread(time_t when, void *arg)
+ 	struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
+ 	PRThread *thread = NULL;
+ 
+-	/* start data import as a separate thread */
+-	thread = PR_CreateThread(PR_USER_THREAD, backend_shr_data_initialize_thread_cb,
+-			(void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+-			PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+-	if (thread == NULL) {
++	if (slapi_is_shutting_down()) {
++		return;
++	}
++
++        if (cbdata->state->priming_mutex == NULL) {
++            /* This mutex is allocated at plugin startup
++             * Without this mutex we can not enforce that shutdown wait for priming completion
++             * This is better to skip the priming
++             */
++            slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id, "priming_mutex not initialized. Priming fails\n");
++            return;
++        }
++        wrap_mutex_lock(cbdata->state->priming_mutex);
++
++        if (!cbdata->state->start_priming_thread) {
++            slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
++                "Likely a shutdown occurred before we started \n");
++            goto done;
++        }
++
++        cbdata->state->priming_tid = wrap_start_thread(&backend_shr_data_initialize_thread_cb, arg);
++        if (cbdata->state->priming_tid == NULL) {
+ 		slapi_log_error(SLAPI_LOG_FATAL,
+ 				cbdata->state->plugin_desc->spd_id,
+ 				"unable to create compatibility tree scan thread!\n");
+@@ -769,6 +811,8 @@ backend_shr_data_initialize_thread(time_t when, void *arg)
+ 				cbdata->state->plugin_desc->spd_id, PLUGIN_SCAN_DELAY);
+ 	}
+ 
++done:
++        wrap_mutex_unlock(cbdata->state->priming_mutex);
+ }
+ 
+ /* Scan for the list of configured groups and sets. */
+@@ -779,6 +823,14 @@ backend_shr_startup(struct plugin_state *state,
+ {
+ 	struct backend_shr_data_init_cbdata *cbdata = NULL;
+ 
++	if (slapi_is_shutting_down()) {
++		slapi_log_error(SLAPI_LOG_FATAL,
++				state->plugin_desc->spd_id,
++				"task for populating compatibility tree will "
++				"not be created due to upcoming server shutdown\n");
++		return;
++	}
++
+ 	cbdata = (struct backend_shr_data_init_cbdata *) 
+ 		 slapi_ch_malloc(sizeof(struct backend_shr_data_init_cbdata));
+ 
+@@ -792,10 +844,10 @@ backend_shr_startup(struct plugin_state *state,
+ 
+ 	PR_AtomicSet(&state->ready_to_serve, 0);
+ 	cbdata->state = state;
+-	cbdata->parent_pb = parent_pb;
+ 	cbdata->filter = filter;
+ 
+-	/* Schedule running a callback that will create a thread */
++	/* Schedule running a callback that will create a thread
++	 * but make sure it is called a first thing when event loop is created */
+ 	slapi_eq_once(backend_shr_data_initialize_thread,
+ 		      cbdata, PR_SecondsToInterval(PLUGIN_SCAN_DELAY));
+ 
+@@ -808,6 +860,24 @@ backend_shr_startup(struct plugin_state *state,
+ 
+ }
+ 
++void
++backend_shr_shutdown(struct plugin_state *state)
++{
++    /* Make sure the priming thread is stopped or will not start
++     * Note: priming_mutex will not be freed because the priming thread
++     * may access it independently of the server/plugin shutdown
++     */
++    wrap_mutex_lock(state->priming_mutex);
++    state->start_priming_thread = 0; /* prevent spawing of priming thread */
++    if (state->priming_tid == NULL) {
++        /* priming thread has not yet started or failed to start */
++        slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++                "At shutdown, priming thread not yet started or failed to start\n");
++    } else {
++        wrap_stop_thread(state->priming_tid);
++    }
++    wrap_mutex_unlock(state->priming_mutex);
++}
+ /* Process a set configuration directory entry.  Pull out the group and set
+  * names which are specified in the entry and delete each in turn. */
+ int
+@@ -2336,7 +2406,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb)
+ 		backend_set_config_entry_add_cb(cbdata.e_post, &set_cbdata);
+ 	}
+ 	/* Lastly, if the entry is our own entry, re-read parameters. */
+-	sdn = slapi_sdn_new_dn_byref(cbdata.state->plugin_base);
++	sdn = slapi_sdn_new_dn_byval(cbdata.state->plugin_base);
+ 	if (sdn != NULL) {
+ 		if ((strcmp(slapi_entry_get_ndn(cbdata.e_pre),
+ 			    slapi_sdn_get_ndn(sdn)) == 0) ||
+diff --git a/src/back-shr.h b/src/back-shr.h
+index 44c25fe..2caea5d 100644
+--- a/src/back-shr.h
++++ b/src/back-shr.h
+@@ -39,6 +39,7 @@ void backend_shr_free_sdnlist(const Slapi_DN **sdnlist);
+ 
+ void backend_shr_startup(struct plugin_state *state,
+ 			 Slapi_PBlock *pb, const char *set_filter);
++void backend_shr_shutdown(struct plugin_state *state);
+ int backend_shr_betxn_postop_init(Slapi_PBlock *pb,
+ 				  struct plugin_state *state);
+ int backend_shr_postop_init(Slapi_PBlock *pb, struct plugin_state *state);
+diff --git a/src/backend.h b/src/backend.h
+index 7974aae..4608d2d 100644
+--- a/src/backend.h
++++ b/src/backend.h
+@@ -58,6 +58,7 @@ struct backend_shr_set_data {
+ 
+ /* Startup/initialization functions called through the map. */
+ void backend_startup(struct slapi_pblock *pb, struct plugin_state *state);
++void backend_shutdown(struct plugin_state *state);
+ int backend_init_preop(struct slapi_pblock *pb, struct plugin_state *state);
+ int backend_init_betxn_preop(struct slapi_pblock *pb,
+ 			     struct plugin_state *state);
+diff --git a/src/plugin.h b/src/plugin.h
+index 7a89ac7..56d672f 100644
+--- a/src/plugin.h
++++ b/src/plugin.h
+@@ -34,6 +34,9 @@ struct plugin_state {
+ 	Slapi_PluginDesc *plugin_desc;
+ 	unsigned int use_be_txns: 1;
+ 	PRInt32 ready_to_serve;
++        struct wrapped_mutex *priming_mutex;
++        unsigned int start_priming_thread: 1;   /* flag to allow spawning of the priming thread */
++        struct wrapped_thread *priming_tid; /* priming thread pid. use to join */
+ 
+ 	/* NIS-specific data. */
+ 	struct wrapped_thread *tid;
+-- 
+2.7.4
+
diff --git a/SOURCES/slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch b/SOURCES/slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch
new file mode 100644
index 0000000..f3122b8
--- /dev/null
+++ b/SOURCES/slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch
@@ -0,0 +1,92 @@
+From 63212ccae673e46334b874688741bf96d996fd36 Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Tue, 26 Apr 2016 13:17:03 +0300
+Subject: [PATCH 3/4] nis: add backend shutdown support to stop priming thread
+
+Resolves: rhbz#1327197
+---
+ src/back-nis.c |  6 ++++++
+ src/plug-nis.c | 34 +++++++++++++++++++++++++++-------
+ 2 files changed, 33 insertions(+), 7 deletions(-)
+
+diff --git a/src/back-nis.c b/src/back-nis.c
+index b9379c0..7fb191d 100644
+--- a/src/back-nis.c
++++ b/src/back-nis.c
+@@ -1021,6 +1021,12 @@ backend_startup(Slapi_PBlock *pb, struct plugin_state *state)
+ 	backend_shr_startup(state, pb, NIS_MAP_CONFIGURATION_FILTER);
+ }
+ 
++void
++backend_shutdown(struct plugin_state *state)
++{
++    backend_shr_shutdown(state);
++}
++
+ /* Set up our post-op callbacks. */
+ #ifdef SLAPI_NIS_SUPPORT_BE_TXNS
+ int
+diff --git a/src/plug-nis.c b/src/plug-nis.c
+index a1bdf89..ee90c37 100644
+--- a/src/plug-nis.c
++++ b/src/plug-nis.c
+@@ -81,14 +81,31 @@ plugin_startup(Slapi_PBlock *pb)
+ 	struct plugin_state *state;
+ 	const char *pname;
+ 	int i, protocol;
++	Slapi_DN *pluginsdn = NULL;
++
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+-	slapi_pblock_get(pb, SLAPI_TARGET_DN, &state->plugin_base);
+-	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+-			"configuration entry is %s%s%s\n",
+-			state->plugin_base ? "\"" : "",
+-			state->plugin_base ? state->plugin_base : "NULL",
+-			state->plugin_base ? "\"" : "");
++	slapi_pblock_get(pb, SLAPI_TARGET_SDN, &pluginsdn);
++	/* plugin base need to be duplicated because it will be destroyed
++	 * when pblock is destroyed but we need to use it in a separate thread */
++	if (NULL == pluginsdn || 0 == slapi_sdn_get_ndn_len(pluginsdn)) {
++        slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id,
++                        "nis plugin_startup: unable to retrieve plugin DN\n");
++		return -1;
++
++    } else {
++        state->plugin_base = slapi_ch_strdup(slapi_sdn_get_dn(pluginsdn));
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"configuration entry is %s%s%s\n",
++				state->plugin_base ? "\"" : "",
++				state->plugin_base ? state->plugin_base : "NULL",
++				state->plugin_base ? "\"" : "");
++    }
++
+ 	/* Populate the maps and data. */
++        if (state->priming_mutex == NULL) {
++            state->priming_mutex = wrap_new_mutex();
++	    state->start_priming_thread = 1;
++        }
+ 	backend_startup(pb, state);
+ 	/* Start a new listening thread to handle incoming traffic. */
+ 	state->tid = wrap_start_thread(&dispatch_thread, state);
+@@ -177,6 +194,7 @@ plugin_shutdown(Slapi_PBlock *pb)
+ 	struct plugin_state *state;
+ 	int i, protocol;
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
++        backend_shutdown(state);
+ 	for (i = 0; i < state->n_listeners; i++) {
+ 		if (state->pmap_client_socket != -1) {
+ 			switch (state->listener[i].type) {
+@@ -217,7 +235,9 @@ plugin_shutdown(Slapi_PBlock *pb)
+ #ifdef HAVE_TCPD_H
+ 	free(state->request_info);
+ #endif
+-	state->plugin_base = NULL;
++        if (state->plugin_base != NULL) {
++		slapi_ch_free((void **)&state->plugin_base);
++	}
+ 	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ 			"plugin shutdown completed\n");
+ 	return 0;
+-- 
+2.7.4
+
diff --git a/SOURCES/slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch b/SOURCES/slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch
new file mode 100644
index 0000000..7772689
--- /dev/null
+++ b/SOURCES/slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch
@@ -0,0 +1,99 @@
+From 02e32192779994cab254c548291c24d89429b335 Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Tue, 26 Apr 2016 13:17:46 +0300
+Subject: [PATCH 4/4] schema-compat: add backend shutdown support for priming
+ thread
+
+Resolves: rhbz#1327197
+---
+ src/back-sch.c |  6 ++++++
+ src/plug-sch.c | 34 +++++++++++++++++++++++++++-------
+ 2 files changed, 33 insertions(+), 7 deletions(-)
+
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 9a0e96b..32b1d9e 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -2280,6 +2280,12 @@ backend_startup(Slapi_PBlock *pb, struct plugin_state *state)
+ 	backend_shr_startup(state, pb, SCH_CONTAINER_CONFIGURATION_FILTER);
+ }
+ 
++void
++backend_shutdown(struct plugin_state *state)
++{
++    backend_shr_shutdown(state);
++}
++
+ int
+ backend_init_preop(Slapi_PBlock *pb, struct plugin_state *state)
+ {
+diff --git a/src/plug-sch.c b/src/plug-sch.c
+index 95a4fd8..7af8480 100644
+--- a/src/plug-sch.c
++++ b/src/plug-sch.c
+@@ -102,13 +102,26 @@ plugin_startup(Slapi_PBlock *pb)
+ 	/* Populate the maps and data. */
+ 	struct plugin_state *state;
+ 	Slapi_Entry *plugin_entry = NULL;
++	Slapi_DN *pluginsdn = NULL;
++
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+-	slapi_pblock_get(pb, SLAPI_TARGET_DN, &state->plugin_base);
+-	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+-			"configuration entry is %s%s%s\n",
+-			state->plugin_base ? "\"" : "",
+-			state->plugin_base ? state->plugin_base : "NULL",
+-			state->plugin_base ? "\"" : "");
++	slapi_pblock_get(pb, SLAPI_TARGET_SDN, &pluginsdn);
++	/* plugin base need to be duplicated because it will be destroyed
++	 * when pblock is destroyed but we need to use it in a separate thread */
++	if (NULL == pluginsdn || 0 == slapi_sdn_get_ndn_len(pluginsdn)) {
++        slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id,
++                        "scheman compat plugin_startup: unable to retrieve plugin DN\n");
++		return -1;
++
++    } else {
++        state->plugin_base = slapi_ch_strdup(slapi_sdn_get_dn(pluginsdn));
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"configuration entry is %s%s%s\n",
++				state->plugin_base ? "\"" : "",
++				state->plugin_base ? state->plugin_base : "NULL",
++				state->plugin_base ? "\"" : "");
++    }
++
+ 	state->pam_lock = wrap_new_rwlock();
+ 	backend_nss_init_context((struct nss_ops_ctx**) &state->nss_context);
+ 	if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
+@@ -122,6 +135,10 @@ plugin_startup(Slapi_PBlock *pb)
+ 	state->cached_entries = PL_NewHashTable(0, PL_HashString, PL_CompareStrings, PL_CompareValues, 0, 0);
+ 	wrap_rwlock_unlock(state->cached_entries_lock);
+ 	/* Populate the tree of fake entries. */
++        if (state->priming_mutex == NULL) {
++            state->priming_mutex = wrap_new_mutex();
++            state->start_priming_thread = 1;
++        }
+ 	backend_startup(pb, state);
+ 	/* Note that the plugin is ready to go. */
+ 	slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id,
+@@ -147,6 +164,7 @@ plugin_shutdown(Slapi_PBlock *pb)
+ {
+ 	struct plugin_state *state;
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
++        backend_shutdown(state);
+ 	map_done(state);
+ 	wrap_free_rwlock(state->pam_lock);
+ 	state->pam_lock = NULL;
+@@ -160,7 +178,9 @@ plugin_shutdown(Slapi_PBlock *pb)
+ 		wrap_free_rwlock(state->cached_entries_lock);
+ 		state->cached_entries_lock = NULL;
+ 	}
+-	state->plugin_base = NULL;
++	if (state->plugin_base != NULL) {
++		slapi_ch_free((void **)&state->plugin_base);
++	}
+ 	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ 			"plugin shutdown completed\n");
+ 	return 0;
+-- 
+2.7.4
+
diff --git a/SPECS/slapi-nis.spec b/SPECS/slapi-nis.spec
index 140a4f5..ca37210 100644
--- a/SPECS/slapi-nis.spec
+++ b/SPECS/slapi-nis.spec
@@ -11,7 +11,7 @@
 
 Name:		slapi-nis
 Version:	0.54
-Release:	6%{?dist}
+Release:	9%{?dist}
 Summary:	NIS Server and Schema Compatibility plugins for Directory Server
 Group:		System Environment/Daemons
 License:	GPLv2
@@ -27,6 +27,17 @@ Patch5:         slapi-nis-nss-Make-sure-default-buffer-for-nsswitch-operations-i
 Patch6:         slapi-nis-don-t-search-in-SSSD-when-memberUid-has-no.patch
 Patch7:		slapi-nis-delay-sending-responses-from-compat-tree-a.patch
 Patch8:		slapi-nis-fix-processing-of-ID-views.patch
+Patch15:	slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch
+Patch16:        slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch
+Patch17:        slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch
+Patch18:        slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch
+Patch19:        slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch
+Patch20:        slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch
+Patch21:        slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch
+Patch22:	slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch
+Patch23:	slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch
+Patch24:	slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch
+Patch25:	slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch
 
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires:	389-ds-base-devel, %{ldap_impl}-devel
@@ -74,6 +85,22 @@ for attributes from multiple entries in the tree.
 %patch6 -p1
 %patch7 -p1
 %patch8 -p1
+# patchset for "External membership of IPA groups"
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+# "Lock out NIS entries with nsAccountLock set to TRUE"
+%patch20 -p1
+# "Support bind with non-overridden uid rdn"
+%patch21 -p1
+# "Wait for priming thread join on shutdown"
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+
 %build
 %configure --disable-static --with-tcp-wrappers --with-ldap=%{ldap_impl} \
 	--with-nsswitch --with-pam --with-pam-service=system-auth \
@@ -103,6 +130,18 @@ rm -rf $RPM_BUILD_ROOT
 %{_sbindir}/nisserver-plugin-defs
 
 %changelog
+* Tue Apr 26 2016 Alexander Bokovoy <abokovoy@redhat.com> - 0.54-9
+- Reworked priming thread shutdown support
+- Resolves: #1327197
+
+* Fri Apr 15 2016 Alexander Bokovoy <abokovoy@redhat.com> - 0.54-8
+- Wait for priming thread to finish before shutdown
+- Resolves: #1327197
+
+* Tue Feb 23 2016 Alexander Bokovoy <abokovoy@redhat.com> - 0.54-7
+- Resolves: #1311257
+- Resolves: #1311012
+
 * Fri Nov 13 2015 Alexander Bokovoy <abokovoy@redhat.com> - 0.54-6
 - delay sending responses from compat tree after map cache search
 - Resolves: #1281748
@@ -115,6 +154,7 @@ rm -rf $RPM_BUILD_ROOT
 
 * Wed Jul 15 2015 Alexander Bokovoy <abokovoy@redhat.com> - 0.54-4
 - Fix CVE-2015-0283 for RHEL 7.2
+
 - Resolves: #1202996
 
 * Wed Mar 18 2015 Alexander Bokovoy <abokovoy@redhat.com> - 0.54-3