diff --git a/source3/include/proto.h b/source3/include/proto.h
index d68aa4b..7a81a84 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -4317,7 +4317,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
 			SEC_DESC **ppsd,
 			bool *pallow_guest);
 int load_usershare_service(const char *servicename);
-int load_usershare_shares(void);
+int load_usershare_shares(bool reload);
 void gfree_loadparm(void);
 void lp_set_in_client(bool b);
 bool lp_is_in_client(void);
@@ -6130,6 +6130,8 @@ NTSTATUS delete_all_streams(connection_struct *conn, const char *fname);
 void conn_init(struct smbd_server_connection *sconn);
 int conn_num_open(struct smbd_server_connection *sconn);
 bool conn_snum_used(int snum);
+void recheck_share_security(int snum);
+void conn_disconnect_snum(int snum);
 connection_struct *conn_find(struct smbd_server_connection *sconn,
 			     unsigned cnum);
 connection_struct *conn_new(struct smbd_server_connection *sconn);
@@ -7067,6 +7069,7 @@ bool change_to_guest(void);
 void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid);
 bool change_to_user(connection_struct *conn, uint16 vuid);
 bool change_to_root_user(void);
+void recheck_current_user(connection_struct *conn);
 bool become_authenticated_pipe_user(pipes_struct *p);
 bool unbecome_authenticated_pipe_user(void);
 void become_root(void);
diff --git a/source3/lib/dummysmbd.c b/source3/lib/dummysmbd.c
index a41e6dc..a100187 100644
--- a/source3/lib/dummysmbd.c
+++ b/source3/lib/dummysmbd.c
@@ -38,6 +38,16 @@ bool conn_snum_used(int snum)
 	return False;
 }
 
+void recheck_share_security(int snum)
+{
+	return;
+}
+
+void conn_disconnect_snum(int snum)
+{
+	return;
+}
+
 void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
 {
 }
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index dbbd6e3..16a2be4 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -364,6 +364,7 @@ struct service {
 	bool autoloaded;
 	int usershare;
 	struct timespec usershare_last_mod;
+	struct timespec usershare_last_mod2; /* only updated when reload from main loop. */
 	char *szService;
 	char *szPath;
 	char *szUsername;
@@ -507,6 +508,7 @@ static struct service sDefault = {
 	False,			/* not autoloaded */
 	0,			/* not a usershare */
 	{0, },                  /* No last mod time */
+	{0, },			/* No last mod time2 */
 	NULL,			/* szService */
 	NULL,			/* szPath */
 	NULL,			/* szUsername */
@@ -8533,6 +8535,9 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
 	return USERSHARE_OK;
 }
 
+/* initialized to invalid */
+static SMB_STRUCT_STAT dir_sbuf = { .st_ex_nlink = 0 }; 
+
 /***************************************************************************
  Deal with a usershare file.
  Returns:
@@ -8542,7 +8547,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
 	    with permissions to share directory etc.
 ***************************************************************************/
 
-static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
+static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template, bool reload)
 {
 	SMB_STRUCT_STAT sbuf;
 	SMB_STRUCT_STAT lsbuf;
@@ -8569,6 +8574,9 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
 	fstrcpy(service_name, file_name);
 
 	if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
+		DEBUG(0, ("process_usershare_file: Allocate memory failed when "
+			  "loading usershare!\n"));
+		return -2;
 	}
 
 	/* Minimize the race condition by doing an lstat before we
@@ -8601,9 +8609,31 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
 		TALLOC_FREE(canon_name);
 	}
 
-	if (iService != -1 &&
-	    timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
-			     &lsbuf.st_ex_mtime) == 0) {
+	if (reload && iService == -1) {
+		/* not loaded, ignore this share. */
+		SAFE_FREE(fname);
+		return -2;
+	}
+
+	/*
+	 * This looks a little weird....
+	 * load_usershare_service() and lp_servicenumber()(calls load_usershare_service())
+	 * are invoked everywhere, each time they are called, usershare_last_mod is updated
+	 * but the access check is not reforced. access check is only checked when we
+	 * reload usershare in the main loop of the child. see, if we depend on
+	 * usershare_last_mod, we are risking missing access check.
+	 * usershare_last_mod2 is only update when access check is performed.
+	 * use another list to keep it is possible, but if we want to use
+	 * load_usershare_shares() and process_usershare_file() here, it is the same
+	 * else we might copy duplicate code to handle usershare reload alone.
+	 */
+
+	if ((!reload && iService != -1 &&
+	     timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
+			      &lsbuf.st_ex_mtime) == 0)
+	     || (reload && iService != -1 && 
+	         timespec_compare(&ServicePtrs[iService]->usershare_last_mod2,
+		 		  &lsbuf.st_ex_mtime) == 0)) {
 		/* Nothing changed - Mark valid and return. */
 		DEBUG(10,("process_usershare_file: service %s not changed.\n",
 			service_name ));
@@ -8612,6 +8642,15 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
 		return iService;
 	}
 
