6736087 smb_kdoor_clnt_upcall: failed
authorAlan Wright <amw@Sun.COM>
Sun, 14 Sep 2008 17:28:06 -0700
changeset 7588 fc605a2defdc
parent 7587 821e6b4434ec
child 7589 7de800909a06
6736087 smb_kdoor_clnt_upcall: failed 6740462 CIFS i/o failure - smb_kdoor_clnt_upcall: failed(4) 6747505 vmem_xfree: NULL pointer dereference panic
usr/src/cmd/smbsrv/smbadm/smbadm.c
usr/src/cmd/smbsrv/smbd/smbd_door_ops.c
usr/src/lib/libshare/smb/libshare_smb.c
usr/src/lib/libshare/smb/smb_share_doorclnt.c
usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c
usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c
usr/src/lib/smbsrv/libmlsvc/common/smb_share.c
usr/src/lib/smbsrv/libsmb/Makefile.com
usr/src/lib/smbsrv/libsmb/common/libsmb.h
usr/src/lib/smbsrv/libsmb/common/mapfile-vers
usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c
usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c
usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c
usr/src/lib/smbsrv/libsmb/common/smb_downcalls.c
usr/src/uts/common/fs/smbsrv/smb_kdoor_clnt.c
usr/src/uts/common/fs/smbsrv/smb_kdoor_srv.c
usr/src/uts/common/fs/smbsrv/smb_server.c
usr/src/uts/common/fs/smbsrv/smb_upcalls.c
usr/src/uts/common/smbsrv/smb_door_svc.h
usr/src/uts/common/smbsrv/smb_share.h
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)smbadm.c	1.9	08/07/30 SMI"
-
 /*
  * This module contains smbadm CLI which offers smb configuration
  * functionalities.
@@ -40,7 +38,6 @@
 #include <grp.h>
 #include <libgen.h>
 #include <netinet/in.h>
-
 #include <smbsrv/libsmb.h>
 
 typedef enum {
@@ -367,23 +364,21 @@
 	boolean_t ret = B_FALSE;
 
 	switch (prmpt_type) {
-
-		case SMBADM_CHANGE_SECMODE:
-			(void) printf(gettext("This operation requires that "
-			    "the service be restarted.\n"));
-			ret = smbadm_confirm(
-			    "Would you like to continue ?", "no");
-			break;
+	case SMBADM_CHANGE_SECMODE:
+		(void) printf(gettext("This operation requires that "
+		    "the service be restarted.\n"));
+		ret = smbadm_confirm("Would you like to continue?", "no");
+		break;
 
-		case SMBADM_CHANGE_DOMAIN:
-			(void) printf(gettext("This system has already "
-			    "joined to '%s' domain.\n"), curdom);
-			ret = smbadm_confirm(
-			    "Would you like to join the new domain ?", "no");
-			break;
+	case SMBADM_CHANGE_DOMAIN:
+		(void) printf(gettext("This system is already a member "
+		    "of %s.\n"), curdom);
+		ret = smbadm_confirm("Would you like to join the new domain?",
+		    "no");
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 
 	return (ret);
--- a/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)smbd_door_ops.c	1.6	08/07/16 SMI"
-
 /*
  * SMBd door operations
  */
@@ -37,10 +35,7 @@
 #include <smbsrv/libmlsvc.h>
 #include "smbd.h"
 
