--- old/usr/src/uts/common/inet/ip/ipsecah.c	Thu Jun 15 10:52:03 2017
+++ new/usr/src/uts/common/inet/ip/ipsecah.c	Thu Jun 15 10:52:03 2017
@@ -21,6 +21,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -247,9 +248,9 @@
 	}
 	ekp = (ah_kstats_t *)kp->ks_data;
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 	ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	netstack_rele(ns);
 	return (0);
@@ -573,7 +574,7 @@
 	 * the variable part (i.e. the algorithms) of the message.
 	 */
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 
 	/*
 	 * Return only valid algorithms, so the number of algorithms
@@ -595,7 +596,7 @@
 	}
 	mp->b_cont = allocb(allocsize, BPRI_HI);
 	if (mp->b_cont == NULL) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		freemsg(mp);
 		return (B_FALSE);
 	}
@@ -642,7 +643,7 @@
 		nextext = (sadb_ext_t *)saalg;
 	}
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	if (sens_tsl != NULL) {
 		sens = (sadb_sens_t *)nextext;
@@ -1123,10 +1124,10 @@
 	 */
 
 	/* verify that there is a mapping for the specified algorithm */
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 	aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
 	if (aalg == NULL || !ALG_VALID(aalg)) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
 		    assoc->sadb_sa_auth));
 		*diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
@@ -1136,7 +1137,7 @@
 
 	/* sanity check key sizes */
 	if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		*diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
 		return (EINVAL);
 	}
@@ -1144,11 +1145,11 @@
 	/* check key and fix parity if needed */
 	if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
 	    diagnostic) != 0) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		return (EINVAL);
 	}
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
 	    diagnostic, ahstack));
@@ -1749,7 +1750,7 @@
 	ipsecah_stack_t	*ahstack = ns->netstack_ipsecah;
 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
 
 	prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
 	prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
@@ -1861,7 +1862,7 @@
 		mutex_exit(&acqrec->ipsacq_lock);
 		return;
 	}
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
 	combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
 	msgmp = pfkeymp->b_cont;
 	samsg = (sadb_msg_t *)(msgmp->b_rptr);
@@ -1873,7 +1874,7 @@
 	samsg->sadb_msg_len += prop->sadb_prop_len;
 	msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	/*
 	 * Must mutex_exit() before sending PF_KEY message up, in
--- old/usr/src/uts/common/inet/ip/ipsecesp.c	Thu Jun 15 10:52:03 2017
+++ new/usr/src/uts/common/inet/ip/ipsecesp.c	Thu Jun 15 10:52:03 2017
@@ -298,12 +298,12 @@
 	}
 	ekp = (esp_kstats_t *)kp->ks_data;
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 	ekp->esp_stat_num_aalgs.value.ui64 =
 	    ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
 	ekp->esp_stat_num_ealgs.value.ui64 =
 	    ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	netstack_rele(ns);
 	return (0);
@@ -1195,7 +1195,7 @@
 	ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
 
 	prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
 	prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
@@ -1325,7 +1325,7 @@
 		mutex_exit(&acqrec->ipsacq_lock);
 		return;
 	}
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
 	combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
 	    ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
 	msgmp = pfkeymp->b_cont;
@@ -1338,7 +1338,7 @@
 	samsg->sadb_msg_len += prop->sadb_prop_len;
 	msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	/*
 	 * Must mutex_exit() before sending PF_KEY message up, in
@@ -3043,7 +3043,7 @@
 	 * Allocate the PF_KEY message that follows KEYSOCK_OUT.
 	 */
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 	/*
 	 * Fill SADB_REGISTER message's algorithm descriptors.  Hold
 	 * down the lock while filling it.
@@ -3072,7 +3072,7 @@
 	}
 	keysock_out_mp->b_cont = allocb(allocsize, BPRI_HI);
 	if (keysock_out_mp->b_cont == NULL) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		freemsg(keysock_out_mp);
 		return (B_FALSE);
 	}
@@ -3166,7 +3166,7 @@
 	current_aalgs = num_aalgs;
 	current_ealgs = num_ealgs;
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	if (sens_tsl != NULL) {
 		sens = (sadb_sens_t *)nextext;
@@ -3691,7 +3691,7 @@
 	 * the weak key check up to the algorithm.
 	 */
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 
 	/*
 	 * First locate the authentication algorithm.
@@ -3706,7 +3706,7 @@
 		aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
 		    [assoc->sadb_sa_auth];
 		if (aalg == NULL || !ALG_VALID(aalg)) {
-			mutex_exit(&ipss->ipsec_alg_lock);
+			rw_exit(&ipss->ipsec_alg_lock);
 			esp1dbg(espstack, ("Couldn't find auth alg #%d.\n",
 			    assoc->sadb_sa_auth));
 			*diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
@@ -3721,7 +3721,7 @@
 		 * a auth_key != NULL should be made here ( see below).
 		 */
 		if (!ipsec_valid_key_size(akey->sadb_key_bits, aalg)) {
-			mutex_exit(&ipss->ipsec_alg_lock);
+			rw_exit(&ipss->ipsec_alg_lock);
 			*diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
 			return (EINVAL);
 		}