+	if (reload && iService != -1 &&
+	    timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
+			     &lsbuf.st_ex_mtime) == 0 &&
+	    timespec_compare(&ServicePtrs[iService]->usershare_last_mod2,
+	    		     &lsbuf.st_ex_mtime) != 0) {
+		/* the share is update, only need to recheck accesses */
+		goto check_access;
+	}
+
 	/* Try and open the file read only - no symlinks allowed. */
 #ifdef O_NOFOLLOW
 	fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
@@ -8725,6 +8764,20 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
 	string_set(&ServicePtrs[iService]->comment, comment);
 
 	talloc_destroy(ctx);
+check_access:
+	if (reload) {
+		/* trying to adjust share access for connections. */
+		if (conn_snum_used(iService)) {
+			/* rechecking share security */
+			DEBUG(0, ("[boyang] process_usershare_file: "
+				  "rechecking permission for share %s\n",
+				  lp_servicename(iService)));
+			recheck_share_security(iService);
+		}
+		/* update time stamp when finish the access check. */
+		ServicePtrs[iService]->usershare_last_mod2 = 
+			ServicePtrs[iService]->usershare_last_mod;
+	}
 
 	return iService;
 }
@@ -8781,6 +8834,11 @@ int load_usershare_service(const char *servicename)
 		return -1;
 	}
 
+	if (dir_sbuf.st_ex_nlink == 0) {
+		/* first time to load, update stat buffer. */
+		memcpy(&dir_sbuf, &sbuf, sizeof(SMB_STRUCT_STAT));
+	}
+
 	if (!S_ISDIR(sbuf.st_ex_mode)) {
 		DEBUG(0,("load_usershare_service: %s is not a directory.\n",
 			usersharepath ));
@@ -8823,7 +8881,34 @@ int load_usershare_service(const char *servicename)
 		}
 	}
 
-	return process_usershare_file(usersharepath, servicename, snum_template);
+	return process_usershare_file(usersharepath, servicename, snum_template, false);
+}
+
+static bool usershare_dir_changed(void)
+{
+	SMB_STRUCT_STAT sbuf;
+	const char *usersharepath = lp_usershare_path();
+	/* not even loaded, so there is no change. :-) */
+	if (dir_sbuf.st_ex_nlink == 0) {
+		return false;
+	}
+	/* usershare is not enabled. */
+	if (lp_usershare_max_shares() == 0 || !usersharepath || !*usersharepath) {
+		return false;
+	}
+	if (sys_stat(usersharepath, &sbuf) != 0) {
+		DEBUG(0, ("usershare_dir_changed: stat usershare path %s failed. %s\n",
+			  usersharepath, strerror(errno)));
+		/* not sure if it is changed. return false? */
+		return false;
+	}
+	if (dir_sbuf.st_ex_dev != sbuf.st_ex_dev
+	    || dir_sbuf.st_ex_ino != sbuf.st_ex_ino
+	    || timespec_compare(&dir_sbuf.st_ex_mtime, &sbuf.st_ex_mtime) != 0) {
+		memcpy(&dir_sbuf, &sbuf, sizeof(SMB_STRUCT_STAT));
+		return true;
+	}
+	return false;
 }
 
 /***************************************************************************
@@ -8833,7 +8918,7 @@ int load_usershare_service(const char *servicename)
  been removed.
 ***************************************************************************/
 