-static int smb_set_downcall_desc(int desc);
-static int smb_get_downcall_desc(void);
-
-static char *smb_dop_set_dwncall_desc(char *argp, size_t arg_size,
+static char *smb_dop_set_downcall_fd(char *argp, size_t arg_size,
     door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
 static char *smb_dop_user_auth_logon(char *argp, size_t arg_size,
     door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
@@ -65,7 +60,7 @@
 smb_dr_op_t smb_doorsrv_optab[] =
 {
 	smb_dop_user_auth_logon,
-	smb_dop_set_dwncall_desc,
+	smb_dop_set_downcall_fd,
 	smb_dop_user_nonauth_logon,
 	smb_dop_user_auth_logoff,
 	smb_dop_user_list,
@@ -128,45 +123,6 @@
 }
 
 /*
- * smb_downcall_desc
- *
- * This downcall descriptor will be initialized when the SMB Kmod
- * makes a upcall for the SMBD_DOOR_SET_DOWNCALL_DESC.
- * This descriptor should be passed as the 1st argument to the
- * door_call() whenever the SMBD is making a downcall to SMB Kmod.
- */
-static int smb_downcall_desc = -1;
-static mutex_t smb_downcall_mutex;
-
-/*
- * Get and set the smb downcall descriptor.
- */
-static int
-smb_set_downcall_desc(int desc)
-{
-	(void) mutex_lock(&smb_downcall_mutex);
-	smb_downcall_desc = desc;
-	(void) mutex_unlock(&smb_downcall_mutex);
-	return (0);
-}
-
-/*
- * smb_get_downcall_desc
- *
- * Returns the downcall descriptor.
- */
-static int
-smb_get_downcall_desc(void)
-{
-	int rc;
-
-	(void) mutex_lock(&smb_downcall_mutex);
-	rc = smb_downcall_desc;
-	(void) mutex_unlock(&smb_downcall_mutex);
-	return (rc);
-}
-
-/*
  * smb_dr_is_valid_opcode
  *
  * Validates the given door opcode.
@@ -219,13 +175,11 @@
 }
 
 /*
- * smb_dop_set_dwncall_desc
- *
- * Set the downcall descriptor.
+ * Set the downcall file descriptor.
  */
 /*ARGSUSED*/
 static char *
-smb_dop_set_dwncall_desc(char *argp, size_t arg_size,
+smb_dop_set_downcall_fd(char *argp, size_t arg_size,
     door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
 {
 	char *buf = NULL;
@@ -234,14 +188,13 @@
 	*rbufsize = 0;
 	*err = 0;
 
-	if (n_desc != 1 ||
-	    smb_set_downcall_desc(dp->d_data.d_desc.d_descriptor) != 0) {
-		stat = SMB_DR_OP_ERR;
+	if (n_desc == 1) {
+		mlsvc_set_door_fd(dp->d_data.d_desc.d_descriptor);
+		stat = SMB_DR_OP_SUCCESS;
 	} else {
-		/* install get downcall descriptor callback */
-		(void) smb_dwncall_install_callback(smb_get_downcall_desc);
-		stat = SMB_DR_OP_SUCCESS;
+		stat = SMB_DR_OP_ERR;
 	}
+
 	if ((buf = smb_dr_set_res_stat(stat, rbufsize)) == NULL) {
 		*err = SMB_DR_OP_ERR_ENCODE;
 		*rbufsize = 0;
@@ -284,7 +237,7 @@
 		return (NULL);
 	}
 
-	cnt = smb_dwncall_get_users(offset, ulist);
+	cnt = mlsvc_get_user_list(offset, ulist);
 	if (cnt < 0) {
 		*err = SMB_DR_OP_ERR_EMPTYBUF;
 		free(ulist);
--- a/usr/src/lib/libshare/smb/libshare_smb.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/libshare/smb/libshare_smb.c	Sun Sep 14 17:28:06 2008 -0700
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)libshare_smb.c	1.16	08/08/05 SMI"
-
 /*
  * SMB specific functions
  */
@@ -939,15 +937,15 @@
  */
 /*ARGSUSED*/
 static int
-path_validator(int index, char *value)
+path_validator(int index, char *path)
 {
 	struct stat buffer;
 	int fd, status;
 
-	if (value == NULL)
+	if (path == NULL)
 		return (SA_BAD_VALUE);
 
-	fd = open(value, O_RDONLY);
+	fd = open(path, O_RDONLY);
 	if (fd < 0)
 		return (SA_BAD_VALUE);
 
@@ -1030,6 +1028,7 @@
 	if (sa_plugin_ops.sa_init != smb_share_init)
 		return (SA_SYSTEM_ERR);
 
+	smb_share_door_clnt_init();
 	return (smb_load_proto_properties());
 }
 
@@ -1043,7 +1042,7 @@
 	xmlFreeNode(protoset);
 	protoset = NULL;
 
-	(void) smb_share_dclose();
+	smb_share_door_clnt_fini();
 }
 
 /*
--- a/usr/src/lib/libshare/smb/smb_share_doorclnt.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/libshare/smb/smb_share_doorclnt.c	Sun Sep 14 17:28:06 2008 -0700
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)smb_share_doorclnt.c	1.5	08/08/05 SMI"
-
 /*
  * User-space door client for LanMan share management.
  */
@@ -46,19 +44,40 @@
 #include <smbsrv/lmerr.h>
 #include <smbsrv/cifs.h>
 
+#define	SMB_SHARE_DOOR_CALL_RETRIES		3
+
 static int smb_share_dfd = -1;
 static uint64_t smb_share_dncall = 0;
 static mutex_t smb_share_dmtx;
 static cond_t smb_share_dcv;
 
+static int smb_share_door_clnt_open(void);
+static void smb_share_door_clnt_close(void);
+
+void
+smb_share_door_clnt_init(void)
+{
+	(void) mutex_lock(&smb_share_dmtx);
+	(void) smb_share_door_clnt_open();
+	(void) mutex_unlock(&smb_share_dmtx);
+}
+
+void
+smb_share_door_clnt_fini(void)
+{
+	(void) mutex_lock(&smb_share_dmtx);
+	smb_share_door_clnt_close();
+	(void) mutex_unlock(&smb_share_dmtx);
+}
+
 /*
- * Open the lmshrd door.  This is a private call for use by
- * smb_share_denter() and must be called with smb_share_dmtx held.
+ * Open smb_share_door.  This is a private call for use by
+ * smb_share_door_clnt_enter() and must be called with smb_share_dmtx held.
  *
  * Returns the door fd on success.  Otherwise, -1.
  */
 static int
-smb_share_dopen(void)
+smb_share_door_clnt_open(void)
 {
 	if (smb_share_dfd == -1) {
 		if ((smb_share_dfd = open(SMB_SHARE_DNAME, O_RDONLY)) < 0)
@@ -71,13 +90,12 @@
 }
 
 /*
- * Close the lmshrd door.
+ * Close smb_share_door.
+ * Private call that must be called with smb_share_dmtx held.
  */
-void
-smb_share_dclose(void)
+static void
+smb_share_door_clnt_close(void)
 {
-	(void) mutex_lock(&smb_share_dmtx);
-
 	if (smb_share_dfd != -1) {
 		while (smb_share_dncall > 0)
 			(void) cond_wait(&smb_share_dcv, &smb_share_dmtx);
@@ -87,22 +105,20 @@
 			smb_share_dfd = -1;
 		}
 	}
-
-	(void) mutex_unlock(&smb_share_dmtx);
 }
 
 /*
- * Entry handler for lmshrd door calls.
+ * Entry handler for smb_share_door calls.
  */
 static door_arg_t *
-smb_share_denter(void)
+smb_share_door_clnt_enter(void)
 {
 	door_arg_t *arg;
 	char *buf;
 
 	(void) mutex_lock(&smb_share_dmtx);
 
-	if (smb_share_dopen() == -1) {
+	if (smb_share_door_clnt_open() == -1) {
 		(void) mutex_unlock(&smb_share_dmtx);
 		return (NULL);
 	}
@@ -122,24 +138,44 @@
 }
 
 /*
- * Exit handler for lmshrd door calls.
+ * Exit handler for smb_share_door calls.
  */
 static void
-smb_share_dexit(door_arg_t *arg, char *errmsg)
+smb_share_door_clnt_exit(door_arg_t *arg, boolean_t must_close, char *errmsg)
 {
 	if (errmsg)
-		syslog(LOG_DEBUG, "lmshrd_door: %s", errmsg);
+		syslog(LOG_DEBUG, "smb_share_door: %s failed", errmsg);
 
 	(void) mutex_lock(&smb_share_dmtx);
 	free(arg);
 	--smb_share_dncall;
 	(void) cond_signal(&smb_share_dcv);
+
+	if (must_close)
+		smb_share_door_clnt_close();
+
 	(void) mutex_unlock(&smb_share_dmtx);
 }
 
-/*
- * Return 0 upon success. Otherwise, -1.
- */
+static int
+smb_share_door_call(int fd, door_arg_t *arg)
+{
+	int rc;
+	int i;
+
+	for (i = 0; i < SMB_SHARE_DOOR_CALL_RETRIES; ++i) {
+		errno = 0;
+
+		if ((rc = door_call(fd, arg)) == 0)
+			break;
+
+		if (errno != EAGAIN && errno != EINTR)
+			break;
+	}
+
+	return (rc);
+}
+
 static int
 smb_share_dchk(smb_dr_ctx_t *dec_ctx)
 {
@@ -164,7 +200,7 @@
 
 	bzero(list, sizeof (smb_shrlist_t));
 
-	if ((arg = smb_share_denter()) == NULL)
+	if ((arg = smb_share_door_clnt_enter()) == NULL)
 		return (NERR_InternalError);
 
 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
@@ -173,31 +209,30 @@
 
 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
 	if (rc != 0) {
-		smb_share_dexit(arg, "encode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "encode");
 		return (NERR_InternalError);
 	}
 
-	if (door_call(smb_share_dfd, arg) < 0) {
-		smb_share_dexit(arg, "door call error");
-		smb_share_dclose();
+	if (smb_share_door_call(smb_share_dfd, arg) < 0) {
+		smb_share_door_clnt_exit(arg, B_TRUE, "door call");
 		return (NERR_InternalError);
 	}
 
 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
 	if (smb_share_dchk(dec_ctx) != 0) {
 		(void) smb_dr_decode_finish(dec_ctx);
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
 	(void) smb_dr_get_buf(dec_ctx, (unsigned char *)list,
 	    sizeof (smb_shrlist_t));
 	if (smb_dr_decode_finish(dec_ctx) != 0) {
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
-	smb_share_dexit(arg, NULL);
+	smb_share_door_clnt_exit(arg, B_FALSE, NULL);
 	return (NERR_Success);
 }
 
@@ -210,7 +245,7 @@
 	uint32_t num_shares;
 	int rc;
 
-	if ((arg = smb_share_denter()) == NULL)
+	if ((arg = smb_share_door_clnt_enter()) == NULL)
 		return (-1);
 
 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
@@ -218,30 +253,29 @@
 
 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
 	if (rc != 0) {
-		smb_share_dexit(arg, "encode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "encode");
 		return (-1);
 	}
 
-	if (door_call(smb_share_dfd, arg) < 0) {
-		smb_share_dexit(arg, "door call error");
-		smb_share_dclose();
+	if (smb_share_door_call(smb_share_dfd, arg) < 0) {
+		smb_share_door_clnt_exit(arg, B_TRUE, "door call");
 		return (-1);
 	}
 
 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
 	if (smb_share_dchk(dec_ctx) != 0) {
 		(void) smb_dr_decode_finish(dec_ctx);
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (-1);
 	}
 
 	num_shares = smb_dr_get_uint32(dec_ctx);
 	if (smb_dr_decode_finish(dec_ctx) != 0) {
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (-1);
 	}
 
-	smb_share_dexit(arg, NULL);
+	smb_share_door_clnt_exit(arg, B_FALSE, NULL);
 	return (num_shares);
 }
 
@@ -253,7 +287,7 @@
 	smb_dr_ctx_t *enc_ctx;
 	uint32_t rc;
 
-	if ((arg = smb_share_denter()) == NULL)
+	if ((arg = smb_share_door_clnt_enter()) == NULL)
 		return (NERR_InternalError);
 
 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
@@ -262,30 +296,29 @@
 
 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
 	if (rc != 0) {
-		smb_share_dexit(arg, "encode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "encode");
 		return (NERR_InternalError);
 	}
 
-	if (door_call(smb_share_dfd, arg) < 0) {
-		smb_share_dexit(arg, "door call error");
-		smb_share_dclose();
+	if (smb_share_door_call(smb_share_dfd, arg) < 0) {
+		smb_share_door_clnt_exit(arg, B_TRUE, "door call");
 		return (NERR_InternalError);
 	}
 
 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
 	if (smb_share_dchk(dec_ctx) != 0) {
 		(void) smb_dr_decode_finish(dec_ctx);
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
 	rc = smb_dr_get_uint32(dec_ctx);
 	if (smb_dr_decode_finish(dec_ctx) != 0) {
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
-	smb_share_dexit(arg, NULL);
+	smb_share_door_clnt_exit(arg, B_FALSE, NULL);
 	return (rc);
 
 }
@@ -298,7 +331,7 @@
 	smb_dr_ctx_t *enc_ctx;
 	uint32_t rc;
 
-	if ((arg = smb_share_denter()) == NULL)
+	if ((arg = smb_share_door_clnt_enter()) == NULL)
 		return (NERR_InternalError);
 
 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
@@ -308,30 +341,29 @@
 
 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
 	if (rc != 0) {
-		smb_share_dexit(arg, "encode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "encode");
 		return (NERR_InternalError);
 	}
 
-	if (door_call(smb_share_dfd, arg) < 0) {
-		smb_share_dexit(arg, "door call error");
-		smb_share_dclose();
+	if (smb_share_door_call(smb_share_dfd, arg) < 0) {
+		smb_share_door_clnt_exit(arg, B_TRUE, "door call");
 		return (NERR_InternalError);
 	}
 
 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
 	if (smb_share_dchk(dec_ctx) != 0) {
 		(void) smb_dr_decode_finish(dec_ctx);
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
 	rc = smb_dr_get_uint32(dec_ctx);
 	if (smb_dr_decode_finish(dec_ctx) != 0) {
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
-	smb_share_dexit(arg, NULL);
+	smb_share_door_clnt_exit(arg, B_FALSE, NULL);
 	return (rc);
 }
 
@@ -343,7 +375,7 @@
 	smb_dr_ctx_t *enc_ctx;
 	uint32_t rc;
 
-	if ((arg = smb_share_denter()) == NULL)
+	if ((arg = smb_share_door_clnt_enter()) == NULL)
 		return (NERR_InternalError);
 
 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
@@ -352,31 +384,30 @@
 
 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
 	if (rc != 0) {
-		smb_share_dexit(arg, "encode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "encode");
 		return (NERR_InternalError);
 	}
 
-	if (door_call(smb_share_dfd, arg) < 0) {
-		smb_share_dexit(arg, "door call error");
-		smb_share_dclose();
+	if (smb_share_door_call(smb_share_dfd, arg) < 0) {
+		smb_share_door_clnt_exit(arg, B_TRUE, "door call");
 		return (NERR_InternalError);
 	}
 
 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
 	if (smb_share_dchk(dec_ctx) != 0) {
 		(void) smb_dr_decode_finish(dec_ctx);
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
 	rc = smb_dr_get_uint32(dec_ctx);
 	smb_dr_get_share(dec_ctx, si);
 	if (smb_dr_decode_finish(dec_ctx) != 0) {
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
-	smb_share_dexit(arg, NULL);
+	smb_share_door_clnt_exit(arg, B_FALSE, NULL);
 	return (rc);
 }
 
@@ -388,7 +419,7 @@
 	smb_dr_ctx_t *enc_ctx;
 	uint32_t rc;
 
-	if ((arg = smb_share_denter()) == NULL)
+	if ((arg = smb_share_door_clnt_enter()) == NULL)
 		return (NERR_InternalError);
 
 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
@@ -397,31 +428,30 @@
 
 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
 	if (rc != 0) {
-		smb_share_dexit(arg, "encode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "encode");
 		return (NERR_InternalError);
 	}
 
-	if (door_call(smb_share_dfd, arg) < 0) {
-		smb_share_dexit(arg, "door call error");
-		smb_share_dclose();
+	if (smb_share_door_call(smb_share_dfd, arg) < 0) {
+		smb_share_door_clnt_exit(arg, B_TRUE, "door call");
 		return (NERR_InternalError);
 	}
 
 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
 	if (smb_share_dchk(dec_ctx) != 0) {
 		(void) smb_dr_decode_finish(dec_ctx);
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
 	rc = smb_dr_get_uint32(dec_ctx);
 	smb_dr_get_share(dec_ctx, si);
 	if (smb_dr_decode_finish(dec_ctx) != 0) {
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
-	smb_share_dexit(arg, NULL);
+	smb_share_door_clnt_exit(arg, B_FALSE, NULL);
 	return (rc);
 }
 
@@ -433,7 +463,7 @@
 	smb_dr_ctx_t *enc_ctx;
 	uint32_t rc;
 
-	if ((arg = smb_share_denter()) == NULL)
+	if ((arg = smb_share_door_clnt_enter()) == NULL)
 		return (NERR_InternalError);
 
 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
@@ -444,29 +474,28 @@
 
 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
 	if (rc != 0) {
-		smb_share_dexit(arg, "encode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "encode");
 		return (NERR_InternalError);
 	}
 
-	if (door_call(smb_share_dfd, arg) < 0) {
-		smb_share_dexit(arg, "door call error");
-		smb_share_dclose();
+	if (smb_share_door_call(smb_share_dfd, arg) < 0) {
+		smb_share_door_clnt_exit(arg, B_TRUE, "door call");
 		return (NERR_InternalError);
 	}
 
 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
 	if (smb_share_dchk(dec_ctx) != 0) {
 		(void) smb_dr_decode_finish(dec_ctx);
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
 	rc = smb_dr_get_uint32(dec_ctx);
 	if (smb_dr_decode_finish(dec_ctx) != 0) {
-		smb_share_dexit(arg, "decode error");
+		smb_share_door_clnt_exit(arg, B_FALSE, "decode");
 		return (NERR_InternalError);
 	}
 
-	smb_share_dexit(arg, NULL);
+	smb_share_door_clnt_exit(arg, B_FALSE, NULL);
 	return (rc);
 }
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Sun Sep 14 17:28:06 2008 -0700
@@ -26,8 +26,6 @@
 #ifndef	_LIBMLSVC_H
 #define	_LIBMLSVC_H
 
-#pragma ident	"@(#)libmlsvc.h	1.7	08/08/05 SMI"
-
 #include <sys/types.h>
 #include <smbsrv/smb_sid.h>
 #include <smbsrv/hash_table.h>
@@ -35,12 +33,18 @@
 #include <smbsrv/smb_privilege.h>
 #include <smbsrv/smb_share.h>
 #include <smbsrv/libsmb.h>
+#include <smbsrv/smb_xdr.h>
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
+extern int mlsvc_get_door_fd(void);
+extern uint64_t mlsvc_get_num_users(void);
+extern int mlsvc_get_user_list(int, smb_dr_ulist_t *);
 extern int mlsvc_init(void);
+extern void mlsvc_set_door_fd(int);
+extern int mlsvc_set_share(int, char *, char *);
 extern uint32_t mlsvc_lookup_name(char *, smb_sid_t **, uint16_t *);
 extern uint32_t mlsvc_lookup_sid(smb_sid_t *, char **);
 extern DWORD mlsvc_netlogon(char *, char *);
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Sun Sep 14 17:28:06 2008 -0700
@@ -30,11 +30,16 @@
 	lsa_enum_trusted_domains;
 	lsa_query_account_domain_info;
 	lsa_query_primary_domain_info;
+	mlsvc_get_door_fd;
+	mlsvc_get_num_users;
+	mlsvc_get_user_list;
 	mlsvc_init;
 	mlsvc_join;
 	mlsvc_lookup_name;
 	mlsvc_lookup_sid;
 	mlsvc_netlogon;
+	mlsvc_set_door_fd;
+	mlsvc_set_share;
 	smb_autohome_add;
 	smb_autohome_remove;
 	smb_logon;
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,10 +23,17 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)mlsvc_init.c	1.5	08/07/22 SMI"
-
+#include <sys/errno.h>
+#include <stdlib.h>
 #include <unistd.h>
+#include <strings.h>
+#include <string.h>
+#include <rpc/xdr.h>
+#include <synch.h>
 #include <pthread.h>
+#include <smbsrv/smb_door_svc.h>
+#include <smbsrv/smb_common_door.h>
+#include <smbsrv/libsmb.h>
 #include <smbsrv/libmlsvc.h>
 
 void dssetup_initialize(void);
@@ -46,6 +53,14 @@
 #define	MLSVC_KEEPALIVE_INTERVAL	(10 * 60)	/* 10 minutes */
 
 /*
+ * Door fd for downcalls to the smbsrv kernel door service.
+ * smbsrv will make an upcall to smbd during initialization to
+ * provide this file descriptor.
+ */
+static int mlsvc_door_fd = -1;
+static mutex_t mlsvc_fd_mutex;
+
+/*
  * All mlrpc initialization is invoked from here.
  * Returns 0 upon success.  Otherwise, returns -1.
  */
@@ -94,3 +109,131 @@
 	/*NOTREACHED*/
 	return (NULL);
 }
+
+void
+mlsvc_set_door_fd(int fd)
+{
+	(void) mutex_lock(&mlsvc_fd_mutex);
+	mlsvc_door_fd = fd;
+	(void) mutex_unlock(&mlsvc_fd_mutex);
+}
+
+int
+mlsvc_get_door_fd(void)
+{
+	int fd;
+
+	(void) mutex_lock(&mlsvc_fd_mutex);
+	fd = mlsvc_door_fd;
+	(void) mutex_unlock(&mlsvc_fd_mutex);
+
+	return (fd);
+}
+
+uint64_t
+mlsvc_get_num_users(void)
+{
+	door_arg_t arg;
+	char *buf;
+	size_t len;
+	int64_t n_users = 0;
+	int fd;
+
+	if ((fd = mlsvc_get_door_fd()) < 0)
+		return (0);
+
+	if ((buf = smb_dr_set_opcode(SMB_KDR_USER_NUM, &len)) == NULL)
+		return (0);
+
+	smb_dr_clnt_setup(&arg, buf, len);
+
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+
+		if (smb_dr_decode_common(buf, len, xdr_uint32_t, &n_users) != 0)
+			n_users = 0;
+	}
+
+	smb_dr_clnt_cleanup(&arg);
+	return (n_users);
+}
+
+/*
+ * The calling function must free the output parameter 'users'.
+ */
+int
+mlsvc_get_user_list(int offset, smb_dr_ulist_t *users)
+{
+	door_arg_t arg;
+	char *buf;
+	size_t len;
+	uint_t opcode = SMB_KDR_USER_LIST;
+	int fd, rc = -1;
+
+	bzero(users, sizeof (smb_dr_ulist_t));
+
+	if ((fd = mlsvc_get_door_fd()) < 0)
+		return (-1);
+
+	buf = smb_dr_encode_common(opcode, &offset, xdr_uint32_t, &len);
+	if (buf == NULL)
+		return (-1);
+
+	smb_dr_clnt_setup(&arg, buf, len);
+
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+
+		rc = smb_dr_decode_common(buf, len, xdr_smb_dr_ulist_t, users);
+		if (rc == 0)
+			rc = users->dul_cnt;
+	}
+
+	smb_dr_clnt_cleanup(&arg);
+	return (rc);
+}
+
+/*
+ * Downcall to the kernel that is executed upon share enable and disable.
+ */
+int
+mlsvc_set_share(int shrop, char *path, char *sharename)
+{
+	door_arg_t arg;
+	char *buf;
+	size_t len;
+	smb_dr_kshare_t kshare;
+	int fd, rc = 0;
+
+	if ((shrop != SMB_SHROP_ADD) && (shrop != SMB_SHROP_DELETE))
+		return (EINVAL);
+
+	if ((fd = mlsvc_get_door_fd()) < 0)
+		return (EBADF);
+
+	kshare.k_op = shrop;
+	kshare.k_path = strdup(path);
+	kshare.k_sharename = strdup(sharename);
+
+	buf = smb_dr_encode_kshare(&kshare, &len);
+	free(kshare.k_path);
+	free(kshare.k_sharename);
+
+	if (buf == NULL)
+		return (ENOMEM);
+
+	smb_dr_clnt_setup(&arg, buf, len);
+
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+
+		if (smb_dr_decode_common(buf, len, xdr_int32_t, &rc) != 0)
+			rc = ENOMEM;
+	}
+
+	smb_dr_clnt_cleanup(&arg);
+	return (rc);
+}
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)mlsvc_srvsvc.c	1.8	08/08/07 SMI"
-
 /*
  * Server Service RPC (SRVSVC) server-side interface definition.
  * The server service provides a remote administration interface.
@@ -686,7 +684,7 @@
 	param->total_entries = 1;
 	param->status = ERROR_SUCCESS;
 
-	n_sessions = (DWORD) smb_dwncall_user_num();
+	n_sessions = (DWORD) mlsvc_get_num_users();
 
 	switch (param->level) {
 	case 0:
@@ -740,7 +738,7 @@
 		return (ERROR_NOT_ENOUGH_MEMORY);
 
 	for (total = 0, offset = 0;
-	    (cnt = smb_dwncall_get_users(offset, ulist)) > 0;
+	    (cnt = mlsvc_get_user_list(offset, ulist)) > 0;
 	    offset += cnt) {
 		for (i = 0; i < cnt && total < n_sessions; i++, total++) {
 			user = &ulist->dul_users[i];
@@ -811,7 +809,7 @@
 		return (ERROR_NOT_ENOUGH_MEMORY);
 
 	for (total = 0, offset = 0;
-	    (cnt = smb_dwncall_get_users(offset, ulist)) > 0;
+	    (cnt = mlsvc_get_user_list(offset, ulist)) > 0;
 	    offset += cnt) {
 		for (i = 0; i < cnt && total < n_sessions; i++, total++) {
 			user = &ulist->dul_users[i];
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)smb_share.c	1.7	08/08/07 SMI"
-
 /*
  * Lan Manager (SMB/CIFS) share interface implementation. This interface
  * returns Win32 error codes, usually network error values (lmerr.h).
@@ -50,6 +48,7 @@
 
 #include <smbsrv/libsmb.h>
 #include <smbsrv/libsmbns.h>
+#include <smbsrv/libmlsvc.h>
 
 #include <libshare.h>
 
@@ -265,7 +264,7 @@
 		}
 	}
 
-	rc = smb_dwncall_share(SMB_SHROP_ADD, si->shr_path, si->shr_name);
+	rc = mlsvc_set_share(SMB_SHROP_ADD, si->shr_path, si->shr_name);
 
 	if (rc == 0) {
 		smb_shr_publish(si->shr_name, si->shr_container,
@@ -317,7 +316,7 @@
 
 	smb_shr_cache_delent(si.shr_name);
 	smb_shr_publish(si.shr_name, si.shr_container, SMB_SHR_UNPUBLISH);
-	(void) smb_dwncall_share(SMB_SHROP_DELETE, si.shr_path, si.shr_name);
+	(void) mlsvc_set_share(SMB_SHROP_DELETE, si.shr_path, si.shr_name);
 
 	return (NERR_Success);
 }
@@ -822,8 +821,7 @@
 		if ((status = smb_shr_cache_addent(si)) != NERR_Success)
 			return (status);
 
-		rc = smb_dwncall_share(SMB_SHROP_ADD, si->shr_path,
-		    si->shr_name);
+		rc = mlsvc_set_share(SMB_SHROP_ADD, si->shr_path, si->shr_name);
 
 		if (rc != 0) {
 			smb_shr_cache_delent(si->shr_name);
--- a/usr/src/lib/smbsrv/libsmb/Makefile.com	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libsmb/Makefile.com	Sun Sep 14 17:28:06 2008 -0700
@@ -22,8 +22,6 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 LIBRARY= libsmb.a
 VERS= .1
@@ -54,7 +52,6 @@
 	smb_domain.o		\
 	smb_door_encdec.o	\
 	smb_doorclnt.o		\
-	smb_downcalls.o		\
 	smb_ht.o		\
 	smb_idmap.o		\
 	smb_info.o		\
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Sun Sep 14 17:28:06 2008 -0700
@@ -26,8 +26,6 @@
 #ifndef	_LIBSMB_H
 #define	_LIBSMB_H
 
-#pragma ident	"@(#)libsmb.h	1.12	08/07/30 SMI"
-
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -233,13 +231,6 @@
 extern bool_t xdr_smb_dr_domain_t(XDR *, smb_ntdomain_t *);
 
 /*
- * Following set of function, handle calls to SMB Kernel driver, via
- * Kernel doors interface.
- */
-extern uint64_t smb_dwncall_user_num(void);
-extern int smb_dwncall_share(int, char *, char *);
-
-/*
  * buffer context structure. This is used to keep track of the buffer
  * context.
  *
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Sun Sep 14 17:28:06 2008 -0700
@@ -113,6 +113,9 @@
 	smb_ctxbuf_init;
 	smb_ctxbuf_len;
 	smb_ctxbuf_printf;
+	smb_dr_clnt_call;
+	smb_dr_clnt_cleanup;
+	smb_dr_clnt_setup;
 	smb_dr_decode_arg_get_token;
 	smb_dr_decode_common;
 	smb_dr_decode_finish;
@@ -120,6 +123,7 @@
 	smb_dr_decode_string;
 	smb_dr_encode_common;
 	smb_dr_encode_finish;
+	smb_dr_encode_kshare;
 	smb_dr_encode_res_token;
 	smb_dr_encode_start;
 	smb_dr_encode_string;
@@ -151,10 +155,6 @@
 	smb_dr_set_opcode;
 	smb_dr_set_res_stat;
 	smb_dr_ulist_free;
-	smb_dwncall_get_users;
-	smb_dwncall_install_callback;
-	smb_dwncall_share;
-	smb_dwncall_user_num;
 	smb_get_dcinfo;
 	smb_get_nameservers;
 	smb_getdomaininfo;
--- a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,13 +23,12 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)smb_api_door_calls.c	1.6	08/07/16 SMI"
-
 /*
  * Door calls invoked by CLIs to obtain various SMB door service provided
  * by SMB daemon.
  */
 
+#include <fcntl.h>
 #include <syslog.h>
 #include <string.h>
 #include <strings.h>
@@ -41,20 +40,6 @@
 #include <smbsrv/smb_door_svc.h>
 #include <smbsrv/smb_common_door.h>
 
-/* indexed via opcode (smb_dr_opcode_t) */
-char *smbapi_desc[] = {
-	"",
-	"",
-	"",
-	"",
-	"SmbapiUserList",
-	"SmbLookupSid",
-	"SmbLookupName",
-	"SmbJoin",
-	"SmbGetDCInfo",
-	0
-};
-
 /*
  * This function will return information on the connected users
  * starting at the given offset.
@@ -69,28 +54,33 @@
 int
 smb_api_ulist(int offset, smb_dr_ulist_t *users)
 {
-	char *buf, *rbufp;
-	size_t buflen, rbufsize;
+	door_arg_t arg;
+	char *buf;
+	size_t len;
 	int rc = -1;
 	uint_t opcode = SMB_DR_USER_LIST;
 	int fd;
 
 	bzero(users, sizeof (smb_dr_ulist_t));
-	buf = smb_dr_encode_common(opcode, &offset, xdr_uint32_t, &buflen);
-	if (!buf)
-		return (-1);
 
-	if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1)
+	if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
 		return (-1);
 
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smbapi_desc[opcode]);
-	if (rbufp) {
-		rc = smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET, xdr_smb_dr_ulist_t, users);
+	buf = smb_dr_encode_common(opcode, &offset, xdr_uint32_t, &len);
+	if (buf == NULL) {
+		(void) close(fd);
+		return (-1);
+	}
+
+	smb_dr_clnt_setup(&arg, buf, len);
 
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+		rc = smb_dr_decode_common(buf, len, xdr_smb_dr_ulist_t, users);
 	}
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
+
+	smb_dr_clnt_cleanup(&arg);
 	(void) close(fd);
 	return (rc);
 }
@@ -109,8 +99,9 @@
 int
 smb_lookup_sid(smb_sid_t *sid, char *namebuf, int namebuflen)
 {
-	char *buf, *rbufp;
-	size_t buflen, rbufsize;
+	door_arg_t arg;
+	char *buf;
+	size_t len;
 	int opcode = SMB_DR_LOOKUP_SID;
 	char *name = NULL;
 	int fd;
@@ -122,28 +113,26 @@
 
 	smb_sid_tostr(sid, namebuf);
 
-	if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) {
+	if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) {
 		/* returning string SID */
 		return (NT_STATUS_SUCCESS);
 	}
 
-	/* Encode */
-	if ((buf = smb_dr_encode_string(opcode, namebuf, &buflen)) == 0) {
+	if ((buf = smb_dr_encode_string(opcode, namebuf, &len)) == 0) {
 		/* returning string SID */
 		(void) close(fd);
 		return (NT_STATUS_SUCCESS);
 	}
 
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smbapi_desc[opcode]);
+	smb_dr_clnt_setup(&arg, buf, len);
 
-	/* Decode Result. */
-	if (rbufp) {
-		name = smb_dr_decode_string(rbufp + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET);
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+		name = smb_dr_decode_string(buf, len);
 	}
 
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
+	smb_dr_clnt_cleanup(&arg);
 	(void) close(fd);
 
 	if (name) {
@@ -166,8 +155,9 @@
 int
 smb_lookup_name(char *name, smb_gsid_t *sid)
 {
-	char *buf, *rbufp;
-	size_t buflen, rbufsize;
+	door_arg_t arg;
+	char *buf;
+	size_t len;
 	int opcode = SMB_DR_LOOKUP_NAME;
 	char *strsid = NULL;
 	char *p;
@@ -178,32 +168,28 @@
 	if (*name == '\0')
 		return (NT_STATUS_NONE_MAPPED);
 
-	if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1)
+	if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
 		return (NT_STATUS_INTERNAL_ERROR);
 
-	/* Encode */
-	if ((buf = smb_dr_encode_string(opcode, name, &buflen)) == 0) {
+	if ((buf = smb_dr_encode_string(opcode, name, &len)) == 0) {
 		(void) close(fd);
 		return (NT_STATUS_INTERNAL_ERROR);
 	}
 
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smbapi_desc[opcode]);
+	smb_dr_clnt_setup(&arg, buf, len);
 
-	/* Decode Result. */
-	if (rbufp) {
-		strsid = smb_dr_decode_string(rbufp + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET);
-		if (strsid == NULL) {
-			smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
-			(void) close(fd);
-			return (NT_STATUS_INTERNAL_ERROR);
-		}
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+		strsid = smb_dr_decode_string(buf, len);
 	}
 
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
+	smb_dr_clnt_cleanup(&arg);
 	(void) close(fd);
 
+	if (strsid == NULL)
+		return (NT_STATUS_INTERNAL_ERROR);
+
 	p = strchr(strsid, '-');
 	if (p == NULL) {
 		xdr_free(xdr_string, (char *)&strsid);
@@ -220,38 +206,38 @@
 uint32_t
 smb_join(smb_joininfo_t *jdi)
 {
-	char *buf, *rbufp;
-	size_t buflen, rbufsize;
+	door_arg_t arg;
+	char *buf;
+	size_t len;
 	int opcode = SMB_DR_JOIN;
 	uint32_t status;
 	int fd, rc;
 
-	if (jdi == NULL) {
-		syslog(LOG_ERR, "%s: invalid parameter", smbapi_desc[opcode]);
+	if (jdi == NULL)
 		return (NT_STATUS_INVALID_PARAMETER);
-	}
 
-	buf = smb_dr_encode_common(opcode, jdi, xdr_smb_dr_joininfo_t, &buflen);
-	if (buf == NULL)
+	if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
 		return (NT_STATUS_INTERNAL_ERROR);
 
-	if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) {
-		free(buf);
+	buf = smb_dr_encode_common(opcode, jdi, xdr_smb_dr_joininfo_t, &len);
+	if (buf == NULL) {
+		(void) close(fd);
 		return (NT_STATUS_INTERNAL_ERROR);
 	}
 
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smbapi_desc[opcode]);
-	if (rbufp) {
-		rc = smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &status);
+	smb_dr_clnt_setup(&arg, buf, len);
+
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+		rc = smb_dr_decode_common(buf, len, xdr_uint32_t, &status);
 		if (rc != 0)
 			status = NT_STATUS_INTERNAL_ERROR;
 	} else {
 		status = NT_STATUS_INTERNAL_ERROR;
 	}
 
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
+	smb_dr_clnt_cleanup(&arg);
 	(void) close(fd);
 	return (status);
 }
@@ -265,31 +251,33 @@
 uint32_t
 smb_get_dcinfo(smb_ntdomain_t *dc_info)
 {
-	char *buf = NULL, *rbufp;
-	size_t buflen, rbufsize;
+	door_arg_t arg;
+	char *buf;
+	size_t len;
 	int opcode = SMB_DR_GET_DCINFO;
 	int fd, rc = NT_STATUS_SUCCESS;
 
-	if ((buf = smb_dr_set_opcode(opcode, &buflen)) == NULL)
+	if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
 		return (NT_STATUS_INTERNAL_ERROR);
 
-	if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME,
-	    smbapi_desc[opcode]) == -1) {
-		free(buf);
+	if ((buf = smb_dr_set_opcode(opcode, &len)) == NULL) {
+		(void) close(fd);
 		return (NT_STATUS_INTERNAL_ERROR);
 	}
 
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smbapi_desc[opcode]);
-	if (rbufp) {
-		if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET, xdr_smb_dr_domain_t,
-		    dc_info) != NULL)
+	smb_dr_clnt_setup(&arg, buf, len);
+
+	if (smb_dr_clnt_call(fd, &arg) == 0) {
+		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
+		len = arg.rsize - SMB_DR_DATA_OFFSET;
+		rc = smb_dr_decode_common(buf, len, xdr_smb_dr_domain_t,
+		    dc_info);
+		if (rc != 0)
 			rc = NT_STATUS_INTERNAL_ERROR;
 	}
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
+
+	smb_dr_clnt_cleanup(&arg);
 	(void) close(fd);
-
 	return (rc);
 }
 
--- a/usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <stdlib.h>
 #include <strings.h>
 #include <rpc/xdr.h>
@@ -46,15 +44,13 @@
 	XDR xdrs;
 	int rc = 0;
 
-	if (!data) {
-		syslog(LOG_ERR, "smb_dr_decode_common: invalid param");
+	if (!data)
 		return (-1);
-	}
 
 	xdrmem_create(&xdrs, buf, len, XDR_DECODE);
-	if (!proc(&xdrs, data)) {
+	if (!proc(&xdrs, data))
 		rc = -1;
-	}
+
 	xdr_destroy(&xdrs);
 	return (rc);
 }
@@ -144,10 +140,12 @@
 int
 smb_dr_get_res_stat(char *rbufp, size_t rbuf_size)
 {
-	int stat;
-	if (smb_dr_decode_common(rbufp, rbuf_size, xdr_uint32_t, &stat) != 0)
-		stat = -1;
-	return (stat);
+	int status;
+
+	if (smb_dr_decode_common(rbufp, rbuf_size, xdr_uint32_t, &status) != 0)
+		status = -1;
+
+	return (status);
 }
 
 /*
@@ -194,10 +192,6 @@
 	char *buf = NULL;
 
 	res.bytes_val = smb_kshare_mkselfrel(kshare, &res.bytes_len);
-
-	free(kshare->k_path);
-	free(kshare->k_sharename);
-
 	if (!res.bytes_val)
 		return (NULL);
 
@@ -205,7 +199,6 @@
 	    buflen);
 
 	free(res.bytes_val);
-
 	return (buf);
 }
 
--- a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c	Sun Sep 14 17:28:06 2008 -0700
@@ -19,17 +19,14 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * User-space door client routines for both SMB daemon and CLIs.
  */
 
-#include <fcntl.h>
 #include <syslog.h>
 #include <door.h>
 #include <string.h>
@@ -42,107 +39,76 @@
 #include <smbsrv/smb_door_svc.h>
 #include <smbsrv/smb_common_door.h>
 
-/*
- * Returns 0 on success. Otherwise, -1.
- */
-int
-smb_dr_clnt_open(int *fd, char *path, char *op_desc)
+#define	SMB_DOOR_CALL_RETRIES		3
+
+void
+smb_dr_clnt_setup(door_arg_t *arg, char *buf, size_t buflen)
 {
-	int rc = 0;
-
-	if (!op_desc)
-		op_desc = "unknown operation";
+	arg->data_ptr = buf;
+	arg->data_size = buflen;
+	arg->desc_ptr = NULL;
+	arg->desc_num = 0;
+	arg->rbuf = buf;
+	arg->rsize = buflen;
+}
 
-	if (!path || !fd)
-		return (-1);
+/*
+ * Free resources allocated for a door call.  If the result buffer provided
+ * by the client is too small, the doorfs will have allocated a new buffer,
+ * which must be unmapped here.
+ *
+ * This function must be called to free both the argument and result door
+ * buffers regardless of the status of the door call.
+ */
+void
+smb_dr_clnt_cleanup(door_arg_t *arg)
+{
+	if (arg->rbuf && (arg->rbuf != arg->data_ptr))
+		(void) munmap(arg->rbuf, arg->rsize);
 
-	if ((*fd = open(path, O_RDONLY)) < 0) {
-		syslog(LOG_ERR, "%s: open %s failed %s", op_desc,
-		    path, strerror(errno));
-		rc = -1;
-	}
-
-	return (rc);
+	free(arg->data_ptr);
 }
 
 /*
- * smb_dr_clnt_call
+ * Make a door call to the server function associated with the door
+ * descriptor fd.
+ *
+ * After a successful door call the local door_arg->data_ptr is assigned
+ * to the caller's arg->rbuf so that arg has references to both input and
+ * response buffers, which is required by smb_dr_clnt_free.
  *
- * This function will make a door call to the server function
- * associated with the door descriptor fd. The specified door
- * request buffer (i.e. argp) will be passed as the argument to the
- * door_call(). Upon success, the result buffer is returned. Otherwise,
- * NULL pointer is returned. The size of the result buffer is returned
- * via rbufsize.
+ * On success, 0 will be returned and the call results can be referenced
+ * via arg->rbuf and arg->rsize.  Otherwise -1 will be returned.
  */
-char *
-smb_dr_clnt_call(int fd, char *argp, size_t arg_size, size_t *rbufsize,
-    char *op_desc)
+int
+smb_dr_clnt_call(int fd, door_arg_t *arg)
 {
-	door_arg_t arg;
+	door_arg_t door_arg;
+	int rc;
+	int i;
 
-	if (!argp) {
-		syslog(LOG_ERR, "smb_dr_clnt_call: invalid parameter");
-		return (NULL);
-	}
+	if (fd < 0 || arg == NULL)
+		return (-1);
+
+	bcopy(arg, &door_arg, sizeof (door_arg_t));
 
-	arg.data_ptr = argp;
-	arg.data_size = arg_size;
-	arg.desc_ptr = NULL;
-	arg.desc_num = 0;
-	arg.rbuf = argp;
-	arg.rsize = arg_size;
+	for (i = 0; i < SMB_DOOR_CALL_RETRIES; ++i) {
+		errno = 0;
 
-	if (!op_desc)
-		op_desc = "unknown operation";
+		if ((rc = door_call(fd, &door_arg)) == 0)
+			break;
 
-	if (door_call(fd, &arg) < 0) {
-		syslog(LOG_ERR, "%s: Door call failed %s", op_desc,
-		    strerror(errno));
-		free(argp);
-		argp = NULL;
-		return (NULL);
+		if (errno != EAGAIN && errno != EINTR)
+			return (-1);
 	}
 
-	if (smb_dr_get_res_stat(arg.data_ptr, arg.rsize)
-	    != SMB_DR_OP_SUCCESS) {
-		smb_dr_clnt_free(argp, arg_size, arg.rbuf, arg.rsize);
-		*rbufsize = 0;
-		return (NULL);
-	}
-	*rbufsize = arg.rsize;
-	return (arg.data_ptr);
-}
+	if (rc != 0)
+		return (-1);
 
-/*
- * smb_dr_clnt_free
- *
- * This function should be invoked to free both the argument/result door buffer
- * regardless of the status of the door call.
- *
- * The doorfs allocates a new buffer if the result buffer passed by the client
- * is too small. This function will munmap if that happens.
- */
-/*ARGSUSED*/
-void
-smb_dr_clnt_free(char *argp, size_t arg_size, char *rbufp, size_t rbuf_size)
-{
-	if (argp) {
-		if (argp == rbufp) {
-			free(argp);
-			argp = NULL;
-		} else if (rbufp) {
-			free(argp);
-			argp = NULL;
-			if (munmap(rbufp, rbuf_size) != 0) {
-				syslog(LOG_ERR, "munmap failed");
-			}
-		}
-	} else {
-		if (rbufp) {
-			if (munmap(rbufp, rbuf_size) != 0) {
-				syslog(LOG_ERR, "munmap failed");
-			}
-		}
-	}
+	if ((rc = smb_dr_get_res_stat(door_arg.data_ptr, door_arg.rsize)) != 0)
+		rc = -1;
+
+	arg->rbuf = door_arg.data_ptr;
+	arg->rsize = door_arg.rsize;
+	return (rc);
 }
--- a/usr/src/lib/smbsrv/libsmb/common/smb_downcalls.c	Sat Sep 13 23:17:18 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"@(#)smb_downcalls.c	1.3	08/08/05 SMI"
-
-/*
- * Down calls to SMB Kmod for obtaining various kernel door services.
- */
-
-#include <syslog.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <string.h>
-#include <rpc/xdr.h>
-#include <sys/errno.h>
-#include <smbsrv/smb_door_svc.h>
-#include <smbsrv/smb_common_door.h>
-#include <smbsrv/libsmb.h>
-
-/* indexed via opcode (smb_kdr_opcode_t) */
-char *smb_dwncall_info[] = {
-	"SmbDwncallNumUser",
-	"SmbDwncallUserList",
-	"SmbDwncallShare",
-	0
-};
-
-static smb_dwncall_get_desc_t get_dwncall_desc;
-
-int
-smb_dwncall_install_callback(smb_dwncall_get_desc_t get_desc_cb)
-{
-	if (!get_desc_cb)
-		return (-1);
-
-	get_dwncall_desc = get_desc_cb;
-	return (0);
-}
-
-static int
-smb_dwncall_init_fd(uint_t opcode)
-{
-	int fd;
-
-	if (!get_dwncall_desc) {
-		syslog(LOG_DEBUG, "%s: failed (unable to get fd)",
-		    smb_dwncall_info[opcode]);
-		return (-1);
-	}
-
-	if ((fd = get_dwncall_desc()) == -1) {
-		syslog(LOG_ERR, "%s: failed (invalid fd)",
-		    smb_dwncall_info[opcode]);
-		return (-1);
-	}
-
-	return (fd);
-}
-
-uint64_t
-smb_dwncall_user_num()
-{
-	char *buf, *rbufp;
-	size_t buflen, rbufsize;
-	int64_t num;
-	uint_t opcode = SMB_KDR_USER_NUM;
-	int fd;
-
-	if ((fd = smb_dwncall_init_fd(opcode)) < 0)
-		return (0);
-
-	buf = smb_dr_set_opcode(opcode, &buflen);
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smb_dwncall_info[opcode]);
-	if (rbufp) {
-		if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &num) != 0) {
-			num = -1;
-		}
-	}
-
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
-	return (num);
-}
-
-/*
- * smb_dwncall_get_users
- *
- * The calling function must free the output parameter 'users'.
- */
-int
-smb_dwncall_get_users(int offset, smb_dr_ulist_t *users)
-{
-	char *buf = NULL, *rbufp;
-	size_t buflen, rbufsize;
-	uint_t opcode = SMB_KDR_USER_LIST;
-	int fd, rc = -1;
-
-	bzero(users, sizeof (smb_dr_ulist_t));
-	if ((fd = smb_dwncall_init_fd(opcode)) < 0)
-		return (-1);
-
-	buf = smb_dr_encode_common(opcode, &offset, xdr_uint32_t, &buflen);
-	if (!buf) {
-		syslog(LOG_ERR, "smb_dwncall_get_users: encode error");
-		return (-1);
-	}
-
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smb_dwncall_info[opcode]);
-
-
-	if (rbufp) {
-		rc = smb_dr_decode_common(rbufp  + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET, xdr_smb_dr_ulist_t, users);
-		if (rc)
-			syslog(LOG_ERR, "smb_dwncall_get_users: decode error");
-		else
-			rc = users->dul_cnt;
-	}
-
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
-	return (rc);
-}
-
-/*
- * smb_dwncall_share()
- *
- * This is a downcall to the kernel that is executed
- * upon share enable and disable.
- */
-
-int
-smb_dwncall_share(int op, char *path, char *sharename)
-{
-	char *buf = NULL, *rbufp;
-	size_t buflen, rbufsize;
-	int32_t opcode = SMB_KDR_SHARE;
-	smb_dr_kshare_t kshare;
-	int fd, rc = 0;
-
-	if ((op != SMB_SHROP_ADD) &&
-	    (op != SMB_SHROP_DELETE))
-		return (EINVAL);
-
-	if ((fd = smb_dwncall_init_fd(opcode)) < 0) {
-		syslog(LOG_ERR, "smb_dwncall_share: init error");
-		return (EBADF);
-	}
-
-	kshare.k_op = op;
-	kshare.k_path = strdup(path);
-	kshare.k_sharename = strdup(sharename);
-
-	buf = smb_dr_encode_kshare(&kshare, &buflen);
-
-	if (!buf) {
-		syslog(LOG_ERR, "smb_dwncall_share: encode error");
-		return (ENOMEM);
-	}
-
-	rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize,
-	    smb_dwncall_info[opcode]);
-
-	if (rbufp) {
-		if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET,
-		    rbufsize - SMB_DR_DATA_OFFSET, xdr_int32_t, &rc) != 0) {
-			rc = ENOMEM;
-		}
-	}
-
-	smb_dr_clnt_free(buf, buflen, rbufp, rbufsize);
-	return (rc);
-}
--- a/usr/src/uts/common/fs/smbsrv/smb_kdoor_clnt.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_kdoor_clnt.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/kmem.h>
 #include <sys/ddi.h>
@@ -34,7 +32,149 @@
 #include <smbsrv/smb_door_svc.h>
 #include <smbsrv/smb_common_door.h>
 
-door_handle_t smb_kdoor_clnt_dh = NULL;
+#define	SMB_KDOOR_RETRIES	3
+
+static char *smb_kdoor_upcall(char *, size_t, door_desc_t *, uint_t, size_t *);
+
+door_handle_t smb_kdoor_clnt_hd = NULL;
+static int smb_kdoor_clnt_id = -1;
+static uint64_t smb_kdoor_clnt_ncall = 0;
+static kmutex_t smb_kdoor_clnt_mutex;
+static kcondvar_t smb_kdoor_clnt_cv;
+
+void
+smb_kdoor_clnt_init(void)
+{
+	mutex_init(&smb_kdoor_clnt_mutex, NULL, MUTEX_DEFAULT, NULL);
+	cv_init(&smb_kdoor_clnt_cv, NULL, CV_DEFAULT, NULL);
+}
+
+void
+smb_kdoor_clnt_fini(void)
+{
+	smb_kdoor_clnt_close();
+	cv_destroy(&smb_kdoor_clnt_cv);
+	mutex_destroy(&smb_kdoor_clnt_mutex);
+}
+
+/*
+ * Open the door.  If the door is already open, close it first
+ * because the door-id has probably changed.
+ */
+int
+smb_kdoor_clnt_open(int door_id)
+{
+	int rc;
+
+	smb_kdoor_clnt_close();
+
+	mutex_enter(&smb_kdoor_clnt_mutex);
+	smb_kdoor_clnt_ncall = 0;
+
+	if (smb_kdoor_clnt_hd == NULL) {
+		smb_kdoor_clnt_id = door_id;
+		smb_kdoor_clnt_hd = door_ki_lookup(door_id);
+	}
+
+	rc = (smb_kdoor_clnt_hd == NULL)  ? -1 : 0;
+	mutex_exit(&smb_kdoor_clnt_mutex);
+	return (rc);
+}
+
+/*
+ * Close the door.
+ */
+void
+smb_kdoor_clnt_close(void)
+{
+	mutex_enter(&smb_kdoor_clnt_mutex);
+
+	if (smb_kdoor_clnt_hd != NULL) {
+		while (smb_kdoor_clnt_ncall > 0)
+			cv_wait(&smb_kdoor_clnt_cv, &smb_kdoor_clnt_mutex);
+
+		door_ki_rele(smb_kdoor_clnt_hd);
+		smb_kdoor_clnt_hd = NULL;
+	}
+
+	mutex_exit(&smb_kdoor_clnt_mutex);
+}
+
+/*
+ * smb_kdoor_clnt_upcall
+ *
+ * Wrapper to handle door call reference counting.
+ */
+char *
+smb_kdoor_clnt_upcall(char *argp, size_t arg_size, door_desc_t *dp,
+    uint_t desc_num, size_t *rbufsize)
+{
+	char *rbufp;
+
+	if (argp == NULL)
+		return (NULL);
+
+	mutex_enter(&smb_kdoor_clnt_mutex);
+
+	if (smb_kdoor_clnt_hd == NULL) {
+		mutex_exit(&smb_kdoor_clnt_mutex);
+
+		if (smb_kdoor_clnt_open(smb_kdoor_clnt_id) != 0)
+			return (NULL);
+
+		mutex_enter(&smb_kdoor_clnt_mutex);
+	}
+
+	++smb_kdoor_clnt_ncall;
+	mutex_exit(&smb_kdoor_clnt_mutex);
+
+	rbufp = smb_kdoor_upcall(argp, arg_size, dp, desc_num, rbufsize);
+
+	mutex_enter(&smb_kdoor_clnt_mutex);
+	--smb_kdoor_clnt_ncall;
+	cv_signal(&smb_kdoor_clnt_cv);
+	mutex_exit(&smb_kdoor_clnt_mutex);
+	return (rbufp);
+}
+
+/*
+ * On success, the result buffer is returned, with rbufsize set to the
+ * size of the result buffer.  Otherwise, a NULL pointer is returned.
+ */
+static char *
+smb_kdoor_upcall(char *argp, size_t arg_size, door_desc_t *dp,
+    uint_t desc_num, size_t *rbufsize)
+{
+	door_arg_t door_arg;
+	int i;
+	int rc;
+
+	door_arg.data_ptr = argp;
+	door_arg.data_size = arg_size;
+	door_arg.desc_ptr = dp;
+	door_arg.desc_num = desc_num;
+	door_arg.rbuf = argp;
+	door_arg.rsize = arg_size;
+
+	for (i = 0; i < SMB_KDOOR_RETRIES; ++i) {
+		if ((rc = door_ki_upcall_limited(smb_kdoor_clnt_hd, &door_arg,
+		    NULL, SIZE_MAX, 0)) == 0)
+			break;
+
+		if (rc != EAGAIN && rc != EINTR)
+			return (NULL);
+	}
+
+	if (rc != 0)
+		return (NULL);
+
+	rc = smb_dr_get_res_stat(door_arg.data_ptr, door_arg.rsize);
+	if (rc != SMB_DR_OP_SUCCESS)
+		return (NULL);
+
+	*rbufsize = door_arg.rsize;
+	return (door_arg.data_ptr);
+}
 
 /*
  * smb_kdoor_clnt_free
@@ -48,99 +188,9 @@
 void
 smb_kdoor_clnt_free(char *argp, size_t arg_size, char *rbufp, size_t rbuf_size)
 {
-	if (argp) {
-		if (argp == rbufp) {
-			kmem_free(argp, arg_size);
-		} else if (rbufp) {
-			kmem_free(argp, arg_size);
-			kmem_free(rbufp, rbuf_size);
-		}
-	} else {
-		if (rbufp)
-			kmem_free(rbufp, rbuf_size);
-	}
-}
-
-/*
- * smb_kdoor_clnt_start
- *
- * The SMB kernel module should invoke this function upon startup.
- */
-int
-smb_kdoor_clnt_start(int door_id)
-{
-	int	rc = 0;
-
-	if (smb_kdoor_clnt_dh == NULL) {
-		smb_kdoor_clnt_dh = door_ki_lookup(door_id);
-		if (smb_kdoor_clnt_dh == NULL) {
-			cmn_err(CE_WARN, "kdoor_clnt: lookup failed");
-			rc = -1;
-		}
-	}
-
-	return (rc);
-}
-
-/*
- * smb_kdoor_clnt_stop
- *
- * The SMB kernel module should invoke this function upon unload.
- */
-void
-smb_kdoor_clnt_stop()
-{
-	if (smb_kdoor_clnt_dh) {
-		door_ki_rele(smb_kdoor_clnt_dh);
-		smb_kdoor_clnt_dh = NULL;
-	}
-}
+	if (argp)
+		kmem_free(argp, arg_size);
 
-/*
- * smb_kdoor_clnt_upcall
- *
- * This function will make a door up-call to the server function
- * associated with the door descriptor fp. The specified door
- * request buffer (i.e. argp) will be passed as the argument to the
- * door_ki_upcall(). Upon success, the result buffer is returned. Otherwise,
- * NULL pointer is returned. The size of the result buffer is returned
- * via rbufsize.
- */
-char *
-smb_kdoor_clnt_upcall(char *argp, size_t arg_size, door_desc_t *dp,
-    uint_t desc_num, size_t *rbufsize)
-{
-	door_arg_t door_arg;
-	int err;
-
-	if (!argp) {
-		cmn_err(CE_WARN, "smb_kdoor_clnt_upcall: invalid parameter");
-		return (NULL);
-	}
-
-	door_arg.data_ptr = argp;
-	door_arg.data_size = arg_size;
-	door_arg.desc_ptr = dp;
-	door_arg.desc_num = desc_num;
-	door_arg.rbuf = argp;
-	door_arg.rsize = arg_size;
-
-	if ((err = door_ki_upcall_limited(smb_kdoor_clnt_dh, &door_arg, NULL,
-	    SIZE_MAX, 0)) != 0) {
-		cmn_err(CE_WARN, "smb_kdoor_clnt_upcall: failed(%d)", err);
-		kmem_free(argp, arg_size);
-		argp = NULL;
-		return (NULL);
-	}
-
-	if (smb_dr_get_res_stat(door_arg.data_ptr, door_arg.rsize) !=
-	    SMB_DR_OP_SUCCESS) {
-		smb_kdoor_clnt_free(argp, arg_size, door_arg.rbuf,
-		    door_arg.rsize);
-		*rbufsize = 0;
-		return (NULL);
-	}
-	*rbufsize = door_arg.rsize;
-	return (door_arg.data_ptr);
-
+	if (rbufp && rbufp != argp)
+		kmem_free(rbufp, rbuf_size);
 }
--- a/usr/src/uts/common/fs/smbsrv/smb_kdoor_srv.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_kdoor_srv.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Kernel door service
  * It has dependency on the kernel door client interface because the downcall
@@ -79,31 +77,24 @@
 }
 
 /*
- * smb_kdoor_srv_set_dwncall
+ * smb_kdoor_srv_set_downcall
  *
  * The door descriptor will be passed up to the user-space SMB daemon.
  */
 int
-smb_kdoor_srv_set_dwncall(void)
+smb_kdoor_srv_set_downcall(void)
 {
 	door_desc_t	smb_kdoor_desc;
-	int		rc;
 
 	bzero(&smb_kdoor_desc, sizeof (smb_kdoor_desc));
 
 	smb_kdoor_desc.d_attributes = DOOR_HANDLE;
 	smb_kdoor_desc.d_data.d_handle = smb_kdoor_hdl;
 
-	rc = smb_upcall_set_dwncall_desc(SMB_DR_SET_DWNCALL_DESC,
-	    &smb_kdoor_desc, 1);
+	if (smb_set_downcall_desc(&smb_kdoor_desc, 1) != 0)
+		return (EIO);
 
-	if (rc != SMB_DR_OP_SUCCESS) {
-		cmn_err(CE_WARN, "SmbKdoorInit: smbd failed to set the"
-		    " downcall descriptor res=%d", rc);
-		rc = EIO;
-	}
-
-	return (rc);
+	return (0);
 }
 
 door_handle_t
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c	Sun Sep 14 17:28:06 2008 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)smb_server.c	1.10	08/08/07 SMI"
-
 /*
  * General Structures Layout
  * -------------------------
@@ -378,6 +376,7 @@
 
 	sv->sv_pid = curproc->p_pid;
 
+	smb_kdoor_clnt_init();
 	smb_opipe_door_init();
 	(void) smb_server_kstat_init(sv);
 
@@ -458,6 +457,7 @@
 	smb_server_stop(sv);
 	rw_destroy(&sv->sv_cfg_lock);
 	smb_opipe_door_fini();
+	smb_kdoor_clnt_fini();
 	smb_server_kstat_fini(sv);
 	smb_llist_destructor(&sv->sv_vfs_list);
 	kmem_cache_destroy(sv->si_cache_vfs);
@@ -469,7 +469,6 @@
 	kmem_cache_destroy(sv->si_cache_odir);
 	kmem_cache_destroy(sv->si_cache_node);
 
-	taskq_destroy(sv->sv_thread_pool);
 	smb_thread_destroy(&sv->si_thread_timers);
 	mutex_destroy(&sv->sv_mutex);
 	cv_destroy(&sv->sv_cv);
@@ -544,7 +543,8 @@
 		    TASKQ_DYNAMIC|TASKQ_PREPOPULATE);
 
 		sv->sv_session = smb_session_create(NULL, 0, sv);
-		if (sv->sv_session == NULL) {
+
+		if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) {
 			rc = ENOMEM;
 			break;
 		}
@@ -555,10 +555,12 @@
 		sv->sv_lmshrd = smb_kshare_init(io_start->lmshrd);
 		if (sv->sv_lmshrd == NULL)
 			break;
-		if (rc = smb_kdoor_clnt_start(io_start->udoor))
+		if (rc = smb_kdoor_clnt_open(io_start->udoor))
 			break;
-		if (rc = smb_kdoor_srv_set_dwncall())
+		if (rc = smb_kdoor_srv_set_downcall()) {
+			cmn_err(CE_WARN, "Cannot set downcall descriptor");
 			break;
+		}
 		if (rc = smb_thread_start(&sv->si_thread_timers))
 			break;
 		/*
@@ -1173,14 +1175,20 @@
 
 	smb_opipe_door_close();
 	smb_thread_stop(&sv->si_thread_timers);
-	smb_kdoor_clnt_stop();
+	smb_kdoor_clnt_close();
 	smb_kshare_fini(sv->sv_lmshrd);
 	sv->sv_lmshrd = NULL;
 	smb_server_fsop_stop(sv);
+
 	if (sv->sv_session) {
 		smb_session_delete(sv->sv_session);
 		sv->sv_session = NULL;
 	}
+
+	if (sv->sv_thread_pool) {
+		taskq_destroy(sv->sv_thread_pool);
+		sv->sv_thread_pool = NULL;
+	}
 }
 
 static int
--- a/usr/src/uts/common/fs/smbsrv/smb_upcalls.c	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_upcalls.c	Sun Sep 14 17:28:06 2008 -0700
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
 #include <sys/cmn_err.h>
@@ -67,38 +65,36 @@
 smb_token_t *
 smb_upcall_get_token(netr_client_t *clnt_info)
 {
-	char *argp, *rbufp;
-	size_t arg_size, rbuf_size;
+	char *arg, *rsp;
+	size_t arg_size, rsp_size;
 	smb_token_t *token = NULL;
 
-	argp = smb_dr_encode_arg_get_token(clnt_info, &arg_size);
-	rbufp = smb_kdoor_clnt_upcall(argp, arg_size, NULL, 0, &rbuf_size);
-	if (rbufp)
-		token = smb_dr_decode_res_token(rbufp + SMB_DR_DATA_OFFSET,
-		    rbuf_size - SMB_DR_DATA_OFFSET);
+	if ((arg = smb_dr_encode_arg_get_token(clnt_info, &arg_size)) == NULL)
+		return (NULL);
 
-	smb_kdoor_clnt_free(argp, arg_size, rbufp, rbuf_size);
+	rsp = smb_kdoor_clnt_upcall(arg, arg_size, NULL, 0, &rsp_size);
+	if (rsp) {
+		token = smb_dr_decode_res_token(rsp + SMB_DR_DATA_OFFSET,
+		    rsp_size - SMB_DR_DATA_OFFSET);
+	}
+
+	smb_kdoor_clnt_free(arg, arg_size, rsp, rsp_size);
 	return (token);
 
 }
 
 int
-smb_upcall_set_dwncall_desc(uint32_t opcode, door_desc_t *dp, uint_t n_desc)
+smb_set_downcall_desc(door_desc_t *dp, uint_t n_desc)
 {
-	char *argp, *rbufp;
-	size_t arg_size, rbuf_size;
-
-	argp = smb_dr_set_opcode(opcode, &arg_size);
-	if (argp == NULL) {
-		return (SMB_DR_OP_ERR_ENCODE);
-	}
+	char *arg, *rsp;
+	size_t arg_size, rsp_size;
 
-	rbufp = smb_kdoor_clnt_upcall(argp, arg_size, dp, n_desc, &rbuf_size);
-	if (rbufp == NULL) {
-		return (SMB_DR_OP_ERR);
-	}
+	arg = smb_dr_set_opcode(SMB_DR_SET_DWNCALL_DESC, &arg_size);
+	if (arg == NULL)
+		return (-1);
 
-	smb_kdoor_clnt_free(argp, arg_size, rbufp, rbuf_size);
+	rsp = smb_kdoor_clnt_upcall(arg, arg_size, dp, n_desc, &rsp_size);
 
-	return (SMB_DR_OP_SUCCESS);
+	smb_kdoor_clnt_free(arg, arg_size, rsp, rsp_size);
+	return ((rsp == NULL) ? -1 : 0);
 }
--- a/usr/src/uts/common/smbsrv/smb_door_svc.h	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/uts/common/smbsrv/smb_door_svc.h	Sun Sep 14 17:28:06 2008 -0700
@@ -26,8 +26,6 @@
 #ifndef	_SMBSRV_SMB_DOOR_SVC_H
 #define	_SMBSRV_SMB_DOOR_SVC_H
 
-#pragma ident	"@(#)smb_door_svc.h	1.5	08/07/16 SMI"
-
 #include <sys/door.h>
 #include <smbsrv/smb_token.h>
 
@@ -126,7 +124,7 @@
  * NOTE: smb_kdoor_srv_init()/smb_kdoor_srv_fini() are noops.
  */
 int smb_kdoor_srv_start(void);
-int smb_kdoor_srv_set_dwncall(void);
+int smb_kdoor_srv_set_downcall(void);
 void smb_kdoor_srv_stop(void);
 int smb_kdr_is_valid_opcode(int);
 
@@ -139,16 +137,18 @@
  * ------------------------
  * NOTE: smb_kdoor_clnt_init()/smb_kdoor_clnt_fini() are noops.
  */
-int smb_kdoor_clnt_start(int);
-void smb_kdoor_clnt_stop(void);
+void smb_kdoor_clnt_init(void);
+void smb_kdoor_clnt_fini(void);
+int smb_kdoor_clnt_open(int);
+void smb_kdoor_clnt_close(void);
+char *smb_kdoor_clnt_upcall(char *, size_t, door_desc_t *, uint_t, size_t *);
 void smb_kdoor_clnt_free(char *, size_t, char *, size_t);
-char *smb_kdoor_clnt_upcall(char *, size_t, door_desc_t *, uint_t, size_t *);
 
 /*
  * SMB upcalls
  */
 smb_token_t *smb_upcall_get_token(netr_client_t *);
-int smb_upcall_set_dwncall_desc(uint32_t, door_desc_t *, uint_t);
+int smb_set_downcall_desc(door_desc_t *, uint_t);
 void smb_user_nonauth_logon(uint32_t);
 void smb_user_auth_logoff(uint32_t);
 #else /* _KERNEL */
@@ -159,23 +159,14 @@
 int smb_door_srv_start(void);
 void smb_door_srv_stop(void);
 
-/* downcall descriptor */
-typedef int (*smb_dwncall_get_desc_t)(void);
-int smb_dwncall_install_callback(smb_dwncall_get_desc_t get_desc_cb);
-
 int smb_dr_is_valid_opcode(int);
 
 /*
  * SMB user-space door client
  */
-int smb_dr_clnt_open(int *, char *, char *);
-char *smb_dr_clnt_call(int, char *, size_t, size_t *, char *);
-void smb_dr_clnt_free(char *, size_t, char *, size_t);
-/*
- * SMB downcalls
- */
-int smb_dwncall_get_users(int, smb_dr_ulist_t *);
-int smb_dwncall_share(int, char *, char *);
+int smb_dr_clnt_call(int, door_arg_t *);
+void smb_dr_clnt_setup(door_arg_t *, char *, size_t);
+void smb_dr_clnt_cleanup(door_arg_t *);
 
 #endif /* _KERNEL */
 
--- a/usr/src/uts/common/smbsrv/smb_share.h	Sat Sep 13 23:17:18 2008 -0700
+++ b/usr/src/uts/common/smbsrv/smb_share.h	Sun Sep 14 17:28:06 2008 -0700
@@ -26,8 +26,6 @@
 #ifndef _SMB_SHARE_H
 #define	_SMB_SHARE_H
 
-#pragma ident	"@(#)smb_share.h	1.7	08/08/07 SMI"
-
 /*
  * This file defines the LanMan (CIFS/SMB) resource share interface.
  */
@@ -231,7 +229,8 @@
 void smb_dr_get_share(smb_dr_ctx_t *, smb_share_t *);
 void smb_dr_put_share(smb_dr_ctx_t *, smb_share_t *);
 
-void smb_share_dclose(void);
+void smb_share_door_clnt_init(void);
+void smb_share_door_clnt_fini(void);
 
 #ifdef __cplusplus
 }