@@ -3730,7 +3730,7 @@
 		/* check key and fix parity if needed */
 		if (ipsec_check_key(aalg->alg_mech_type, akey, B_TRUE,
 		    diagnostic) != 0) {
-			mutex_exit(&ipss->ipsec_alg_lock);
+			rw_exit(&ipss->ipsec_alg_lock);
 			return (EINVAL);
 		}
 	}
@@ -3745,7 +3745,7 @@
 		ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
 		    [assoc->sadb_sa_encrypt];
 		if (ealg == NULL || !ALG_VALID(ealg)) {
-			mutex_exit(&ipss->ipsec_alg_lock);
+			rw_exit(&ipss->ipsec_alg_lock);
 			esp1dbg(espstack, ("Couldn't find encr alg #%d.\n",
 			    assoc->sadb_sa_encrypt));
 			*diagnostic = SADB_X_DIAGNOSTIC_BAD_EALG;
@@ -3766,7 +3766,7 @@
 		keybits -= SADB_8TO1(ealg->alg_saltlen);
 		if ((assoc->sadb_sa_encrypt == SADB_EALG_NULL) ||
 		    (!ipsec_valid_key_size(keybits, ealg))) {
-			mutex_exit(&ipss->ipsec_alg_lock);
+			rw_exit(&ipss->ipsec_alg_lock);
 			*diagnostic = SADB_X_DIAGNOSTIC_BAD_EKEYBITS;
 			return (EINVAL);
 		}
@@ -3775,11 +3775,11 @@
 		/* check key */
 		if (ipsec_check_key(ealg->alg_mech_type, ekey, B_FALSE,
 		    diagnostic) != 0) {
-			mutex_exit(&ipss->ipsec_alg_lock);
+			rw_exit(&ipss->ipsec_alg_lock);
 			return (EINVAL);
 		}
 	}
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	return (esp_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
 	    diagnostic, espstack));
--- old/usr/src/uts/common/inet/ip/sadb.c	Thu Jun 15 10:52:03 2017
+++ new/usr/src/uts/common/inet/ip/sadb.c	Thu Jun 15 10:52:03 2017
@@ -21,6 +21,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -3198,7 +3199,7 @@
 		newbie->ipsa_kcfauthkey.ck_length = newbie->ipsa_authkeybits;
 		newbie->ipsa_kcfauthkey.ck_data = newbie->ipsa_authkey;
 
-		mutex_enter(&ipss->ipsec_alg_lock);
+		rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 		alg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
 		    [newbie->ipsa_auth_alg];
 		if (alg != NULL && ALG_VALID(alg)) {
@@ -3211,7 +3212,7 @@
 			newbie->ipsa_amech.cm_type = CRYPTO_MECHANISM_INVALID;
 		}
 		error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_AUTH);
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		if (error != 0) {
 			mutex_exit(&newbie->ipsa_lock);
 			/*
@@ -3228,7 +3229,7 @@
 	}
 
 	if (ekey != NULL) {
-		mutex_enter(&ipss->ipsec_alg_lock);
+		rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 		async = async || (ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
 		    IPSEC_ALGS_EXEC_ASYNC);
 		alg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
@@ -3261,7 +3262,7 @@
 		} else {
 			newbie->ipsa_emech.cm_type = CRYPTO_MECHANISM_INVALID;
 		}
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 
 		/*
 		 * The byte stream following the sadb_key_t is made up of:
@@ -3373,9 +3374,9 @@
 		newbie->ipsa_kcfencrkey.ck_length = newbie->ipsa_encrkeybits;
 		newbie->ipsa_kcfencrkey.ck_data = newbie->ipsa_encrkey;
 
-		mutex_enter(&ipss->ipsec_alg_lock);
+		rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 		error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_ENCR);
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		if (error != 0) {
 			mutex_exit(&newbie->ipsa_lock);
 			/* See above for error explanation. */
@@ -5281,11 +5282,11 @@
 	 * a stronger policy, and when the framework loads a stronger version,
 	 * you can just keep plowing w/o rewhacking your SPD.
 	 */
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 	algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ?
 	    IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg];
 	if (algp == NULL) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		return (NULL);	/* Algorithm doesn't exist.  Fail gracefully. */
 	}
 	if (minbits < algp->alg_ef_minbits)