-int load_usershare_shares(void)
+int load_usershare_shares(bool reload)
 {
 	SMB_STRUCT_DIR *dp;
 	SMB_STRUCT_STAT sbuf;
@@ -8848,6 +8933,14 @@ int load_usershare_shares(void)
 	const char *usersharepath = Globals.szUsersharePath;
 	int ret = lp_numservices();
 
+	if (reload && !usershare_dir_changed()) {
+		return lp_numservices();
+	}
+
+	if (reload) {
+		DEBUG(0, ("[boyang] load_usershare_shares: trying to reload usershare!!\n"));
+	}
+
 	if (max_user_shares == 0 || *usersharepath == '\0') {
 		return lp_numservices();
 	}
@@ -8858,6 +8951,11 @@ int load_usershare_shares(void)
 		return ret;
 	}
 
+	if (reload || dir_sbuf.st_ex_nlink == 0) {
+		/* first time to load usershare or reload, update stat buffer. */
+		memcpy(&dir_sbuf, &sbuf, sizeof(SMB_STRUCT_STAT));
+	}
+
 	/*
 	 * This directory must be owned by root, and have the 't' bit set.
 	 * It also must not be writable by "other".
@@ -8934,8 +9032,8 @@ int load_usershare_shares(void)
 			break;
 		}
 
-		r = process_usershare_file(usersharepath, n, snum_template);
-		if (r == 0) {
+		r = process_usershare_file(usersharepath, n, snum_template, reload);
+		if (r >= 0) {
 			/* Update the services count. */
 			num_usershares++;
 			if (num_usershares >= max_user_shares) {
@@ -8972,6 +9070,13 @@ int load_usershare_shares(void)
 	for (iService = iNumServices - 1; iService >= 0; iService--) {
 		if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
 			if (conn_snum_used(iService)) {
+				/* should we disconnect the tconxs if we are reloading? */
+				if (reload) {
+					DEBUG(10, ("[boyang] removing non-exist shares.\n"));
+					delete_share_security(lp_servicename(iService));
+					conn_disconnect_snum(iService);
+					free_service_byindex(iService);
+				}
 				continue;
 			}
 			/* Remove from the share ACL db. */
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index c58c08e..41304a5 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -527,7 +527,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
 
 	/* Ensure all the usershares are loaded. */
 	become_root();
-	load_usershare_shares();
+	load_usershare_shares(false);
 	load_registry_shares();
 	num_services = lp_numservices();
 	unbecome_root();
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index af6e091..b6183e5 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -61,6 +61,61 @@ bool conn_snum_used(int snum)
 	return(False);
 }
 
+/***************************************************************************
+ Recheck share access for existing connections, which is used for usershare
+ now. This cannot be used for other shares now, because this cannot handle
+ force user parameters. At present, usershare has no force user parameter.
+***************************************************************************/
+void recheck_share_security(int snum)
+{
+	struct smbd_server_connection *sconn = smbd_server_conn;
+	int i;
+	struct vuid_cache_entry *ent;
+	connection_struct *conn;
+	for (conn = sconn->smb1.tcons.Connections; conn; conn=conn->next) {
+		if (conn->params->service == snum) {
+			conn->read_only = false;
+			conn->admin_user = false;
+			for (i = 0; i < VUID_CACHE_SIZE; i++) {
+				ent = &conn->vuid_cache.array[i];
+				if (ent->vuid != UID_FIELD_INVALID) {
+					ent->vuid = UID_FIELD_INVALID;
+					if (conn->server_info == ent->server_info) {
+						ent->server_info = NULL;
+					} else {
+						TALLOC_FREE(ent->server_info);
+					}
+					ent->read_only = false;
+					ent->admin_user = false;
+				}
+			}
+			/* handle current user if he is on this tree. */
+			recheck_current_user(conn);
+			/* need to handle fsp too? */
+			/* leave the tree connect here, but close open fsps. */
+			file_close_conn(conn);
+		}
+	}
+	return;
+}
+
+/***************************************************************************
+ Given a service number to disconnect all tconx connected to the share.
+***************************************************************************/
+void conn_disconnect_snum(int snum)
+{
+	struct smbd_server_connection *sconn = smbd_server_conn;
+	connection_struct *conn, *next;
+	for (conn = sconn->smb1.tcons.Connections; conn; conn=next) {
+		next = conn->next;
+		if (SNUM(conn) == snum) {
+			set_current_service(NULL, 0, true);
+			close_cnum(sconn, conn, conn->vuid);
+		}
+	}
+	return;
+}
+
 /****************************************************************************
  Find a conn given a cnum.
 ****************************************************************************/
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 6fc72c2..55d69c2 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -1806,7 +1806,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
 	/* Ensure all the usershares are loaded. */
 	become_root();
 	load_registry_shares();
-	count = load_usershare_shares();
+	count = load_usershare_shares(false);
 	unbecome_root();
 
 	data_len = fixed_len = string_len = 0;
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index d40b8a8..7139470 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -1681,7 +1681,7 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn)
 	/* Ensure all the usershares are loaded. */
 	become_root();
 	load_registry_shares();
-	sharecount = load_usershare_shares();
+	sharecount = load_usershare_shares(false);
 	unbecome_root();
 
 	for(i=0;i < sharecount;i++) {
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index b26bc15..20aae81 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -762,6 +762,15 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *
 	struct timeval to;
 	int maxfd = 0;
 
+	/* 
+	 * Watch on usershare service changes. Only load usershare
+	 * that were loaded by the child already. The change of unloaded
+	 * shares won't affect current connection. The purpose here is to
+	 * detect user share change on fly, which is the case in windows.
+	 * We don't want to reload all services when only usershare service
+	 * changed. we don't add the directory to lp_file_lists_changed().
+	 */
+
 	to.tv_sec = SMBD_SELECT_TIMEOUT;
 	to.tv_usec = 0;
 
@@ -800,6 +809,8 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *
 		END_PROFILE(smbd_idle);
 		errno = sav;
 	}
+	
+	load_usershare_shares(true);
 
 	if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
 		return NT_STATUS_RETRY;
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 2ec50cd..ef620bd 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -505,3 +505,26 @@ bool unbecome_user(void)
 	pop_conn_ctx();
 	return True;
 }
+
+void recheck_current_user(connection_struct *conn)
+{
+	struct auth_serversupplied_info *server_info;
+	user_struct *vuser = get_valid_user_struct(smbd_server_conn, current_user.vuid); 
+	if ((current_user.conn == conn)
+	     && (current_user.vuid != UID_FIELD_INVALID)) {
+		server_info = vuser ? vuser->server_info : conn->server_info;
+		if (!check_user_ok(conn, current_user.vuid, server_info, SNUM(conn))) {
+			DEBUG(10, ("[boyang] recheck_share_security: rechecking for "
+				   "current user, access denied!"));
+			/*
+			 * change to root user. which will force
+			 * check at next request.
+			 */
+			change_to_root_user();
+		} else {
+			DEBUG(0, ("[boyang] current user access %s\n", conn->read_only ?
+		        	  "read" : "read/write"));
+		}
+	}
+	return;
+}