@@ -5292,7 +5293,7 @@
 		minbits = algp->alg_ef_minbits;
 	if (maxbits > algp->alg_ef_maxbits)
 		maxbits = algp->alg_ef_maxbits;
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen);
 	algdesc->sadb_x_algdesc_satype = satype;
@@ -5774,7 +5775,7 @@
 	/* Make sure there's enough to cover both AF_INET and AF_INET6. */
 	allocsize += 2 * sizeof (struct sockaddr_in6);
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 	/* NOTE:  The lock is now held through to this function's return. */
 	allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
 	    ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t);
@@ -5789,7 +5790,7 @@
 	msgmp = allocb(allocsize, BPRI_HI);
 	if (msgmp == NULL) {
 		freeb(pfkeymp);
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		return (NULL);
 	}
 
@@ -5812,7 +5813,7 @@
 		cmn_err(CE_WARN,
 		    "sadb_setup_acquire:  corrupt ACQUIRE record.\n");
 		ASSERT(0);
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		return (NULL);
 	}
 
@@ -5859,7 +5860,7 @@
 	if (cur != NULL)
 		samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
 	else
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 
 	return (pfkeymp);
 }
@@ -7190,7 +7191,7 @@
 	int rv;
 	ipsec_stack_t	*ipss = sa->ipsa_netstack->netstack_ipsec;
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
 	ASSERT(MUTEX_HELD(&sa->ipsa_lock));
 
 	/* get pointers to the algorithm info, context template, and key */
--- old/usr/src/uts/common/inet/ip/spd.c	Thu Jun 15 10:52:04 2017
+++ new/usr/src/uts/common/inet/ip/spd.c	Thu Jun 15 10:52:04 2017
@@ -21,6 +21,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2016 by Delphix. All rights reserved.
  */
 
@@ -413,7 +414,7 @@
 		mutex_destroy(&(ipss->ipsec_sel_hash[i].hash_lock));
 	}
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_WRITER);
 	for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype ++) {
 		int nalgs = ipss->ipsec_nalgs[algtype];
 
@@ -422,8 +423,8 @@
 				ipsec_alg_unreg(algtype, i, ns);
 		}
 	}
-	mutex_exit(&ipss->ipsec_alg_lock);
-	mutex_destroy(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
+	rw_destroy(&ipss->ipsec_alg_lock);
 
 	ipsid_gc(ns);
 	ipsid_fini(ns);
@@ -655,7 +656,7 @@
 		mutex_init(&(ipss->ipsec_sel_hash[i].hash_lock),
 		    NULL, MUTEX_DEFAULT, NULL);
 
-	mutex_init(&ipss->ipsec_alg_lock, NULL, MUTEX_DEFAULT, NULL);
+	rw_init(&ipss->ipsec_alg_lock, NULL, RW_DEFAULT, NULL);
 	for (i = 0; i < IPSEC_NALGTYPES; i++) {
 		ipss->ipsec_nalgs[i] = 0;
 	}
@@ -718,7 +719,7 @@
 	ASSERT(ai != NULL);
 	ASSERT(algid == ai->alg_id);
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 
 	holder = algid;
 
@@ -755,7 +756,7 @@
 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
 	int newcount = ipss->ipsec_nalgs[at];
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 
 	for (i = 0; i <= newcount; i++) {
 		if (copyback) {
@@ -776,7 +777,7 @@
 {
 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 
 	ASSERT(ipss->ipsec_alglists[algtype][alg->alg_id] == NULL);
 	ipsec_alg_fix_min_max(alg, algtype, ns);
@@ -795,7 +796,7 @@
 {
 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 
 	ASSERT(ipss->ipsec_alglists[algtype][algid] != NULL);
 	ipsec_alg_free(ipss->ipsec_alglists[algtype][algid]);
@@ -4703,7 +4704,7 @@
 	crypto_mech_usage_t mask;
 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
 
-	ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
+	ASSERT(RW_WRITE_HELD(&ipss->ipsec_alg_lock));
 
 	/*
 	 * Compute the min, max, and default key sizes (in number of
@@ -5056,7 +5057,7 @@
 	 * the algorithm valid flag and trigger an update of the
 	 * SAs that depend on that algorithm.
 	 */
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_WRITER);
 	for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
 		for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
 		    algidx++) {
@@ -5119,7 +5120,7 @@
 				    CRYPTO_MECH_ADDED, ns);
 		}
 	}
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 	crypto_free_mech_list(mechs, mech_count);
 
 	if (alg_changed) {
--- old/usr/src/uts/common/inet/ip/spdsock.c	Thu Jun 15 10:52:05 2017
+++ new/usr/src/uts/common/inet/ip/spdsock.c	Thu Jun 15 10:52:05 2017
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <sys/param.h>
@@ -2268,7 +2269,7 @@
 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
 	ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 	/*
 	 * The SPD client expects to receive separate entries for
 	 * AH authentication and ESP authentication supported algorithms.
@@ -2296,7 +2297,7 @@
 
 	m = allocb(size, BPRI_HI);
 	if (m == NULL) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		spdsock_error(q, mp, ENOMEM, 0);
 		return;
 	}
@@ -2367,7 +2368,7 @@
 		}
 	}
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 #undef EMITALGATTRS
 #undef EMIT
@@ -2404,7 +2405,7 @@
 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
 	ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 
 	/*
 	 * For each algorithm, we encode:
@@ -2437,7 +2438,7 @@
 
 	m = allocb(size, BPRI_HI);
 	if (m == NULL) {
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		spdsock_error(q, mp, ENOMEM, 0);
 		return;
 	}
@@ -2471,7 +2472,7 @@
 	 */
 	if (act->spd_actions_count == 0) {
 		act->spd_actions_len = 0;
-		mutex_exit(&ipss->ipsec_alg_lock);
+		rw_exit(&ipss->ipsec_alg_lock);
 		goto error;
 	}
 
@@ -2523,7 +2524,7 @@
 		}
 	}
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 #undef EMITALGATTRS
 #undef EMIT
@@ -3684,7 +3685,7 @@
 		}
 	}
 
-	mutex_enter(&ipss->ipsec_alg_lock);
+	rw_enter(&ipss->ipsec_alg_lock, RW_WRITER);
 
 	/*
 	 * For each algorithm currently defined, check if it is
@@ -3740,7 +3741,7 @@
 		    spds->spds_algs_exec_mode[algtype];
 	}
 
-	mutex_exit(&ipss->ipsec_alg_lock);
+	rw_exit(&ipss->ipsec_alg_lock);
 
 	crypto_free_mech_list(mechs, mech_count);
 
--- old/usr/src/uts/common/inet/ipsec_impl.h	Thu Jun 15 10:52:05 2017
+++ new/usr/src/uts/common/inet/ipsec_impl.h	Thu Jun 15 10:52:05 2017
@@ -21,6 +21,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef _INET_IPSEC_IMPL_H
@@ -785,7 +786,7 @@
 	 * Because policy needs to know what algorithms are supported, keep the
 	 * lists of algorithms here.
 	 */
-	kmutex_t 		ipsec_alg_lock;
+	krwlock_t 		ipsec_alg_lock;
 
 	uint8_t			ipsec_nalgs[IPSEC_NALGTYPES];
 	ipsec_alginfo_t	*ipsec_alglists[IPSEC_NALGTYPES][IPSEC_MAX_ALGS];
--- old/usr/src/uts/common/inet/sadb.h	Thu Jun 15 10:52:05 2017
+++ new/usr/src/uts/common/inet/sadb.h	Thu Jun 15 10:52:05 2017
@@ -21,6 +21,7 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #ifndef	_INET_SADB_H
@@ -915,9 +916,9 @@
 			ipsec_stack_t *ipss;				\
 									\
 			ipss = assoc->ipsa_netstack->netstack_ipsec;	\
-			mutex_enter(&ipss->ipsec_alg_lock);		\
+			rw_enter(&ipss->ipsec_alg_lock, RW_READER);	\
 			(void) ipsec_create_ctx_tmpl(_sa, _type);	\
-			mutex_exit(&ipss->ipsec_alg_lock);		\
+			rw_exit(&ipss->ipsec_alg_lock);			\
 		}							\
 		mutex_exit(&assoc->ipsa_lock);				\
 		if ((_tmpl = (_sa)->_which) == IPSEC_CTX_TMPL_ALLOC)	\
