diff -urpN ksmbd-tools-3.1.0/configure.ac ksmbd-tools-3.1.0.new/configure.ac
--- ksmbd-tools-3.1.0/configure.ac	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/configure.ac	2020-01-25 02:01:29.299043469 +0400
@@ -48,11 +48,6 @@ AC_CHECK_FUNCS_ONCE([
 	recvmsg
 ])
 
-PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.40], [has_glib2=1], [has_glib2=0])
-AS_IF([test "$has_glib2" -eq 0],
-      AC_MSG_ERROR([No glib2 (libglib2.0-dev or glib2-devel) was found])
-])
-
 has_libnl_ver=0
 dnl libnl-genl-3.0.pc pkg-config file just for libnl-3.0 case.
 PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.0 libnl-genl-3.0 >= 3.0], [has_libnl_ver=3], [has_libnl_ver=0])
diff -urpN ksmbd-tools-3.1.0/include/config_parser.h ksmbd-tools-3.1.0.new/include/config_parser.h
--- ksmbd-tools-3.1.0/include/config_parser.h	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/include/config_parser.h	2020-01-25 02:01:29.299043469 +0400
@@ -8,15 +8,15 @@
 #ifndef __USMBD_CONFIG_H__
 #define __USMBD_CONFIG_H__
 
-#include <glib.h>
+#include <usmbdtools.h>
 
 struct smbconf_group {
 	char			*name;
-	GHashTable		*kv;
+	struct LIST		*kv;
 };
 
 struct smbconf_parser {
-	GHashTable		*groups;
+	struct LIST		*groups;
 	struct smbconf_group	*current;
 };
 
diff -urpN ksmbd-tools-3.1.0/include/management/session.h ksmbd-tools-3.1.0.new/include/management/session.h
--- ksmbd-tools-3.1.0/include/management/session.h	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/include/management/session.h	2020-01-25 02:01:29.299043469 +0400
@@ -8,7 +8,7 @@
 #ifndef __MANAGEMENT_TCONNECTION_H__
 #define __MANAGEMENT_TCONNECTION_H__
 
-#include <glib.h>
+#include <usmbdtools.h>
 
 struct usmbd_user;
 
@@ -17,8 +17,8 @@ struct usmbd_session {
 
 	struct usmbd_user	*user;
 
-	GRWLock			update_lock;
-	GList			*tree_conns;
+	pthread_rwlock_t	update_lock;
+	struct LIST		*tree_conns;
 	int			ref_counter;
 };
 
diff -urpN ksmbd-tools-3.1.0/include/management/share.h ksmbd-tools-3.1.0.new/include/management/share.h
--- ksmbd-tools-3.1.0/include/management/share.h	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/include/management/share.h	2020-01-26 13:58:13.864726159 +0400
@@ -8,7 +8,7 @@
 #ifndef __MANAGEMENT_SHARE_H__
 #define __MANAGEMENT_SHARE_H__
 
-#include <glib.h>
+#include <usmbdtools.h>
 
 
 enum share_users {
@@ -44,7 +44,7 @@ struct usmbd_share {
 	int		max_connections;
 	int		num_connections;
 
-	GRWLock		update_lock;
+	pthread_rwlock_t	update_lock;
 	int		ref_count;
 
 	unsigned short	create_mask;
@@ -61,19 +61,19 @@ struct usmbd_share {
 
 	char		*guest_account;
 
-	GHashTable	*maps[USMBD_SHARE_USERS_MAX];
+	struct LIST	*maps[USMBD_SHARE_USERS_MAX];
 	/*
 	 * FIXME
 	 * We need to support IP ranges, netmasks, etc.
 	 * This is just a silly hostname matching, hence
 	 * these two are not in ->maps[].
 	 */
-	GHashTable	*hosts_allow_map;
+	struct LIST	*hosts_allow_map;
 	/* Deny access */
-	GHashTable	*hosts_deny_map;
+	struct LIST	*hosts_deny_map;
 
 	/* One lock to rule them all [as of now] */
-	GRWLock		maps_lock;
+	pthread_rwlock_t maps_lock;
 
 	char		*comment;
 };
@@ -158,10 +158,8 @@ int shm_lookup_hosts_map(struct usmbd_sh
 int shm_open_connection(struct usmbd_share *share);
 int shm_close_connection(struct usmbd_share *share);
 
-typedef void (*walk_shares)(gpointer key,
-			    gpointer value,
-			    gpointer user_data);
-void for_each_usmbd_share(walk_shares cb, gpointer user_data);
+typedef void (*walk_shares)(void *item, unsigned long long id, void *user_data);
+void foreach_usmbd_share(walk_shares cb, void *user_data);
 
 struct usmbd_share_config_response;
 
diff -urpN ksmbd-tools-3.1.0/include/management/tree_conn.h ksmbd-tools-3.1.0.new/include/management/tree_conn.h
--- ksmbd-tools-3.1.0/include/management/tree_conn.h	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/include/management/tree_conn.h	2020-01-25 02:01:29.299043469 +0400
@@ -8,8 +8,6 @@
 #ifndef __MANAGEMENT_TREE_CONN_H__
 #define __MANAGEMENT_TREE_CONN_H__
 
-#include <glib.h>
-
 struct usmbd_share;
 
 struct usmbd_tree_conn {
diff -urpN ksmbd-tools-3.1.0/include/management/user.h ksmbd-tools-3.1.0.new/include/management/user.h
--- ksmbd-tools-3.1.0/include/management/user.h	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/include/management/user.h	2020-01-26 13:58:13.864726159 +0400
@@ -10,7 +10,6 @@
 
 #include <sys/types.h>
 #include <pwd.h>
-#include <glib.h>
 
 struct usmbd_user {
 	char		*name;
@@ -24,7 +23,7 @@ struct usmbd_user {
 
 	int		ref_count;
 	int		flags;
-	GRWLock		update_lock;
+	pthread_rwlock_t	update_lock;
 };
 
 static inline void set_user_flag(struct usmbd_user *user, int bit)
@@ -50,10 +49,10 @@ int usm_add_update_user_from_pwdentry(ch
 void usm_destroy(void);
 int usm_init(void);
 
-typedef void (*walk_users)(gpointer key,
-			   gpointer value,
-			   gpointer user_data);
-void for_each_usmbd_user(walk_users cb, gpointer user_data);
+typedef void (*walk_users)(void *value,
+			   unsigned long long key,
+			   void *user_data);
+void foreach_usmbd_user(walk_users cb, void *user_data);
 
 struct usmbd_login_request;
 struct usmbd_login_response;
diff -urpN ksmbd-tools-3.1.0/include/rpc.h ksmbd-tools-3.1.0.new/include/rpc.h
--- ksmbd-tools-3.1.0/include/rpc.h	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/include/rpc.h	2020-01-25 02:01:29.299043469 +0400
@@ -9,7 +9,6 @@
 #define __USMBD_RPC_H__
 
 #include <linux/types.h>
-#include <glib.h>
 
 #define USMBD_DCERPC_LITTLE_ENDIAN	(1 << 0)
 #define USMBD_DCERPC_ALIGN2		(1 << 1)
@@ -251,27 +250,27 @@ struct usmbd_dcerpc {
 	 * restriction
 	 */
 	int			(*entry_size)(struct usmbd_dcerpc *dce,
-					      gpointer entry);
+					      void *entry);
 	/*
 	 * Entry representation under the given container level
 	 * restriction for array representation
 	 */
 	int			(*entry_rep)(struct usmbd_dcerpc *dce,
-					      gpointer entry);
+					      void *entry);
 	/*
 	 * Entry data under the given container level restriction
 	 * for array representation
 	 */
 	int			(*entry_data)(struct usmbd_dcerpc *dce,
-					      gpointer entry);
+					      void *entry);
 };
 
 struct usmbd_rpc_pipe {
-	unsigned int		id;
+	unsigned int	id;
 
 	int			num_entries;
 	int			num_processed;
-	GArray			*entries;
+	struct LIST		*entries;
 
 	struct usmbd_dcerpc	*dce;
 
diff -urpN ksmbd-tools-3.1.0/include/usmbdtools.h ksmbd-tools-3.1.0.new/include/usmbdtools.h
--- ksmbd-tools-3.1.0/include/usmbdtools.h	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/include/usmbdtools.h	2020-01-26 14:06:09.634412732 +0400
@@ -23,35 +23,99 @@
 #include <time.h>
 #include <poll.h>
 #include <getopt.h>
-#include <glib.h>
+#include <pthread.h>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+char *ascii_strdown(char *str, size_t len);
+
+int atomic_int_add(volatile int *atomic, int val);
+void atomic_int_inc(volatile int *atomic);
+
+int atomic_int_compare_and_exchange(volatile int *atomic,
+				    int oldval, int newval);
+
+#define KEY_ID 0x0
+#define KEY_STRING 0x1
+struct LIST {
+	struct LIST *prev;
+	struct LIST *next;
+	int type;
+	unsigned long long id;
+	char *keystr;
+	void *item;
+};
+
+struct LIST *list_init(struct LIST **list);
+long long list_maxid(struct LIST **list);
+int list_add_str(struct LIST **list, void *item, char *str);
+int list_add(struct LIST **list, void *item, unsigned long long id);
+void list_append(struct LIST **list, void *item);
+int list_remove(struct LIST **list, unsigned long long id);
+int list_remove_dec(struct LIST **list, unsigned long long id);
+void *list_get(struct LIST **list, unsigned long long id);
+void list_clear(struct LIST **list);
+int list_foreach(struct LIST **list,
+		 void (*func)(void *item, unsigned long long id,
+			      void *user_data), void *user_data);
+
+static unsigned long long list_tokey(void *ptr)
+{
+	size_t p = (size_t)ptr;
+	return p;
+}
+
+static void *list_fromkey(unsigned long long key)
+{
+	size_t p = key;
+
+	return (void *)p;
+}
+
+typedef enum {
+	step_A, step_B, step_C
+} base64_encodestep;
+
+typedef struct {
+	base64_encodestep step;
+	char result;
+	int stepcount;
+} base64_encodestate;
+
+typedef enum {
+	step_a, step_b, step_c, step_d
+} base64_decodestep;
+
+typedef struct {
+	base64_decodestep step;
+	char plainchar;
+} base64_decodestate;
+
 struct smbconf_global {
-	int			flags;
-	int			map_to_guest;
-	char			*guest_account;
-
-	char			*server_string;
-	char			*work_group;
-	char			*netbios_name;
-	char			*server_min_protocol;
-	char			*server_max_protocol;
-	char			*root_dir;
-	int			server_signing;
-	int			sessions_cap;
-	int			restrict_anon;
-	unsigned short		tcp_port;
-	unsigned short		ipc_timeout;
-	unsigned int		deadtime;
-	int			bind_interfaces_only;
-	char			**interfaces;
-	unsigned long		file_max;
-	unsigned int		smb2_max_read;
-	unsigned int		smb2_max_write;
-	unsigned int		smb2_max_trans;
+	int flags;
+	int map_to_guest;
+	char *guest_account;
+
+	char *server_string;
+	char *work_group;
+	char *netbios_name;
+	char *server_min_protocol;
+	char *server_max_protocol;
+	char *root_dir;
+	int server_signing;
+	int sessions_cap;
+	int restrict_anon;
+	unsigned short tcp_port;
+	unsigned short ipc_timeout;
+	unsigned int deadtime;
+	int bind_interfaces_only;
+	char **interfaces;
+	unsigned long file_max;
+	unsigned int smb2_max_read;
+	unsigned int smb2_max_write;
+	unsigned int smb2_max_trans;
 };
 
 #define USMBD_LOCK_FILE		"/tmp/usmbd.lock"
@@ -113,7 +177,7 @@ static int log_level = PR_INFO;
  */
 char *strerr(int err);
 
-__attribute__ ((format (printf, 2, 3)))
+__attribute__((format(printf, 2, 3)))
 extern void __pr_log(int level, const char *fmt, ...);
 extern void set_logger_app_name(const char *an);
 extern const char *get_logger_app_name(void);
@@ -141,20 +205,19 @@ void pr_hex_dump(const void *mem, size_t
 char *base64_encode(unsigned char *src, size_t srclen);
 unsigned char *base64_decode(char const *src, size_t *dstlen);
 
-gchar *usmbd_gconvert(const gchar *str,
-		      gssize       str_len,
-		      int          to_codeset,
-		      int          from_codeset,
-		      gsize       *bytes_read,
-		      gsize       *bytes_written);
+char *usmbd_gconvert(const char *str,
+		     size_t str_len,
+		     int to_codeset,
+		     int from_codeset,
+		     size_t *bytes_read, size_t *bytes_written);
 
 enum charset_idx {
-	USMBD_CHARSET_UTF8		= 0,
+	USMBD_CHARSET_UTF8 = 0,
 	USMBD_CHARSET_UTF16LE,
 	USMBD_CHARSET_UCS2LE,
 	USMBD_CHARSET_UTF16BE,
 	USMBD_CHARSET_UCS2BE,
-	USMBD_CHARSET_MAX		= 5,
+	USMBD_CHARSET_MAX = 5,
 };
 
 #define USMBD_CHARSET_DEFAULT		USMBD_CHARSET_UTF8
diff -urpN ksmbd-tools-3.1.0/lib/config_parser.c ksmbd-tools-3.1.0.new/lib/config_parser.c
--- ksmbd-tools-3.1.0/lib/config_parser.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/lib/config_parser.c	2020-01-26 14:06:09.634412732 +0400
@@ -5,13 +5,14 @@
  *   linux-cifsd-devel@lists.sourceforge.net
  */
 
-#include <glib.h>
 #include <string.h>
-#include <glib/gstdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <ctype.h>
+#include <sys/mman.h>
+#include <limits.h>
 #include <linux/usmbd_server.h>
 
 #include <config_parser.h>
@@ -52,9 +53,9 @@ unsigned long long memparse(const char *
 	return ret;
 }
 
-static void kv_release_cb(gpointer p)
+static void kv_release_cb(void *p, unsigned long long id, void *user_data)
 {
-	g_free(p);
+	free(p);
 }
 
 static int is_ascii_space_tab(char c)
@@ -67,6 +68,18 @@ static int is_a_comment(char *line)
 	return (*line == 0x00 || *line == ';' || *line == '\n' || *line == '#');
 }
 
+static char *utf8_find_next_char(const char *p, const char *end)
+{
+	if (end) {
+		for (++p; p < end && (*p & 0xc0) == 0x80; ++p)
+		;
+		return (p >= end) ? NULL : (char *)p;
+	}
+	for (++p; (*p & 0xc0) == 0x80; ++p)
+	;
+	return (char *)p;
+}
+
 static int is_a_group(char *line)
 {
 	char *p = line;
@@ -75,7 +88,7 @@ static int is_a_group(char *line)
 		return 0;
 	p++;
 	while (*p && *p != ']')
-		p = g_utf8_find_next_char(p, NULL);
+		p = utf8_find_next_char(p, NULL);
 	if (*p != ']')
 		return 0;
 	return 1;
@@ -90,42 +103,40 @@ static int add_new_group(char *line)
 	struct smbconf_group *lookup;
 
 	while (*end && *end != ']')
-		end = g_utf8_find_next_char(end, NULL);
+		end = utf8_find_next_char(end, NULL);
 
-	name = g_ascii_strdown(begin + 1, end - begin - 1);
+	name = ascii_strdown(begin + 1, end - begin - 1);
 	if (!name)
 		goto out_free;
 
-	lookup = g_hash_table_lookup(parser.groups, name);
+	lookup = list_get(&parser.groups, list_tokey(name));
 	if (lookup) {
 		parser.current = lookup;
-		pr_info("SMB conf: multiple group definitions `%s'\n",
-				name);
-		g_free(name);
+		pr_info("SMB conf: multiple group definitions `%s'\n", name);
+		free(name);
 		return 0;
 	}
 
-	group = g_malloc(sizeof(struct smbconf_group));
+	group = malloc(sizeof(struct smbconf_group));
 	if (!group)
 		goto out_free;
 
 	group->name = name;
-	group->kv = g_hash_table_new_full(g_str_hash,
-					  g_str_equal,
-					  kv_release_cb,
-					  kv_release_cb);
+	list_init(&group->kv);
+
 	if (!group->kv)
 		goto out_free;
 
 	parser.current = group;
-	g_hash_table_insert(parser.groups, group->name, group);
+	list_add_str(&parser.groups, group, group->name);
+
 	return 0;
 
 out_free:
-	g_free(name);
+	free(name);
 	if (group && group->kv)
-		g_hash_table_destroy(group->kv);
-	g_free(group);
+		list_clear(&group->kv);
+	free(group);
 	return -ENOMEM;
 }
 
@@ -150,22 +161,22 @@ static int add_group_key_value(char *lin
 	if (is_a_comment(value))
 		return 0;
 
-	if (g_hash_table_lookup(parser.current->kv, key)) {
+	if (list_get(&parser.current->kv, list_tokey(key))) {
 		pr_info("SMB conf: multuple key-value [%s] %s\n",
-				parser.current->name, key);
+			parser.current->name, key);
 		return 0;
 	}
 
-	key = g_strndup(line, key - line + 1);
-	value = g_strdup(value);
+	key = strndup(line, key - line + 1);
+	value = strdup(value);
 
 	if (!key || !value) {
-		g_free(key);
-		g_free(value);
+		free(key);
+		free(value);
 		return -ENOMEM;
 	}
 
-	g_hash_table_insert(parser.current->kv, key, value);
+	list_add_str(&parser.current->kv, value, key);
 	return 0;
 }
 
@@ -183,35 +194,29 @@ static int process_smbconf_entry(char *d
 	return add_group_key_value(data);
 }
 
-static int __mmap_parse_file(const char *fname, int (*callback)(char *data))
+static int __mmap_parse_file(const char *fname, int (*callback)(char *d))
 {
-	GMappedFile *file;
-	GError *err = NULL;
-	gchar *contents;
-	int len;
+	char *contents, *buf;
+	size_t len;
 	char *delim;
-	int fd, ret = 0;
+	int ret = 0;
+	FILE *fd;
 
-	fd = g_open(fname, O_RDONLY, 0);
-	if (fd == -1) {
+	fd = fopen(fname, "rb");
+	if (fd == NULL) {
 		ret = errno;
 		pr_err("Can't open `%s': %s\n", fname, strerr(ret));
 		return -ret;
 	}
-
-	file = g_mapped_file_new_from_fd(fd, FALSE, &err);
-	if (err) {
-		pr_err("%s: `%s'\n", err->message, fname);
-		g_error_free(err);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	contents = g_mapped_file_get_contents(file);
+	fseek(fd, 0, SEEK_END);
+	len = ftell(fd);
+	rewind(fd);
+	buf = contents = malloc(len + 1);
 	if (!contents)
 		goto out;
+	fread(contents, 1, len, fd);
+	contents[len] = 0;
 
-	len = g_mapped_file_get_length(file);
 	while (len > 0) {
 		delim = strchr(contents, '\n');
 		if (!delim)
@@ -219,7 +224,6 @@ static int __mmap_parse_file(const char
 
 		if (delim) {
 			size_t sz = delim - contents;
-			char *data;
 
 			if (delim == contents) {
 				contents = delim + 1;
@@ -229,23 +233,15 @@ static int __mmap_parse_file(const char
 
 			if (!sz)
 				break;
-
-			data = g_malloc(sz + 1);
-			if (!data) {
-				ret = -ENOMEM;
-				goto out;
-			}
-
-			strncpy(data, contents, sz);
-			data[sz] = 0x00;
+			char *data = strndup(contents, sz);
 
 			ret = callback(data);
 			if (ret) {
-				g_free(data);
+				free(data);
 				goto out;
 			}
+			free(data);
 
-			g_free(data);
 			contents = delim + 1;
 			len -= (sz + 1);
 		}
@@ -253,16 +249,12 @@ static int __mmap_parse_file(const char
 
 	ret = 0;
 out:
-	if (file)
-		g_mapped_file_unref(file);
+	if (buf)
+		free(buf);
+
+	if (fd)
+		fclose(fd);
 
-	if (fd) {
-		g_close(fd, &err);
-		if (err) {
-			pr_err("%s: %s\n", err->message, fname);
-			g_error_free(err);
-		}
-	}
 	return ret;
 }
 
@@ -271,28 +263,29 @@ static int init_smbconf_parser(void)
 	if (parser.groups)
 		return 0;
 
-	parser.groups = g_hash_table_new(g_str_hash, g_str_equal);
+	list_init(&parser.groups);
 	if (!parser.groups)
 		return -ENOMEM;
 	return 0;
 }
 
-static void release_smbconf_group(gpointer k, gpointer v, gpointer user_data)
+static void release_smbconf_group(void *v, unsigned long long id,
+				  void *user_data)
 {
 	struct smbconf_group *g = v;
 
-	g_hash_table_destroy(g->kv);
-	g_free(g->name);
-	g_free(g);
+	list_foreach(&g->kv, kv_release_cb, NULL);
+	list_clear(&g->kv);
+	free(g->name);
+	free(g);
 }
 
 static void release_smbconf_parser(void)
 {
 	if (!parser.groups)
 		return;
-
-	g_hash_table_foreach(parser.groups, release_smbconf_group, NULL);
-	g_hash_table_destroy(parser.groups);
+	list_foreach(&parser.groups, release_smbconf_group, NULL);
+	list_clear(&parser.groups);
 	parser.groups = NULL;
 }
 
@@ -312,33 +305,32 @@ int cp_key_cmp(char *k, char *v)
 {
 	if (!k || !v)
 		return -1;
-	return g_ascii_strncasecmp(k, v, strlen(v));
+	return strncasecmp(k, v, strlen(v));
 }
 
 char *cp_get_group_kv_string(char *v)
 {
-	return g_strdup(v);
+	return strdup(v);
 }
 
 int cp_get_group_kv_bool(char *v)
 {
-	if (!g_ascii_strncasecmp(v, "yes", 3) ||
-		!g_ascii_strncasecmp(v, "1", 1) ||
-		!g_ascii_strncasecmp(v, "true", 4) ||
-		!g_ascii_strncasecmp(v, "enable", 6))
+	if (!strncasecmp(v, "yes", 3) ||
+	    !strncasecmp(v, "1", 1) ||
+	    !strncasecmp(v, "true", 4) || !strncasecmp(v, "enable", 6))
 		return 1;
 	return 0;
 }
 
 int cp_get_group_kv_config_opt(char *v)
 {
-	if (!g_ascii_strncasecmp(v, "disabled", 8))
+	if (!strncasecmp(v, "disabled", 8))
 		return USMBD_CONFIG_OPT_DISABLED;
-	if (!g_ascii_strncasecmp(v, "enabled", 7))
+	if (!strncasecmp(v, "enabled", 7))
 		return USMBD_CONFIG_OPT_ENABLED;
-	if (!g_ascii_strncasecmp(v, "auto", 4))
+	if (!strncasecmp(v, "auto", 4))
 		return USMBD_CONFIG_OPT_AUTO;
-	if (!g_ascii_strncasecmp(v, "mandatory", 9))
+	if (!strncasecmp(v, "mandatory", 9))
 		return USMBD_CONFIG_OPT_MANDATORY;
 	return USMBD_CONFIG_OPT_DISABLED;
 }
@@ -353,25 +345,110 @@ unsigned long cp_get_group_kv_long(char
 	return cp_get_group_kv_long_base(v, 10);
 }
 
+struct SList {
+	void *data;
+	struct SList *next;
+};
+
+struct SList *slist_prepend(struct SList *list, void *data)
+{
+	struct SList *new_list;
+
+	new_list = malloc(sizeof(*list));
+	new_list->data = data;
+	new_list->next = list;
+
+	return new_list;
+}
+
+static char **strsplit_set(const char *string,
+			   const char *delimiters, int max_tokens)
+{
+	unsigned int delim_table[256];
+	struct SList *list, *tokens;
+	int n_tokens;
+	const char *s;
+	const char *current;
+	char *token;
+	char **result;
+
+	if (!string || !delimiters)
+		return NULL;
+
+	if (max_tokens < 1)
+		max_tokens = INT_MAX;
+
+	if (*string == '\0') {
+		result = malloc(sizeof(char *));
+		result[0] = NULL;
+		return result;
+	}
+
+	memset(delim_table, 0, sizeof(delim_table));
+	for (s = delimiters; *s != '\0'; ++s)
+		delim_table[*(unsigned char *)s] = 1;
+
+	tokens = NULL;
+	n_tokens = 0;
+
+	s = current = string;
+	while (*s != '\0') {
+		if (delim_table[*(unsigned char *)s]
+		    && n_tokens + 1 < max_tokens) {
+			token = strndup(current, s - current);
+			tokens = slist_prepend(tokens, token);
+			++n_tokens;
+
+			current = s + 1;
+		}
+
+		++s;
+	}
+
+	token = strndup(current, s - current);
+	tokens = slist_prepend(tokens, token);
+	++n_tokens;
+
+	result = malloc(sizeof(char *) * (n_tokens + 1));
+
+	result[n_tokens] = NULL;
+	for (list = tokens; list != NULL; list = list->next)
+		result[--n_tokens] = list->data;
+
+	list = tokens;
+	while (list) {
+		struct SList *old = list;
+
+		list = list->next;
+		free(old);
+	}
+	return result;
+}
+
 char **cp_get_group_kv_list(char *v)
 {
 	/*
 	 * SMB conf lists are "tabs, spaces, commas" separated.
 	 */
-	return g_strsplit_set(v, "\t ,", -1);
+	return strsplit_set(v, "\t ,", -1);
 }
 
 void cp_group_kv_list_free(char **list)
 {
-	g_strfreev(list);
+	if (list) {
+		int i;
+
+		for (i = 0; list[i] != NULL; i++)
+			free(list[i]);
+		free(list);
+	}
 }
 
-static int cp_add_global_guest_account(gpointer _v)
+static int cp_add_global_guest_account(void *_v)
 {
 	struct usmbd_user *user;
 
-	if (usm_add_new_user(cp_get_group_kv_string(_v),
-			     g_strdup("NULL"))) {
+	if (usm_add_new_user(cp_get_group_kv_string(_v), strdup("NULL"))) {
 		pr_err("Unable to add guest account\n");
 		return -ENOMEM;
 	}
@@ -379,7 +456,7 @@ static int cp_add_global_guest_account(g
 	user = usm_lookup_user(_v);
 	if (!user) {
 		pr_err("Fatal error: unable to find `%s' account.\n",
-			(const char *) _v);
+		       (const char *)_v);
 		return -EINVAL;
 	}
 
@@ -389,8 +466,10 @@ static int cp_add_global_guest_account(g
 	return 0;
 }
 
-static void global_group_kv(gpointer _k, gpointer _v, gpointer user_data)
+static void global_group_kv(void *_v, unsigned long long id, void *user_data)
 {
+	void *_k = list_fromkey(id);
+
 	if (!cp_key_cmp(_k, "server string")) {
 		global_conf.server_string = cp_get_group_kv_string(_v);
 		return;
@@ -450,7 +529,7 @@ static void global_group_kv(gpointer _k,
 	if (!cp_key_cmp(_k, "restrict anonymous")) {
 		global_conf.restrict_anon = cp_get_group_kv_long(_v);
 		if (global_conf.restrict_anon > USMBD_RESTRICT_ANON_TYPE_2 ||
-				global_conf.restrict_anon < 0) {
+		    global_conf.restrict_anon < 0) {
 			global_conf.restrict_anon = 0;
 			pr_err("Invalid restrict anonymous value\n");
 		}
@@ -462,13 +541,13 @@ static void global_group_kv(gpointer _k,
 		global_conf.map_to_guest = USMBD_CONF_MAP_TO_GUEST_NEVER;
 		if (!cp_key_cmp(_v, "bad user"))
 			global_conf.map_to_guest =
-				USMBD_CONF_MAP_TO_GUEST_BAD_USER;
+			    USMBD_CONF_MAP_TO_GUEST_BAD_USER;
 		if (!cp_key_cmp(_v, "bad password"))
 			global_conf.map_to_guest =
-				USMBD_CONF_MAP_TO_GUEST_BAD_PASSWORD;
+			    USMBD_CONF_MAP_TO_GUEST_BAD_PASSWORD;
 		if (!cp_key_cmp(_v, "bad uid"))
 			global_conf.map_to_guest =
-				USMBD_CONF_MAP_TO_GUEST_BAD_UID;
+			    USMBD_CONF_MAP_TO_GUEST_BAD_UID;
 		return;
 	}
 
@@ -563,14 +642,13 @@ static void fixup_missing_global_group(v
 		global_conf.file_max = USMBD_CONF_FILE_MAX;
 	if (!global_conf.server_string)
 		global_conf.server_string =
-			cp_get_group_kv_string(
-					USMBD_CONF_DEFAULT_SERVER_STRING);
+		    cp_get_group_kv_string(USMBD_CONF_DEFAULT_SERVER_STRING);
 	if (!global_conf.netbios_name)
 		global_conf.netbios_name =
-			cp_get_group_kv_string(USMBD_CONF_DEFAULT_NETBIOS_NAME);
+		    cp_get_group_kv_string(USMBD_CONF_DEFAULT_NETBIOS_NAME);
 	if (!global_conf.work_group)
 		global_conf.work_group =
-			cp_get_group_kv_string(USMBD_CONF_DEFAULT_WORK_GROUP);
+		    cp_get_group_kv_string(USMBD_CONF_DEFAULT_WORK_GROUP);
 	if (!global_conf.tcp_port)
 		global_conf.tcp_port = USMBD_CONF_DEFAULT_TPC_PORT;
 
@@ -586,7 +664,7 @@ static void fixup_missing_global_group(v
 	ret = cp_add_global_guest_account(USMBD_CONF_FALLBACK_GUEST_ACCOUNT);
 	if (ret)
 		pr_err("Fatal error: Cannot set a global guest account %d\n",
-			ret);
+		       ret);
 }
 
 static void default_global_group(void)
@@ -597,20 +675,22 @@ static void default_global_group(void)
 
 static void global_group(struct smbconf_group *group)
 {
-	g_hash_table_foreach(group->kv, global_group_kv, NULL);
+	list_foreach(&group->kv, global_group_kv, NULL);
 }
 
 #define GROUPS_CALLBACK_STARTUP_INIT	0x1
 #define GROUPS_CALLBACK_REINIT		0x2
 
-static void groups_callback(gpointer _k, gpointer _v, gpointer flags)
+static void groups_callback(void *_v, unsigned long long id, void *flags)
 {
-	if (g_ascii_strncasecmp(_k, "global", 6)) {
+	void *_k = list_fromkey(id);
+
+	if (strncasecmp(_k, "global", 6)) {
 		shm_add_new_share((struct smbconf_group *)_v);
 		return;
 	}
 
-	if (flags == (gpointer)GROUPS_CALLBACK_STARTUP_INIT)
+	if (flags == (void *)GROUPS_CALLBACK_STARTUP_INIT)
 		global_group((struct smbconf_group *)_v);
 }
 
@@ -619,10 +699,10 @@ static int cp_add_ipc_share(void)
 	char *comment = NULL;
 	int ret = 0;
 
-	if (g_hash_table_lookup(parser.groups, "ipc$"))
+	if (list_get(&parser.groups, list_tokey("ipc$")))
 		return 0;
 
-	comment = g_strdup("comment = IPC share");
+	comment = strdup("comment = IPC share");
 	ret = add_new_group("[IPC$]");
 	ret |= add_group_key_value(comment);
 	if (ret) {
@@ -633,11 +713,11 @@ static int cp_add_ipc_share(void)
 	return ret;
 
 out:
-	g_free(comment);
+	free(comment);
 	return ret;
 }
 
-static int __cp_parse_smbconfig(const char *smbconf, GHFunc cb, long flags)
+static int __cp_parse_smbconfig(const char *smbconf, long flags)
 {
 	int ret;
 
@@ -649,9 +729,7 @@ static int __cp_parse_smbconfig(const ch
 
 	ret = cp_add_ipc_share();
 	if (!ret) {
-		g_hash_table_foreach(parser.groups,
-				     groups_callback,
-				     (gpointer)flags);
+		list_foreach(&parser.groups, groups_callback, (void *)flags);
 		fixup_missing_global_group();
 	}
 	cp_smbconfig_destroy();
@@ -660,16 +738,12 @@ static int __cp_parse_smbconfig(const ch
 
 int cp_parse_reload_smbconf(const char *smbconf)
 {
-	return __cp_parse_smbconfig(smbconf,
-				    groups_callback,
-				    GROUPS_CALLBACK_REINIT);
+	return __cp_parse_smbconfig(smbconf, GROUPS_CALLBACK_REINIT);
 }
 
 int cp_parse_smbconf(const char *smbconf)
 {
-	return __cp_parse_smbconfig(smbconf,
-				    groups_callback,
-				    GROUPS_CALLBACK_STARTUP_INIT);
+	return __cp_parse_smbconfig(smbconf, GROUPS_CALLBACK_STARTUP_INIT);
 }
 
 int cp_parse_pwddb(const char *pwddb)
diff -urpN ksmbd-tools-3.1.0/lib/management/session.c ksmbd-tools-3.1.0.new/lib/management/session.c
--- ksmbd-tools-3.1.0/lib/management/session.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/lib/management/session.c	2020-01-26 13:58:13.868726106 +0400
@@ -7,18 +7,17 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <glib.h>
 #include <linux/usmbd_server.h>
-
+#include <pthread.h>
 #include <management/session.h>
 #include <management/tree_conn.h>
 #include <management/user.h>
 #include <usmbdtools.h>
 
-static GHashTable	*sessions_table;
-static GRWLock		sessions_table_lock;
+static struct LIST *sessions_table;
+static pthread_rwlock_t sessions_table_lock;
 
-static void __free_func(gpointer data, gpointer user_data)
+static void __free_func(void *data, unsigned long long id, void *user_data)
 {
 	struct usmbd_tree_conn *tree_conn;
 
@@ -28,9 +27,9 @@ static void __free_func(gpointer data, g
 
 static void kill_usmbd_session(struct usmbd_session *sess)
 {
-	g_list_foreach(sess->tree_conns, __free_func, NULL);
-	g_list_free(sess->tree_conns);
-	g_rw_lock_clear(&sess->update_lock);
+	list_foreach(&sess->tree_conns, __free_func, NULL);
+	list_clear(&sess->tree_conns);
+	pthread_rwlock_destroy(&sess->update_lock);
 	free(sess);
 }
 
@@ -43,31 +42,31 @@ static struct usmbd_session *new_usmbd_s
 	if (!sess)
 		return NULL;
 
-	g_rw_lock_init(&sess->update_lock);
+	pthread_rwlock_init(&sess->update_lock, NULL);
 	sess->ref_counter = 1;
 	sess->id = id;
 	sess->user = user;
 	return sess;
 }
 
-static void free_hash_entry(gpointer k, gpointer s, gpointer user_data)
+static void free_hash_entry(void *s, unsigned long long id, void *user_data)
 {
 	kill_usmbd_session(s);
 }
 
 static void sm_clear_sessions(void)
 {
-	g_hash_table_foreach(sessions_table, free_hash_entry, NULL);
+	list_foreach(&sessions_table, free_hash_entry, NULL);
 }
 
 static int __sm_remove_session(struct usmbd_session *sess)
 {
 	int ret = -EINVAL;
 
-	g_rw_lock_writer_lock(&sessions_table_lock);
-	if (g_hash_table_remove(sessions_table, &sess->id))
+	pthread_rwlock_wrlock(&sessions_table_lock);
+	if (list_remove(&sessions_table, sess->id))
 		ret = 0;
-	g_rw_lock_writer_unlock(&sessions_table_lock);
+	pthread_rwlock_unlock(&sessions_table_lock);
 
 	if (!ret)
 		kill_usmbd_session(sess);
@@ -78,14 +77,14 @@ static struct usmbd_session *__get_sessi
 {
 	struct usmbd_session *ret = NULL;
 
-	g_rw_lock_writer_lock(&sess->update_lock);
+	pthread_rwlock_wrlock(&sess->update_lock);
 	if (sess->ref_counter != 0) {
 		sess->ref_counter++;
 		ret = sess;
 	} else {
 		ret = NULL;
 	}
-	g_rw_lock_writer_unlock(&sess->update_lock);
+	pthread_rwlock_unlock(&sess->update_lock);
 	return ret;
 }
 
@@ -93,10 +92,10 @@ static void __put_session(struct usmbd_s
 {
 	int drop = 0;
 
-	g_rw_lock_writer_lock(&sess->update_lock);
+	pthread_rwlock_wrlock(&sess->update_lock);
 	sess->ref_counter--;
 	drop = !sess->ref_counter;
-	g_rw_lock_writer_unlock(&sess->update_lock);
+	pthread_rwlock_unlock(&sess->update_lock);
 
 	if (drop)
 		__sm_remove_session(sess);
@@ -104,32 +103,21 @@ static void __put_session(struct usmbd_s
 
 static struct usmbd_session *__sm_lookup_session(unsigned long long id)
 {
-	return g_hash_table_lookup(sessions_table, &id);
+	return list_get(&sessions_table, id);
 }
 
 static struct usmbd_session *sm_lookup_session(unsigned long long id)
 {
 	struct usmbd_session *sess;
 
-	g_rw_lock_reader_lock(&sessions_table_lock);
+	pthread_rwlock_rdlock(&sessions_table_lock);
 	sess = __sm_lookup_session(id);
 	if (sess)
 		sess = __get_session(sess);
-	g_rw_lock_reader_unlock(&sessions_table_lock);
+	pthread_rwlock_unlock(&sessions_table_lock);
 	return sess;
 }
 
-static int sm_insert_session(struct usmbd_session *sess)
-{
-	int ret;
-
-	g_rw_lock_writer_lock(&sessions_table_lock);
-	ret = g_hash_table_insert(sessions_table, &(sess->id), sess);
-	g_rw_lock_writer_unlock(&sessions_table_lock);
-
-	return ret;
-}
-
 int sm_handle_tree_connect(unsigned long long id,
 			   struct usmbd_user *user,
 			   struct usmbd_tree_conn *tree_conn)
@@ -143,7 +131,7 @@ retry:
 		if (!sess)
 			return -EINVAL;
 
-		g_rw_lock_writer_lock(&sessions_table_lock);
+		pthread_rwlock_wrlock(&sessions_table_lock);
 		lookup = __sm_lookup_session(id);
 		if (lookup)
 			lookup = __get_session(lookup);
@@ -151,19 +139,19 @@ retry:
 			kill_usmbd_session(sess);
 			sess = lookup;
 		}
-		if (!g_hash_table_insert(sessions_table, &(sess->id), sess)) {
+		if (!list_add(&sessions_table, sess, sess->id)) {
 			kill_usmbd_session(sess);
 			sess = NULL;
 		}
-		g_rw_lock_writer_unlock(&sessions_table_lock);
+		pthread_rwlock_unlock(&sessions_table_lock);
 
 		if (!sess)
 			goto retry;
 	}
 
-	g_rw_lock_writer_lock(&sess->update_lock);
-	sess->tree_conns = g_list_insert(sess->tree_conns, tree_conn, -1);
-	g_rw_lock_writer_unlock(&sess->update_lock);
+	pthread_rwlock_wrlock(&sess->update_lock);
+	list_add(&sess->tree_conns, tree_conn, -1);
+	pthread_rwlock_unlock(&sess->update_lock);
 	return 0;
 }
 
@@ -174,14 +162,14 @@ int sm_check_sessions_capacity(unsigned
 	if (sm_lookup_session(id))
 		return ret;
 
-	if (g_atomic_int_add(&global_conf.sessions_cap, -1) < 1) {
+	if (atomic_int_add(&global_conf.sessions_cap, -1) < 1) {
 		ret = -EINVAL;
-		g_atomic_int_inc(&global_conf.sessions_cap);
+		atomic_int_inc(&global_conf.sessions_cap);
 	}
 	return ret;
 }
 
-static gint lookup_tree_conn(gconstpointer data, gconstpointer user_data)
+static int lookup_tree_conn(const void *data, const void *user_data)
 {
 	struct usmbd_tree_conn *tree_conn = (struct usmbd_tree_conn *)data;
 	struct usmbd_tree_conn *dummy = (struct usmbd_tree_conn *)user_data;
@@ -194,29 +182,22 @@ static gint lookup_tree_conn(gconstpoint
 int sm_handle_tree_disconnect(unsigned long long sess_id,
 			      unsigned long long tree_conn_id)
 {
-	struct usmbd_tree_conn dummy;
 	struct usmbd_session *sess;
-	GList *tc_list;
+	struct usmbd_tree_conn *tree_conn;
 
 	sess = sm_lookup_session(sess_id);
 	if (!sess)
 		return 0;
 
-	g_atomic_int_inc(&global_conf.sessions_cap);
-	g_rw_lock_writer_lock(&sess->update_lock);
-	dummy.id = tree_conn_id;
-	tc_list = g_list_find_custom(sess->tree_conns,
-				     &dummy,
-				     lookup_tree_conn);
-	if (tc_list) {
-		struct usmbd_tree_conn *tree_conn;
-
-		tree_conn = (struct usmbd_tree_conn *)tc_list->data;
-		sess->tree_conns = g_list_remove(sess->tree_conns, tree_conn);
+	atomic_int_inc(&global_conf.sessions_cap);
+	pthread_rwlock_wrlock(&sess->update_lock);
+	tree_conn = list_get(&sess->tree_conns, tree_conn_id);
+	if (tree_conn) {
+		list_remove(&sess->tree_conns, tree_conn_id);
 		sess->ref_counter--;
 		tcm_tree_conn_free(tree_conn);
 	}
-	g_rw_lock_writer_unlock(&sess->update_lock);
+	pthread_rwlock_unlock(&sess->update_lock);
 
 	__put_session(sess);
 	return 0;
@@ -226,16 +207,16 @@ void sm_destroy(void)
 {
 	if (sessions_table) {
 		sm_clear_sessions();
-		g_hash_table_destroy(sessions_table);
+		list_clear(&sessions_table);
 	}
-	g_rw_lock_clear(&sessions_table_lock);
+	pthread_rwlock_destroy(&sessions_table_lock);
 }
 
 int sm_init(void)
 {
-	sessions_table = g_hash_table_new(g_int64_hash, g_int64_equal);
+	list_init(&sessions_table);
 	if (!sessions_table)
 		return -ENOMEM;
-	g_rw_lock_init(&sessions_table_lock);
+	pthread_rwlock_init(&sessions_table_lock, NULL);
 	return 0;
 }
diff -urpN ksmbd-tools-3.1.0/lib/management/share.c ksmbd-tools-3.1.0.new/lib/management/share.c
--- ksmbd-tools-3.1.0/lib/management/share.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/lib/management/share.c	2020-01-26 13:58:13.872726058 +0400
@@ -7,7 +7,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <glib.h>
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
@@ -25,39 +24,39 @@
  * Add new entries ONLY to the bottom.
  */
 char *USMBD_SHARE_CONF[USMBD_SHARE_CONF_MAX] = {
-	"comment",				/* 0 */
+	"comment",		/* 0 */
 	"path",
 	"guest ok",
 	"guest account",
 	"read only",
-	"browseable",				/* 5 */
+	"browseable",		/* 5 */
 	"write ok",
 	"writeable",
 	"store dos attributes",
 	"oplocks",
-	"create mask",				/* 10 */
+	"create mask",		/* 10 */
 	"directory mask",
 	"force create mode",
 	"force directory mode",
 	"force group",
-	"force user",				/* 15 */
+	"force user",		/* 15 */
 	"hide dot files",
 	"valid users",
 	"invalid users",
 	"read list",
-	"write list",				/* 20 */
+	"write list",		/* 20 */
 	"admin users",
 	"hosts allow",
 	"hosts deny",
 	"max connections",
-	"veto files",				/* 25 */
+	"veto files",		/* 25 */
 	"inherit smack",
 	"inherit owner",
 	"streams",
 };
 
-static GHashTable	*shares_table;
-static GRWLock		shares_table_lock;
+static struct LIST *shares_table;
+static pthread_rwlock_t shares_table_lock;
 
 int shm_share_config(char *k, enum USMBD_SHARE_CONF c)
 {
@@ -67,30 +66,32 @@ int shm_share_config(char *k, enum USMBD
 	return !cp_key_cmp(k, USMBD_SHARE_CONF[c]);
 }
 
-static void list_hosts_callback(gpointer k, gpointer v, gpointer user_data)
+static void list_hosts_callback(void *item, unsigned long long id,
+				void *user_data)
 {
-	free(k);
-	free(v);
+	free(item);
+	free(list_fromkey(id));
 }
 
-static void free_hosts_map(GHashTable *map)
+static void free_hosts_map(struct LIST *map)
 {
 	if (map) {
-		g_hash_table_foreach(map, list_hosts_callback, NULL);
-		g_hash_table_destroy(map);
+		list_foreach(&map, list_hosts_callback, NULL);
+		list_clear(&map);
 	}
 }
 
-static void list_user_callback(gpointer k, gpointer u, gpointer user_data)
+static void list_user_callback(void *item, unsigned long long id,
+			       void *user_data)
 {
-	put_usmbd_user((struct usmbd_user *)u);
+	put_usmbd_user((struct usmbd_user *)item);
 }
 
-static void free_user_map(GHashTable *map)
+static void free_user_map(struct LIST *map)
 {
 	if (map) {
-		g_hash_table_foreach(map, list_user_callback, NULL);
-		g_hash_table_destroy(map);
+		list_foreach(&map, list_user_callback, NULL);
+		list_clear(&map);
 	}
 }
 
@@ -106,14 +107,14 @@ static void kill_usmbd_share(struct usmb
 	free_hosts_map(share->hosts_allow_map);
 	free_hosts_map(share->hosts_deny_map);
 
-	g_rw_lock_clear(&share->maps_lock);
+	pthread_rwlock_destroy(&share->maps_lock);
 
 	free(share->name);
 	free(share->path);
 	free(share->comment);
 	free(share->veto_list);
 	free(share->guest_account);
-	g_rw_lock_clear(&share->update_lock);
+	pthread_rwlock_destroy(&share->update_lock);
 	free(share);
 }
 
@@ -121,10 +122,10 @@ static int __shm_remove_share(struct usm
 {
 	int ret = -EINVAL;
 
-	g_rw_lock_writer_lock(&shares_table_lock);
-	if (g_hash_table_remove(shares_table, share->name))
+	pthread_rwlock_wrlock(&shares_table_lock);
+	if (list_remove(&shares_table, list_tokey(share->name)))
 		ret = 0;
-	g_rw_lock_writer_unlock(&shares_table_lock);
+	pthread_rwlock_unlock(&shares_table_lock);
 
 	if (!ret)
 		kill_usmbd_share(share);
@@ -133,12 +134,12 @@ static int __shm_remove_share(struct usm
 
 struct usmbd_share *get_usmbd_share(struct usmbd_share *share)
 {
-	g_rw_lock_writer_lock(&share->update_lock);
+	pthread_rwlock_wrlock(&share->update_lock);
 	if (share->ref_count != 0)
 		share->ref_count++;
 	else
 		share = NULL;
-	g_rw_lock_writer_unlock(&share->update_lock);
+	pthread_rwlock_unlock(&share->update_lock);
 
 	return share;
 }
@@ -150,10 +151,10 @@ void put_usmbd_share(struct usmbd_share
 	if (!share)
 		return;
 
-	g_rw_lock_writer_lock(&share->update_lock);
+	pthread_rwlock_wrlock(&share->update_lock);
 	share->ref_count--;
 	drop = !share->ref_count;
-	g_rw_lock_writer_unlock(&share->update_lock);
+	pthread_rwlock_unlock(&share->update_lock);
 
 	if (!drop)
 		return;
@@ -180,61 +181,61 @@ static struct usmbd_share *new_usmbd_sha
 
 	share->hosts_allow_map = NULL;
 	share->hosts_deny_map = NULL;
-	g_rw_lock_init(&share->maps_lock);
-	g_rw_lock_init(&share->update_lock);
+	pthread_rwlock_init(&share->maps_lock, NULL);
+	pthread_rwlock_init(&share->update_lock, NULL);
 
 	return share;
 }
 
-static void free_hash_entry(gpointer k, gpointer s, gpointer user_data)
+static void free_hash_entry(void *item, unsigned long long id, void *user_data)
 {
-	kill_usmbd_share(s);
+	kill_usmbd_share(item);
 }
 
 static void shm_clear_shares(void)
 {
-	g_hash_table_foreach(shares_table, free_hash_entry, NULL);
+	list_foreach(&shares_table, free_hash_entry, NULL);
 }
 
 void shm_destroy(void)
 {
 	if (shares_table) {
 		shm_clear_shares();
-		g_hash_table_destroy(shares_table);
+		list_clear(&shares_table);
 	}
-	g_rw_lock_clear(&shares_table_lock);
+	pthread_rwlock_destroy(&shares_table_lock);
 }
 
 int shm_init(void)
 {
-	shares_table = g_hash_table_new(g_str_hash, g_str_equal);
+	list_init(&shares_table);
 	if (!shares_table)
 		return -ENOMEM;
-	g_rw_lock_init(&shares_table_lock);
+	pthread_rwlock_init(&shares_table_lock, NULL);
 	return 0;
 }
 
 static struct usmbd_share *__shm_lookup_share(char *name)
 {
-	return g_hash_table_lookup(shares_table, name);
+	return (struct usmbd_share *)list_get(&shares_table, list_tokey(name));
 }
 
 struct usmbd_share *shm_lookup_share(char *name)
 {
 	struct usmbd_share *share, *ret;
 
-	g_rw_lock_reader_lock(&shares_table_lock);
+	pthread_rwlock_rdlock(&shares_table_lock);
 	share = __shm_lookup_share(name);
 	if (share) {
 		ret = get_usmbd_share(share);
 		if (!ret)
 			share = NULL;
 	}
-	g_rw_lock_reader_unlock(&shares_table_lock);
+	pthread_rwlock_unlock(&shares_table_lock);
 	return share;
 }
 
-static GHashTable *parse_list(GHashTable *map, char **list)
+static struct LIST *parse_list(struct LIST *map, char **list)
 {
 	int i;
 
@@ -242,11 +243,11 @@ static GHashTable *parse_list(GHashTable
 		return map;
 
 	if (!map)
-		map = g_hash_table_new(g_str_hash, g_str_equal);
+		list_init(&map);
 	if (!map)
 		return map;
 
-	for (i = 0;  list[i] != NULL; i++) {
+	for (i = 0; list[i] != NULL; i++) {
 		struct usmbd_user *user;
 		char *p = list[i];
 
@@ -260,12 +261,12 @@ static GHashTable *parse_list(GHashTable
 			continue;
 		}
 
-		if (g_hash_table_lookup(map, user->name)) {
+		if (list_get(&map, list_tokey(user->name))) {
 			pr_debug("User already exists in a map: %s\n", p);
 			continue;
 		}
 
-		g_hash_table_insert(map, user->name, user);
+		list_add_str(&map, user, user->name);
 	}
 
 	cp_group_kv_list_free(list);
@@ -311,11 +312,11 @@ static void force_user(struct usmbd_shar
 	}
 }
 
-static void process_group_kv(gpointer _k, gpointer _v, gpointer user_data)
+static void process_group_kv(void *_v, unsigned long long _k, void *user_data)
 {
 	struct usmbd_share *share = user_data;
-	char *k = _k;
-	char *v = _v;
+	char *k = (char *)list_fromkey(_k);
+	char *v = (char *)_v;
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_COMMENT)) {
 		share->comment = cp_get_group_kv_string(v);
@@ -341,7 +342,7 @@ static void process_group_kv(gpointer _k
 		struct usmbd_user *user;
 
 		if (usm_add_new_user(cp_get_group_kv_string(_v),
-				     g_strdup("NULL"))) {
+				     strdup("NULL"))) {
 			pr_err("Unable to add guest account\n");
 			set_share_flag(share, USMBD_SHARE_FLAG_INVALID);
 			return;
@@ -378,7 +379,7 @@ static void process_group_kv(gpointer _k
 	}
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_WRITE_OK) ||
-			shm_share_config(k, USMBD_SHARE_CONF_WRITEABLE)) {
+	    shm_share_config(k, USMBD_SHARE_CONF_WRITEABLE)) {
 		if (cp_get_group_kv_bool(v))
 			set_share_flag(share, USMBD_SHARE_FLAG_WRITEABLE);
 		else
@@ -391,7 +392,7 @@ static void process_group_kv(gpointer _k
 			set_share_flag(share, USMBD_SHARE_FLAG_STORE_DOS_ATTRS);
 		else
 			clear_share_flag(share,
-					USMBD_SHARE_FLAG_STORE_DOS_ATTRS);
+					 USMBD_SHARE_FLAG_STORE_DOS_ATTRS);
 		return;
 	}
 
@@ -438,13 +439,13 @@ static void process_group_kv(gpointer _k
 			set_share_flag(share, USMBD_SHARE_FLAG_HIDE_DOT_FILES);
 		else
 			clear_share_flag(share,
-				USMBD_SHARE_FLAG_HIDE_DOT_FILES);
+					 USMBD_SHARE_FLAG_HIDE_DOT_FILES);
 	}
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_VALID_USERS)) {
 		share->maps[USMBD_SHARE_VALID_USERS_MAP] =
-			parse_list(share->maps[USMBD_SHARE_VALID_USERS_MAP],
-				cp_get_group_kv_list(v));
+		    parse_list(share->maps[USMBD_SHARE_VALID_USERS_MAP],
+			       cp_get_group_kv_list(v));
 		if (share->maps[USMBD_SHARE_VALID_USERS_MAP] == NULL)
 			set_share_flag(share, USMBD_SHARE_FLAG_INVALID);
 		return;
@@ -452,8 +453,8 @@ static void process_group_kv(gpointer _k
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_INVALID_USERS)) {
 		share->maps[USMBD_SHARE_INVALID_USERS_MAP] =
-			parse_list(share->maps[USMBD_SHARE_INVALID_USERS_MAP],
-				cp_get_group_kv_list(v));
+		    parse_list(share->maps[USMBD_SHARE_INVALID_USERS_MAP],
+			       cp_get_group_kv_list(v));
 		if (share->maps[USMBD_SHARE_INVALID_USERS_MAP] == NULL)
 			set_share_flag(share, USMBD_SHARE_FLAG_INVALID);
 		return;
@@ -461,8 +462,8 @@ static void process_group_kv(gpointer _k
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_READ_LIST)) {
 		share->maps[USMBD_SHARE_READ_LIST_MAP] =
-			parse_list(share->maps[USMBD_SHARE_READ_LIST_MAP],
-				   cp_get_group_kv_list(v));
+		    parse_list(share->maps[USMBD_SHARE_READ_LIST_MAP],
+			       cp_get_group_kv_list(v));
 		if (share->maps[USMBD_SHARE_READ_LIST_MAP] == NULL)
 			set_share_flag(share, USMBD_SHARE_FLAG_INVALID);
 		return;
@@ -470,8 +471,8 @@ static void process_group_kv(gpointer _k
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_WRITE_LIST)) {
 		share->maps[USMBD_SHARE_WRITE_LIST_MAP] =
-			parse_list(share->maps[USMBD_SHARE_WRITE_LIST_MAP],
-				   cp_get_group_kv_list(v));
+		    parse_list(share->maps[USMBD_SHARE_WRITE_LIST_MAP],
+			       cp_get_group_kv_list(v));
 		if (share->maps[USMBD_SHARE_WRITE_LIST_MAP] == NULL)
 			set_share_flag(share, USMBD_SHARE_FLAG_INVALID);
 		return;
@@ -479,8 +480,8 @@ static void process_group_kv(gpointer _k
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_ADMIN_USERS)) {
 		share->maps[USMBD_SHARE_ADMIN_USERS_MAP] =
-			parse_list(share->maps[USMBD_SHARE_ADMIN_USERS_MAP],
-				   cp_get_group_kv_list(v));
+		    parse_list(share->maps[USMBD_SHARE_ADMIN_USERS_MAP],
+			       cp_get_group_kv_list(v));
 		if (share->maps[USMBD_SHARE_ADMIN_USERS_MAP] == NULL)
 			set_share_flag(share, USMBD_SHARE_FLAG_INVALID);
 		return;
@@ -522,28 +523,28 @@ static void process_group_kv(gpointer _k
 		if (cp_get_group_kv_bool(v))
 			set_share_flag(share, USMBD_SHARE_FLAG_INHERIT_SMACK);
 		else
-			clear_share_flag(share,	USMBD_SHARE_FLAG_INHERIT_SMACK);
+			clear_share_flag(share, USMBD_SHARE_FLAG_INHERIT_SMACK);
 	}
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_INHERIT_OWNER)) {
 		if (cp_get_group_kv_bool(v))
 			set_share_flag(share, USMBD_SHARE_FLAG_INHERIT_OWNER);
 		else
-			clear_share_flag(share,	USMBD_SHARE_FLAG_INHERIT_OWNER);
+			clear_share_flag(share, USMBD_SHARE_FLAG_INHERIT_OWNER);
 	}
 
 	if (shm_share_config(k, USMBD_SHARE_CONF_STREAMS)) {
 		if (cp_get_group_kv_bool(v))
 			set_share_flag(share, USMBD_SHARE_FLAG_STREAMS);
 		else
-			clear_share_flag(share,	USMBD_SHARE_FLAG_STREAMS);
+			clear_share_flag(share, USMBD_SHARE_FLAG_STREAMS);
 	}
 }
 
 static void init_share_from_group(struct usmbd_share *share,
-				 struct smbconf_group *group)
+				  struct smbconf_group *group)
 {
-	share->name = g_strdup(group->name);
+	share->name = strdup(group->name);
 	share->create_mask = USMBD_SHARE_DEFAULT_CREATE_MASK;
 	share->directory_mask = USMBD_SHARE_DEFAULT_DIRECTORY_MASK;
 	share->force_create_mode = 0;
@@ -560,7 +561,7 @@ static void init_share_from_group(struct
 	if (!cp_key_cmp(share->name, "IPC$"))
 		set_share_flag(share, USMBD_SHARE_FLAG_PIPE);
 
-	g_hash_table_foreach(group->kv, process_group_kv, share);
+	list_foreach(&(group->kv), process_group_kv, share);
 }
 
 int shm_add_new_share(struct smbconf_group *group)
@@ -578,25 +579,24 @@ int shm_add_new_share(struct smbconf_gro
 		return 0;
 	}
 
-	g_rw_lock_writer_lock(&shares_table_lock);
+	pthread_rwlock_wrlock(&shares_table_lock);
 	if (__shm_lookup_share(share->name)) {
-		g_rw_lock_writer_unlock(&shares_table_lock);
+		pthread_rwlock_unlock(&shares_table_lock);
 		pr_info("share exists %s\n", share->name);
 		kill_usmbd_share(share);
 		return 0;
 	}
 
-	if (!g_hash_table_insert(shares_table, share->name, share)) {
+	if (!list_add_str(&shares_table, share, share->name)) {
 		kill_usmbd_share(share);
 		ret = -EINVAL;
 	}
-	g_rw_lock_writer_unlock(&shares_table_lock);
+	pthread_rwlock_unlock(&shares_table_lock);
 	return ret;
 }
 
 int shm_lookup_users_map(struct usmbd_share *share,
-			  enum share_users map,
-			  char *name)
+			 enum share_users map, char *name)
 {
 	int ret = -ENOENT;
 
@@ -608,10 +608,10 @@ int shm_lookup_users_map(struct usmbd_sh
 	if (!share->maps[map])
 		return -EINVAL;
 
-	g_rw_lock_reader_lock(&share->maps_lock);
-	if (g_hash_table_lookup(share->maps[map], name))
+	pthread_rwlock_rdlock(&share->maps_lock);
+	if (list_get(&share->maps[map], list_tokey(name)))
 		ret = 0;
-	g_rw_lock_reader_unlock(&share->maps_lock);
+	pthread_rwlock_unlock(&share->maps_lock);
 
 	return ret;
 }
@@ -621,10 +621,9 @@ int shm_lookup_users_map(struct usmbd_sh
  * Do a real hosts lookup. IP masks, etc.
  */
 int shm_lookup_hosts_map(struct usmbd_share *share,
-			  enum share_hosts map,
-			  char *host)
+			 enum share_hosts map, char *host)
 {
-	GHashTable *lookup_map;
+	struct LIST *lookup_map;
 	int ret = -ENOENT;
 
 	if (map >= USMBD_SHARE_HOSTS_MAX) {
@@ -640,10 +639,10 @@ int shm_lookup_hosts_map(struct usmbd_sh
 	if (!lookup_map)
 		return -EINVAL;
 
-	g_rw_lock_reader_lock(&share->maps_lock);
-	if (g_hash_table_lookup(lookup_map, host))
+	pthread_rwlock_rdlock(&share->maps_lock);
+	if (list_get(&lookup_map, list_tokey(host)))
 		ret = 0;
-	g_rw_lock_reader_unlock(&share->maps_lock);
+	pthread_rwlock_unlock(&share->maps_lock);
 
 	return ret;
 }
@@ -652,13 +651,13 @@ int shm_open_connection(struct usmbd_sha
 {
 	int ret = 0;
 
-	g_rw_lock_writer_lock(&share->update_lock);
+	pthread_rwlock_wrlock(&share->update_lock);
 	share->num_connections++;
 	if (share->max_connections) {
 		if (share->num_connections >= share->max_connections)
 			ret = -EINVAL;
 	}
-	g_rw_lock_writer_unlock(&share->update_lock);
+	pthread_rwlock_unlock(&share->update_lock);
 	return ret;
 }
 
@@ -667,17 +666,17 @@ int shm_close_connection(struct usmbd_sh
 	if (!share)
 		return 0;
 
-	g_rw_lock_writer_lock(&share->update_lock);
+	pthread_rwlock_wrlock(&share->update_lock);
 	share->num_connections--;
-	g_rw_lock_writer_unlock(&share->update_lock);
+	pthread_rwlock_unlock(&share->update_lock);
 	return 0;
 }
 
-void for_each_usmbd_share(walk_shares cb, gpointer user_data)
+void foreach_usmbd_share(walk_shares cb, void *user_data)
 {
-	g_rw_lock_reader_lock(&shares_table_lock);
-	g_hash_table_foreach(shares_table, cb, user_data);
-	g_rw_lock_reader_unlock(&shares_table_lock);
+	pthread_rwlock_rdlock(&shares_table_lock);
+	list_foreach(&shares_table, cb, user_data);
+	pthread_rwlock_unlock(&shares_table_lock);
 }
 
 int shm_share_config_payload_size(struct usmbd_share *share)
@@ -721,16 +720,12 @@ int shm_handle_share_config_request(stru
 
 	config_payload = USMBD_SHARE_CONFIG_VETO_LIST(resp);
 	if (resp->veto_list_sz) {
-		memcpy(config_payload,
-		       share->veto_list,
-		       resp->veto_list_sz);
+		memcpy(config_payload, share->veto_list, resp->veto_list_sz);
 		config_payload += resp->veto_list_sz + 1;
 	}
 	if (global_conf.root_dir)
 		sprintf(config_payload,
-			"%s%s",
-			global_conf.root_dir,
-			share->path);
+			"%s%s", global_conf.root_dir, share->path);
 	else
 		sprintf(config_payload, "%s", share->path);
 	return 0;
diff -urpN ksmbd-tools-3.1.0/lib/management/tree_conn.c ksmbd-tools-3.1.0.new/lib/management/tree_conn.c
--- ksmbd-tools-3.1.0/lib/management/tree_conn.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/lib/management/tree_conn.c	2020-01-26 15:34:56.345726417 +0400
@@ -7,7 +7,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <glib.h>
 #include <linux/usmbd_server.h>
 
 #include <management/tree_conn.h>
diff -urpN ksmbd-tools-3.1.0/lib/management/user.c ksmbd-tools-3.1.0.new/lib/management/user.c
--- ksmbd-tools-3.1.0/lib/management/user.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/lib/management/user.c	2020-01-26 13:58:13.872726058 +0400
@@ -7,14 +7,14 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <glib.h>
+#include <pthread.h>
 #include <linux/usmbd_server.h>
 
 #include <management/user.h>
 #include <usmbdtools.h>
 
-static GHashTable	*users_table;
-static GRWLock		users_table_lock;
+static struct LIST *users_table;
+static pthread_rwlock_t users_table_lock;
 
 static void kill_usmbd_user(struct usmbd_user *user)
 {
@@ -23,7 +23,7 @@ static void kill_usmbd_user(struct usmbd
 	free(user->name);
 	free(user->pass_b64);
 	free(user->pass);
-	g_rw_lock_clear(&user->update_lock);
+	pthread_rwlock_destroy(&user->update_lock);
 	free(user);
 }
 
@@ -31,10 +31,10 @@ static int __usm_remove_user(struct usmb
 {
 	int ret = -EINVAL;
 
-	g_rw_lock_writer_lock(&users_table_lock);
-	if (g_hash_table_remove(users_table, user->name))
+	pthread_rwlock_wrlock(&users_table_lock);
+	if (list_remove(&users_table, list_tokey(user->name)))
 		ret = 0;
-	g_rw_lock_writer_unlock(&users_table_lock);
+	pthread_rwlock_unlock(&users_table_lock);
 
 	if (!ret)
 		kill_usmbd_user(user);
@@ -43,12 +43,12 @@ static int __usm_remove_user(struct usmb
 
 struct usmbd_user *get_usmbd_user(struct usmbd_user *user)
 {
-	g_rw_lock_writer_lock(&user->update_lock);
+	pthread_rwlock_wrlock(&user->update_lock);
 	if (user->ref_count != 0)
 		user->ref_count++;
 	else
 		user = NULL;
-	g_rw_lock_writer_unlock(&user->update_lock);
+	pthread_rwlock_unlock(&user->update_lock);
 	return user;
 }
 
@@ -59,10 +59,10 @@ void put_usmbd_user(struct usmbd_user *u
 	if (!user)
 		return;
 
-	g_rw_lock_writer_lock(&user->update_lock);
+	pthread_rwlock_wrlock(&user->update_lock);
 	user->ref_count--;
 	drop = !user->ref_count;
-	g_rw_lock_writer_unlock(&user->update_lock);
+	pthread_rwlock_unlock(&user->update_lock);
 
 	if (!drop)
 		return;
@@ -80,7 +80,7 @@ static struct usmbd_user *new_usmbd_user
 	if (!user)
 		return NULL;
 
-	g_rw_lock_clear(&user->update_lock);
+	pthread_rwlock_destroy(&user->update_lock);
 	user->name = name;
 	user->pass_b64 = pwd;
 	user->ref_count = 1;
@@ -97,37 +97,37 @@ static struct usmbd_user *new_usmbd_user
 	return user;
 }
 
-static void free_hash_entry(gpointer k, gpointer u, gpointer user_data)
+static void free_hash_entry(void *u, unsigned long long id, void *user_data)
 {
 	kill_usmbd_user(u);
 }
 
 static void usm_clear_users(void)
 {
-	g_hash_table_foreach(users_table, free_hash_entry, NULL);
+	list_foreach(&users_table, free_hash_entry, NULL);
 }
 
 void usm_destroy(void)
 {
 	if (users_table) {
 		usm_clear_users();
-		g_hash_table_destroy(users_table);
+		list_clear(&users_table);
 	}
-	g_rw_lock_clear(&users_table_lock);
+	pthread_rwlock_destroy(&users_table_lock);
 }
 
 int usm_init(void)
 {
-	users_table = g_hash_table_new(g_str_hash, g_str_equal);
+	list_init(&users_table);
 	if (!users_table)
 		return -ENOMEM;
-	g_rw_lock_init(&users_table_lock);
+	pthread_rwlock_init(&users_table_lock, NULL);
 	return 0;
 }
 
 static struct usmbd_user *__usm_lookup_user(char *name)
 {
-	return g_hash_table_lookup(users_table, name);
+	return list_get(&users_table, list_tokey(name));
 }
 
 struct usmbd_user *usm_lookup_user(char *name)
@@ -137,14 +137,14 @@ struct usmbd_user *usm_lookup_user(char
 	if (!name)
 		return NULL;
 
-	g_rw_lock_reader_lock(&users_table_lock);
+	pthread_rwlock_rdlock(&users_table_lock);
 	user = __usm_lookup_user(name);
 	if (user) {
 		ret = get_usmbd_user(user);
 		if (!ret)
 			user = NULL;
 	}
-	g_rw_lock_reader_unlock(&users_table_lock);
+	pthread_rwlock_unlock(&users_table_lock);
 	return user;
 }
 
@@ -159,19 +159,18 @@ int usm_add_new_user(char *name, char *p
 		return -ENOMEM;
 	}
 
-	g_rw_lock_writer_lock(&users_table_lock);
+	pthread_rwlock_wrlock(&users_table_lock);
 	if (__usm_lookup_user(name)) {
-		g_rw_lock_writer_unlock(&users_table_lock);
+		pthread_rwlock_unlock(&users_table_lock);
 		pr_info("User already exists %s\n", name);
 		kill_usmbd_user(user);
 		return 0;
 	}
-
-	if (!g_hash_table_insert(users_table, user->name, user)) {
+	if (!list_add_str(&users_table, user, user->name)) {
 		kill_usmbd_user(user);
 		ret = -EINVAL;
 	}
-	g_rw_lock_writer_unlock(&users_table_lock);
+	pthread_rwlock_unlock(&users_table_lock);
 	return ret;
 }
 
@@ -189,8 +188,8 @@ int usm_add_update_user_from_pwdentry(ch
 	}
 
 	*pos = 0x00;
-	name = g_strdup(data);
-	pwd = g_strdup(pos + 1);
+	name = strdup(data);
+	pwd = strdup(pos + 1);
 
 	if (!name || !pwd) {
 		free(name);
@@ -210,17 +209,17 @@ int usm_add_update_user_from_pwdentry(ch
 	return usm_add_new_user(name, pwd);
 }
 
-void for_each_usmbd_user(walk_users cb, gpointer user_data)
+void foreach_usmbd_user(walk_users cb, void *user_data)
 {
-	g_rw_lock_reader_lock(&users_table_lock);
-	g_hash_table_foreach(users_table, cb, user_data);
-	g_rw_lock_reader_unlock(&users_table_lock);
+	pthread_rwlock_rdlock(&users_table_lock);
+	list_foreach(&users_table, cb, user_data);
+	pthread_rwlock_unlock(&users_table_lock);
 }
 
 int usm_update_user_password(struct usmbd_user *user, char *pswd)
 {
 	size_t pass_sz;
-	char *pass_b64 = g_strdup(pswd);
+	char *pass_b64 = strdup(pswd);
 	char *pass = base64_decode(pass_b64, &pass_sz);
 
 	if (!pass_b64 || !pass) {
@@ -231,13 +230,13 @@ int usm_update_user_password(struct usmb
 	}
 
 	pr_debug("Update user password: %s\n", user->name);
-	g_rw_lock_writer_lock(&user->update_lock);
+	pthread_rwlock_wrlock(&user->update_lock);
 	free(user->pass_b64);
 	free(user->pass);
 	user->pass_b64 = pass_b64;
 	user->pass = pass;
 	user->pass_sz = (int)pass_sz;
-	g_rw_lock_writer_unlock(&user->update_lock);
+	pthread_rwlock_unlock(&user->update_lock);
 
 	return 0;
 }
@@ -251,12 +250,12 @@ static int usm_copy_user_passhash(struct
 	if (test_user_flag(user, USMBD_USER_FLAG_GUEST_ACCOUNT))
 		return 0;
 
-	g_rw_lock_reader_lock(&user->update_lock);
+	pthread_rwlock_rdlock(&user->update_lock);
 	if (sz >= user->pass_sz) {
 		memcpy(pass, user->pass, user->pass_sz);
 		ret = user->pass_sz;
 	}
-	g_rw_lock_reader_unlock(&user->update_lock);
+	pthread_rwlock_unlock(&user->update_lock);
 
 	return ret;
 }
diff -urpN ksmbd-tools-3.1.0/lib/usmbdtools.c ksmbd-tools-3.1.0.new/lib/usmbdtools.c
--- ksmbd-tools-3.1.0/lib/usmbdtools.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/lib/usmbdtools.c	2020-01-27 13:31:02.065751274 +0400
@@ -6,15 +6,206 @@
  */
 
 #include <syslog.h>
-#include <glib/gi18n.h>
+#include <iconv.h>
 
 #include <unistd.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <ctype.h>
 
 #include <stdio.h>
+#include <stdarg.h>
 #include <usmbdtools.h>
 
+/*
+ * special simple linked list implementation, just made for the need of usmbd.
+ * not yet optimized
+ */
+
+struct LIST *list_init(struct LIST **list)
+{
+	*list = malloc(sizeof(struct LIST));
+	if (!*list)
+		return NULL;
+	(*list)->prev = NULL;
+	(*list)->next = NULL;
+	return *list;
+}
+
+long long list_maxid(struct LIST **list)
+{
+	long long id = -1;
+	struct LIST *head = *list;
+
+	while ((head = head->next)) {
+		if (((long long)head->id) >= id)
+			id = head->id;
+	}
+	return id;
+}
+
+int list_foreach(struct LIST **list,
+		 void (*func)(void *item, unsigned long long id,
+			      void *user_data), void *user_data)
+{
+	struct LIST *head = *list;
+
+	while ((head = head->next)) {
+		if (head->type == KEY_STRING)
+			func(head->item, list_tokey(head->keystr), user_data);
+		else
+			func(head->item, head->id, user_data);
+	}
+}
+
+struct LIST *head_get(struct LIST **list, unsigned long long id)
+{
+	struct LIST *head = *list;
+	struct LIST *last = NULL;
+
+	head = *list;
+	while ((head = head->next)) {
+		if (head == last) {
+			/* should not happen. if this triggers we have a bug */
+			pr_debug("fixup list\n");
+			head->next = NULL;
+			break;
+		}
+		last = head;
+		if (head->type == KEY_STRING) {
+			char *c = (char *)list_fromkey(id);
+
+			if (!strcmp(head->keystr, c))
+				return head;
+		} else {
+			if (head->id == id)
+				return head;
+		}
+	}
+	return NULL;
+}
+
+int _list_add(struct LIST **list, void *item, unsigned long long id, char *str)
+{
+	int ret = 1;
+	struct LIST *new;
+
+	if (!*list)
+		list_init(list);
+	new = head_get(list, str ? list_tokey(str) : id);
+	if (new)
+		ret = 0;
+	if (!new)
+		new = malloc(sizeof(struct LIST));
+	if (!new)
+		return 0;
+
+	new->item = item;
+	if (ret) {
+		if (str) {
+			new->keystr = str;
+			new->type = KEY_STRING;
+		} else {
+			new->id = id;
+			new->type = KEY_ID;
+		}
+		new->next = NULL;
+		struct LIST *head = *list;
+		struct LIST *last = head;
+
+		while ((head = head->next))
+			last = head;
+
+		last->next = new;
+		new->prev = last;
+	}
+	return ret;
+}
+
+int list_add(struct LIST **list, void *item, unsigned long long id)
+{
+	return _list_add(list, item, id, NULL);
+}
+
+int list_add_str(struct LIST **list, void *item, char *str)
+{
+	return _list_add(list, item, 0, str);
+}
+
+void list_append(struct LIST **list, void *item)
+{
+	_list_add(list, item, list_maxid(list) + 1, NULL);
+}
+
+int _list_remove(struct LIST **list, unsigned long long id, int dec)
+{
+	int ret = 0;
+	struct LIST *head = *list;
+	struct LIST *next = NULL;
+
+	while ((head = head->next)) {
+		if ((head->type == KEY_ID && head->id == id)
+		    || (head->type == KEY_STRING
+			&& !strcmp(head->keystr, list_fromkey(id)))) {
+			if (head->prev)
+				head->prev->next = head->next;
+
+			if (head->next) {
+				next = head->next;
+				head->next->prev = head->prev;
+			}
+
+			free(head);
+			ret = 1;
+			goto out;
+		}
+	}
+out:
+	if (dec && !ret && next) {
+		/* reorder all following ids after removing slot */
+		while (next) {
+			next->id = next->prev->id + 1;
+			next = next->next;
+		}
+	}
+	return ret;
+}
+
+int list_remove_dec(struct LIST **list, unsigned long long id)
+{
+	return _list_remove(list, id, 1);
+}
+
+int list_remove(struct LIST **list, unsigned long long id)
+{
+	return _list_remove(list, id, 0);
+}
+
+void *list_get(struct LIST **list, unsigned long long id)
+{
+	struct LIST *head = head_get(list, id);
+
+	if (head)
+		return head->item;
+	return NULL;
+}
+
+void list_clear(struct LIST **list)
+{
+	struct LIST *head = *list;
+
+	if (head)
+		return;
+
+	while (head) {
+		struct LIST *h = head->next;
+
+		free(head);
+		head = h;
+	}
+	*list = NULL;
+}
+
 static const char *app_name = "unknown";
 static int log_open;
 
@@ -137,40 +328,233 @@ void pr_hex_dump(const void *mem, size_t
 }
 #endif
 
+void base64_init_encodestate(base64_encodestate *state_in)
+{
+	state_in->step = step_A;
+	state_in->result = 0;
+	state_in->stepcount = 0;
+}
+
+char base64_encode_value(char value_in)
+{
+	static const char *encoding =
+	    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+	if (value_in > 63)
+		return '=';
+	return encoding[(int)value_in];
+}
+
+int base64_encode_block(const char *plaintext_in, int length_in, char *code_out,
+			base64_encodestate *state_in)
+{
+	const char *plainchar = plaintext_in;
+	const char *const plaintextend = plaintext_in + length_in;
+	char *codechar = code_out;
+	char result;
+	char fragment;
+
+	result = state_in->result;
+
+	switch (state_in->step) {
+		while (1) {
+		case step_A:
+			if (plainchar == plaintextend) {
+				state_in->result = result;
+				state_in->step = step_A;
+				return codechar - code_out;
+			}
+			fragment = *plainchar++;
+			result = (fragment & 0x0fc) >> 2;
+			*codechar++ = base64_encode_value(result);
+			result = (fragment & 0x003) << 4;
+		case step_B:
+			if (plainchar == plaintextend) {
+				state_in->result = result;
+				state_in->step = step_B;
+				return codechar - code_out;
+			}
+			fragment = *plainchar++;
+			result |= (fragment & 0x0f0) >> 4;
+			*codechar++ = base64_encode_value(result);
+			result = (fragment & 0x00f) << 2;
+		case step_C:
+			if (plainchar == plaintextend) {
+				state_in->result = result;
+				state_in->step = step_C;
+				return codechar - code_out;
+			}
+			fragment = *plainchar++;
+			result |= (fragment & 0x0c0) >> 6;
+			*codechar++ = base64_encode_value(result);
+			result = (fragment & 0x03f) >> 0;
+			*codechar++ = base64_encode_value(result);
+
+			++(state_in->stepcount);
+		}
+	}
+	/* control should not reach here */
+	return codechar - code_out;
+}
+
+int base64_encode_blockend(char *code_out, base64_encodestate *state_in)
+{
+	char *codechar = code_out;
+
+	switch (state_in->step) {
+	case step_B:
+		*codechar++ = base64_encode_value(state_in->result);
+		break;
+	case step_C:
+		*codechar++ = base64_encode_value(state_in->result);
+		break;
+	case step_A:
+		break;
+	}
+	*codechar++ = 0;
+	return codechar - code_out;
+}
+
 char *base64_encode(unsigned char *src, size_t srclen)
 {
-	return g_base64_encode(src, srclen);
+	char *out = malloc((srclen / 3 + 1) * 4 + 1);
+	base64_encodestate state;
+
+	base64_init_encodestate(&state);
+	int len = base64_encode_block(src, srclen, out, &state);
+
+	base64_encode_blockend(out + len, &state);
+	return out;
+}
+
+int base64_decode_value(char value_in)
+{
+	static const char decoding[] = {
+		62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1,
+		-1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+		    12, 13, 14, 15, 16, 17,
+		18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27,
+		    28, 29, 30, 31, 32, 33,
+		34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+		    50, 51
+	};
+	static const char decoding_size = sizeof(decoding);
+
+	value_in -= 43;
+	if (value_in < 0 || value_in > decoding_size)
+		return -1;
+	return decoding[(int)value_in];
+}
+
+void base64_init_decodestate(base64_decodestate *state_in)
+{
+	state_in->step = step_a;
+	state_in->plainchar = 0;
+}
+
+int base64_decode_block(const char *code_in, int length_in, char *plaintext_out,
+			const int outlen, base64_decodestate *state_in)
+{
+	const char *codechar = code_in;
+	char *plainchar = plaintext_out;
+	char fragment;
+	int count = 0;
+
+	*plainchar = state_in->plainchar;
+
+	switch (state_in->step) {
+		while (1) {
+		case step_a:
+			do {
+				if (codechar == code_in + length_in) {
+					state_in->step = step_a;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment =
+				    (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			if (count > outlen)
+				return plainchar - plaintext_out;
+			*plainchar = (fragment & 0x03f) << 2;
+		case step_b:
+			do {
+				if (codechar == code_in + length_in) {
+					state_in->step = step_b;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment =
+				    (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			count += 1;
+			if (count > outlen)
+				return plainchar - plaintext_out;
+			*plainchar++ |= (fragment & 0x030) >> 4;
+			*plainchar = (fragment & 0x00f) << 4;
+		case step_c:
+			do {
+				if (codechar == code_in + length_in) {
+					state_in->step = step_c;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment =
+				    (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			count += 1;
+			if (count > outlen)
+				return plainchar - plaintext_out;
+			*plainchar++ |= (fragment & 0x03c) >> 2;
+			*plainchar = (fragment & 0x003) << 6;
+		case step_d:
+			do {
+				if (codechar == code_in + length_in) {
+					state_in->step = step_d;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment =
+				    (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			count++;
+			if (count > outlen)
+				return plainchar - plaintext_out;
+			*plainchar++ |= (fragment & 0x03f);
+		}
+	}
+	/* control should not reach here */
+	return plainchar - plaintext_out;
 }
 
 unsigned char *base64_decode(char const *src, size_t *dstlen)
 {
-	unsigned char *ret = g_base64_decode(src, dstlen);
+	base64_decodestate state;
 
-	if (ret)
-		ret[*dstlen] = 0x00;
-	return ret;
+	base64_init_decodestate(&state);
+	int len = ((strlen(src) / 4) * 3) + 1;
+	char *out = malloc(len);
+	*dstlen = base64_decode_block(src, strlen(src), out, len, &state);
+	return out;
 }
 
 static int codeset_has_altname(int codeset)
 {
 	if (codeset == USMBD_CHARSET_UTF16LE ||
-			codeset == USMBD_CHARSET_UTF16BE)
+	    codeset == USMBD_CHARSET_UTF16BE)
 		return 1;
 	return 0;
 }
 
-gchar *usmbd_gconvert(const gchar *str,
-		      gssize       str_len,
-		      int          to_codeset,
-		      int          from_codeset,
-		      gsize       *bytes_read,
-		      gsize       *bytes_written)
+char *usmbd_gconvert(const char *str, size_t str_len, int to_codeset,
+		     int from_codeset, size_t *bytes_read,
+		     size_t *bytes_written)
 {
-	gchar *converted;
-	GError *err;
+	char *converted, *buf;
+	int err;
 
 retry:
-	err = NULL;
+	err = 0;
 	if (from_codeset >= USMBD_CHARSET_MAX) {
 		pr_err("Unknown source codeset: %d\n", from_codeset);
 		return NULL;
@@ -180,15 +564,19 @@ retry:
 		pr_err("Unknown target codeset: %d\n", to_codeset);
 		return NULL;
 	}
-
-	converted = g_convert(str,
-			      str_len,
-			      usmbd_conv_charsets[to_codeset],
-			      usmbd_conv_charsets[from_codeset],
-			      bytes_read,
-			      bytes_written,
-			      &err);
-	if (err) {
+	buf = converted = malloc((str_len * 2) + 1);
+	memset(converted, 0, (str_len * 2) + 1);
+	iconv_t conv = iconv_open(usmbd_conv_charsets[to_codeset],
+				  usmbd_conv_charsets[from_codeset]);
+	*bytes_read = str_len;
+	*bytes_written = str_len * 2;
+	err = iconv(conv, (char **)&str, bytes_read, &converted, bytes_written);
+	*bytes_read = 0;
+	err = iconv(conv, NULL, bytes_read, &converted, bytes_written);
+	iconv_close(conv);
+	*bytes_written = (str_len * 2) - *bytes_written;
+	*bytes_read = str_len - *bytes_read;
+	if (err < 0) {
 		int has_altname = 0;
 
 		if (codeset_has_altname(to_codeset)) {
@@ -201,9 +589,6 @@ retry:
 			has_altname = 1;
 		}
 
-		pr_info("%s\n", err->message);
-		g_error_free(err);
-
 		if (has_altname) {
 			pr_info("Will try '%s' and '%s'\n",
 				usmbd_conv_charsets[to_codeset],
@@ -211,17 +596,66 @@ retry:
 			goto retry;
 		}
 
-		pr_err("Can't convert string: %s\n", err->message);
-		g_error_free(err);
 		return NULL;
 	}
 
-	return converted;
+	return buf;
+}
+
+static pthread_mutex_t atomic_lock = PTHREAD_MUTEX_INITIALIZER;
+
+int atomic_int_add(volatile int *atomic, int val)
+{
+	int oldval;
+
+	pthread_mutex_lock(&atomic_lock);
+	oldval = *atomic;
+	*atomic = oldval + val;
+	pthread_mutex_unlock(&atomic_lock);
+	return oldval;
+}
+
+void atomic_int_inc(volatile int *atomic)
+{
+	pthread_mutex_lock(&atomic_lock);
+	(*atomic)++;
+	pthread_mutex_unlock(&atomic_lock);
+}
+
+int atomic_int_compare_and_exchange(volatile int *atomic, int oldval,
+				    int newval)
+{
+	int success;
+
+	pthread_mutex_lock(&atomic_lock);
+	success = (*atomic == oldval);
+	if (success)
+		*atomic = newval;
+
+	pthread_mutex_unlock(&atomic_lock);
+
+	return success;
+}
+
+char *ascii_strdown(char *str, size_t len)
+{
+	char *result, *s;
+
+	if (!str)
+		return NULL;
+
+	if (len < 0)
+		len = strlen(str);
+
+	result = strndup(str, len);
+	for (s = result; *s; s++)
+		*s = tolower(*s);
+	return result;
 }
 
 void notify_usmbd_daemon(void)
 {
-	char manager_pid[10] = {0, };
+	char manager_pid[10] = { 0, };
 	int pid = 0;
 	int lock_fd;
 
diff -urpN ksmbd-tools-3.1.0/smbshareadd/Makefile.am ksmbd-tools-3.1.0.new/smbshareadd/Makefile.am
--- ksmbd-tools-3.1.0/smbshareadd/Makefile.am	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/smbshareadd/Makefile.am	2020-01-25 02:06:37.334284742 +0400
@@ -1,6 +1,6 @@
 AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(LIBNL_CFLAGS) -fno-common
 LIBS = $(GLIB_LIBS)
-smbshareadd_LDADD = $(top_builddir)/lib/libusmbdtools.la
+smbshareadd_LDADD = $(top_builddir)/lib/libusmbdtools.la -lpthread
 
 sbin_PROGRAMS = smbshareadd
 
diff -urpN ksmbd-tools-3.1.0/smbshareadd/share_admin.c ksmbd-tools-3.1.0.new/smbshareadd/share_admin.c
--- ksmbd-tools-3.1.0/smbshareadd/share_admin.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/smbshareadd/share_admin.c	2020-01-26 13:58:13.876726005 +0400
@@ -5,7 +5,6 @@
  *   linux-cifsd-devel@lists.sourceforge.net
  */
 
-#include <glib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -34,7 +33,7 @@ static char *new_group_name(char *name)
 	if (strchr(name, '['))
 		return name;
 
-	gn = g_malloc(strlen(name) + 3);
+	gn = malloc(strlen(name) + 3);
 	if (gn)
 		sprintf(gn, "[%s]", name);
 	return gn;
@@ -44,7 +43,7 @@ static char *aux_group_name(char *name)
 {
 	char *gn;
 
-	gn = g_malloc(strlen(name) + 3 + strlen(AUX_GROUP_PREFIX));
+	gn = malloc(strlen(name) + 3 + strlen(AUX_GROUP_PREFIX));
 	if (gn)
 		sprintf(gn, "[%s%s]", AUX_GROUP_PREFIX, name);
 	return gn;
@@ -85,16 +84,15 @@ static void __write(void)
 	}
 }
 
-static void __write_share(gpointer key, gpointer value, gpointer buf)
+static void __write_share(void *value, unsigned long long key, void *buf)
 {
-	char *k = (char *)key;
+	char *k = (char *)list_fromkey(key);
 	char *v = (char *)value;
 
 	wsz = snprintf(wbuf, sizeof(wbuf), "\t%s = %s\n", k, v);
 	if (wsz > sizeof(wbuf)) {
 		pr_err("smb.conf entry size is above the limit: %zu > %zu\n",
-			wsz,
-			sizeof(wbuf));
+		       wsz, sizeof(wbuf));
 		exit(EXIT_FAILURE);
 	}
 	__write();
@@ -106,10 +104,11 @@ static void write_share(struct smbconf_g
 
 	wsz = snprintf(wbuf, sizeof(wbuf), "[%s]\n", g->name);
 	__write();
-	g_hash_table_foreach(g->kv, __write_share, NULL);
+	list_foreach(&g->kv, __write_share, NULL);
 }
 
-static void write_share_cb(gpointer key, gpointer value, gpointer share_data)
+static void write_share_cb(void *value, unsigned long long key,
+			   void *share_data)
 {
 	struct smbconf_group *g = (struct smbconf_group *)value;
 
@@ -120,13 +119,12 @@ static void write_share_cb(gpointer key,
 		write_share(g);
 }
 
-static void write_remove_share_cb(gpointer key,
-				  gpointer value,
-				  gpointer name)
+static void write_remove_share_cb(void *value,
+				  unsigned long long key, void *name)
 {
 	struct smbconf_group *g = (struct smbconf_group *)value;
 
-	if (!g_ascii_strcasecmp(g->name, name)) {
+	if (!strcasecmp(g->name, name)) {
 		pr_info("share '%s' removed\n", g->name);
 		return;
 	}
@@ -134,26 +132,25 @@ static void write_remove_share_cb(gpoint
 	write_share(g);
 }
 
-static void update_share_cb(gpointer key,
-			    gpointer value,
-			    gpointer g)
+static void update_share_cb(void *value, unsigned long long key, void *g)
 {
+	struct LIST *list = (struct LIST *)g;
 	char *nk, *nv;
 
-	nk = g_strdup(key);
-	nv = g_strdup(value);
+	nk = strdup(list_fromkey(key));
+	nv = strdup(value);
 	if (!nk || !nv)
 		exit(EXIT_FAILURE);
 
 	/* This will call .dtor for already existing key/value pairs */
-	g_hash_table_insert(g, nk, nv);
+	list_add_str(&list, nv, nk);
 }
 
 int command_add_share(char *smbconf, char *name, char *opts)
 {
 	char *new_name = NULL;
 
-	if (g_hash_table_lookup(parser.groups, name)) {
+	if (list_get(&parser.groups, list_tokey(name))) {
 		pr_err("Share already exists: %s\n", name);
 		return -EEXIST;
 	}
@@ -164,13 +161,13 @@ int command_add_share(char *smbconf, cha
 
 	if (__open_smbconf(smbconf))
 		goto error;
-	g_hash_table_foreach(parser.groups, write_share_cb, NULL);
+	list_foreach(&parser.groups, write_share_cb, NULL);
 	close(conf_fd);
-	g_free(new_name);
+	free(new_name);
 	return 0;
 
 error:
-	g_free(new_name);
+	free(new_name);
 	return -EINVAL;
 }
 
@@ -180,7 +177,7 @@ int command_update_share(char *smbconf,
 	struct smbconf_group *update_group;
 	char *aux_name = NULL;
 
-	existing_group = g_hash_table_lookup(parser.groups, name);
+	existing_group = list_get(&parser.groups, list_tokey(name));
 	if (!existing_group) {
 		pr_err("Unknown share: %s\n", name);
 		goto error;
@@ -192,26 +189,24 @@ int command_update_share(char *smbconf,
 
 	/* get rid of [] */
 	sprintf(aux_name, "%s%s", AUX_GROUP_PREFIX, name);
-	update_group = g_hash_table_lookup(parser.groups, aux_name);
+	update_group = list_get(&parser.groups, list_tokey(aux_name));
 	if (!update_group) {
 		pr_err("Cannot find the external group\n");
 		goto error;
 	}
 
-	g_hash_table_foreach(update_group->kv,
-			     update_share_cb,
-			     existing_group->kv);
+	list_foreach(&update_group->kv, update_share_cb, existing_group->kv);
 
 	if (__open_smbconf(smbconf))
 		goto error;
 
-	g_hash_table_foreach(parser.groups, write_share_cb, NULL);
+	list_foreach(&parser.groups, write_share_cb, NULL);
 	close(conf_fd);
-	g_free(aux_name);
+	free(aux_name);
 	return 0;
 
 error:
-	g_free(aux_name);
+	free(aux_name);
 	return -EINVAL;
 }
 
@@ -220,9 +215,7 @@ int command_del_share(char *smbconf, cha
 	if (__open_smbconf(smbconf))
 		return -EINVAL;
 
-	g_hash_table_foreach(parser.groups,
-			     write_remove_share_cb,
-			     name);
+	list_foreach(&parser.groups, write_remove_share_cb, (void *)name);
 	close(conf_fd);
 	return 0;
 }
diff -urpN ksmbd-tools-3.1.0/smbshareadd/smbshareadd.c ksmbd-tools-3.1.0.new/smbshareadd/smbshareadd.c
--- ksmbd-tools-3.1.0/smbshareadd/smbshareadd.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/smbshareadd/smbshareadd.c	2020-01-25 02:01:29.299043469 +0400
@@ -4,8 +4,6 @@
  *
  *   linux-cifsd-devel@lists.sourceforge.net
  */
-
-#include <glib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -109,15 +107,15 @@ int main(int argc, char *argv[])
 	while ((c = getopt(argc, argv, "c:a:d:u:p:o:Vvh")) != EOF)
 		switch (c) {
 		case 'a':
-			arg_name = g_ascii_strdown(optarg, strlen(optarg));
+			arg_name = ascii_strdown(optarg, strlen(optarg));
 			cmd = COMMAND_ADD_SHARE;
 			break;
 		case 'd':
-			arg_name = g_ascii_strdown(optarg, strlen(optarg));
+			arg_name = ascii_strdown(optarg, strlen(optarg));
 			cmd = COMMAND_DEL_SHARE;
 			break;
 		case 'u':
-			arg_name = g_ascii_strdown(optarg, strlen(optarg));
+			arg_name = ascii_strdown(optarg, strlen(optarg));
 			cmd = COMMAND_UPDATE_SHARE;
 			break;
 		case 'c':
diff -urpN ksmbd-tools-3.1.0/smbuseradd/Makefile.am ksmbd-tools-3.1.0.new/smbuseradd/Makefile.am
--- ksmbd-tools-3.1.0/smbuseradd/Makefile.am	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/smbuseradd/Makefile.am	2020-01-25 02:06:13.558651236 +0400
@@ -1,6 +1,6 @@
 AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(LIBNL_CFLAGS) -fno-common
 LIBS = $(GLIB_LIBS)
-smbuseradd_LDADD = $(top_builddir)/lib/libusmbdtools.la
+smbuseradd_LDADD = $(top_builddir)/lib/libusmbdtools.la -lpthread
 
 sbin_PROGRAMS = smbuseradd
 
diff -urpN ksmbd-tools-3.1.0/smbuseradd/smbuseradd.c ksmbd-tools-3.1.0.new/smbuseradd/smbuseradd.c
--- ksmbd-tools-3.1.0/smbuseradd/smbuseradd.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/smbuseradd/smbuseradd.c	2020-01-26 13:58:13.876726005 +0400
@@ -5,7 +5,6 @@
  *   linux-cifsd-devel@lists.sourceforge.net
  */
 
-#include <glib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -26,8 +25,8 @@
 
 #include <linux/usmbd_server.h>
 
-static char *arg_account = NULL;
-static char *arg_password = NULL;
+static char *arg_account;
+static char *arg_password;
 
 enum {
 	COMMAND_ADD_USER = 1,
@@ -107,22 +106,22 @@ int main(int argc, char *argv[])
 	while ((c = getopt(argc, argv, "c:i:a:d:u:p:Vvh")) != EOF)
 		switch (c) {
 		case 'a':
-			arg_account = g_strdup(optarg);
+			arg_account = strdup(optarg);
 			cmd = COMMAND_ADD_USER;
 			break;
 		case 'd':
-			arg_account = g_strdup(optarg);
+			arg_account = strdup(optarg);
 			cmd = COMMAND_DEL_USER;
 			break;
 		case 'u':
-			arg_account = g_strdup(optarg);
+			arg_account = strdup(optarg);
 			cmd = COMMAND_UPDATE_USER;
 			break;
 		case 'p':
-			arg_password = g_strdup(optarg);
+			arg_password = strdup(optarg);
 			break;
 		case 'i':
-			pwddb = g_strdup(optarg);
+			pwddb = strdup(optarg);
 			break;
 		case 'V':
 			show_version();
@@ -133,7 +132,7 @@ int main(int argc, char *argv[])
 		case 'h':
 		default:
 			usage();
-	}
+		}
 
 	if (sanity_check_user_name_simple(arg_account)) {
 		pr_err("User name sanity check failure\n");
diff -urpN ksmbd-tools-3.1.0/smbuseradd/user_admin.c ksmbd-tools-3.1.0.new/smbuseradd/user_admin.c
--- ksmbd-tools-3.1.0/smbuseradd/user_admin.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/smbuseradd/user_admin.c	2020-01-26 13:58:13.876726005 +0400
@@ -5,7 +5,6 @@
  *   linux-cifsd-devel@lists.sourceforge.net
  */
 
-#include <glib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -26,8 +25,8 @@
 
 #define MAX_NT_PWD_LEN 129
 
-static char *arg_account = NULL;
-static char *arg_password = NULL;
+static char *arg_account;
+static char *arg_password;
 static int conf_fd = -1;
 static char wbuf[2 * MAX_NT_PWD_LEN + 2 * USMBD_REQ_MAX_ACCOUNT_NAME_SZ];
 
@@ -136,8 +135,8 @@ static char *get_utf8_password(long *len
 {
 	size_t raw_sz;
 	char *pswd_raw, *pswd_converted;
-	gsize bytes_read = 0;
-	gsize bytes_written = 0;
+	size_t bytes_read = 0;
+	size_t bytes_written = 0;
 
 	pswd_raw = prompt_password(&raw_sz);
 	if (!pswd_raw)
@@ -237,30 +236,30 @@ static void write_user(struct usmbd_user
 	}
 }
 
-static void write_user_cb(gpointer key, gpointer value, gpointer user_data)
+static void write_user_cb(void *value, unsigned long long id, void *user_data)
 {
 	struct usmbd_user *user = (struct usmbd_user *)value;
 
 	write_user(user);
 }
 
-static void write_remove_user_cb(gpointer key,
-				 gpointer value,
-				 gpointer user_data)
+static void write_remove_user_cb(void *value,
+				 unsigned long long key,
+				 void *user_data)
 {
 	struct usmbd_user *user = (struct usmbd_user *)value;
 
-	if (!g_ascii_strcasecmp(user->name, arg_account)) {
+	if (!strcasecmp(user->name, arg_account)) {
 		pr_info("User '%s' removed\n", user->name);
 		return;
 	}
 
-	write_user_cb(key, value, user_data);
+	write_user_cb(value, key, user_data);
 }
 
-static void lookup_can_del_user(gpointer key,
-				gpointer value,
-				gpointer user_data)
+static void lookup_can_del_user(void *value,
+				unsigned long long key,
+				void *user_data)
 {
 	struct usmbd_share *share = (struct usmbd_share *)value;
 	int ret = 0;
@@ -327,7 +326,7 @@ int command_add_user(char *pwddb, char *
 	if (__opendb_file(pwddb))
 		return -EINVAL;
 
-	for_each_usmbd_user(write_user_cb, NULL);
+	foreach_usmbd_user(write_user_cb, NULL);
 	close(conf_fd);
 	return 0;
 }
@@ -366,7 +365,7 @@ int command_update_user(char *pwddb, cha
 	if (__opendb_file(pwddb))
 		return -EINVAL;
 
-	for_each_usmbd_user(write_user_cb, NULL);
+	foreach_usmbd_user(write_user_cb, NULL);
 	close(conf_fd);
 	return 0;
 }
@@ -382,7 +381,7 @@ int command_del_user(char *pwddb, char *
 		return -EINVAL;
 	}
 
-	for_each_usmbd_share(lookup_can_del_user, &abort_del_user);
+	foreach_usmbd_share(lookup_can_del_user, &abort_del_user);
 
 	if (abort_del_user) {
 		pr_err("Aborting user deletion\n");
@@ -392,7 +391,7 @@ int command_del_user(char *pwddb, char *
 	if (__opendb_file(pwddb))
 		return -EINVAL;
 
-	for_each_usmbd_user(write_remove_user_cb, NULL);
+	foreach_usmbd_user(write_remove_user_cb, NULL);
 	close(conf_fd);
 	return 0;
 }
diff -urpN ksmbd-tools-3.1.0/usmbd/Makefile.am ksmbd-tools-3.1.0.new/usmbd/Makefile.am
--- ksmbd-tools-3.1.0/usmbd/Makefile.am	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/usmbd/Makefile.am	2020-01-25 02:05:57.746895560 +0400
@@ -1,6 +1,6 @@
 AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(LIBNL_CFLAGS) -fno-common
 LIBS = $(GLIB_LIBS) $(LIBNL_LIBS)
-usmbd_LDADD = $(top_builddir)/lib/libusmbdtools.la
+usmbd_LDADD = $(top_builddir)/lib/libusmbdtools.la -lpthread
 
 sbin_PROGRAMS = usmbd
 
diff -urpN ksmbd-tools-3.1.0/usmbd/ipc.c ksmbd-tools-3.1.0.new/usmbd/ipc.c
--- ksmbd-tools-3.1.0/usmbd/ipc.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/usmbd/ipc.c	2020-01-25 02:01:29.299043469 +0400
@@ -6,7 +6,6 @@
  */
 
 #include <memory.h>
-#include <glib.h>
 #include <errno.h>
 #include <netlink/netlink.h>
 #include <netlink/msg.h>
diff -urpN ksmbd-tools-3.1.0/usmbd/multicall.c ksmbd-tools-3.1.0.new/usmbd/multicall.c
diff -urpN ksmbd-tools-3.1.0/usmbd/rpc.c ksmbd-tools-3.1.0.new/usmbd/rpc.c
--- ksmbd-tools-3.1.0/usmbd/rpc.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/usmbd/rpc.c	2020-01-26 13:58:13.876726005 +0400
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identi	fier: GPL-2.0-or-later
 /*
  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
  *
@@ -7,17 +7,17 @@
 
 #include <memory.h>
 #include <endian.h>
-#include <glib.h>
 #include <errno.h>
 #include <linux/usmbd_server.h>
 
 #include <rpc.h>
 #include <rpc_srvsvc.h>
 #include <rpc_wkssvc.h>
+#include <pthread.h>
 #include <usmbdtools.h>
 
-static GHashTable	*pipes_table;
-static GRWLock		pipes_table_lock;
+static struct LIST *pipes_table;
+static pthread_rwlock_t pipes_table_lock;
 
 /*
  * Version 2.0 data representation protocol
@@ -35,31 +35,31 @@ static GRWLock		pipes_table_lock;
  * Interface: SRVSVC UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188
  */
 struct dcerpc_syntax_table {
-	struct dcerpc_syntax	syn;
-	int			ack_result;
+	struct dcerpc_syntax syn;
+	int ack_result;
 };
 
 static struct dcerpc_syntax_table known_syntaxes[] = {
 	{
-		.syn.uuid.time_low = 0x8a885d04,
-		.syn.uuid.time_mid = 0x1ceb,
-		.syn.uuid.time_hi_and_version = 0x11c9,
-		.syn.uuid.clock_seq = {0x9f, 0xe8},
-		.syn.uuid.node = {0x8, 0x0, 0x2b, 0x10, 0x48, 0x60},
-		.syn.ver_major = 0x2,
-		.syn.ver_minor = 0x0,
-		.ack_result = DCERPC_BIND_ACK_RES_ACCEPT,
-	},
+	 .syn.uuid.time_low = 0x8a885d04,
+	 .syn.uuid.time_mid = 0x1ceb,
+	 .syn.uuid.time_hi_and_version = 0x11c9,
+	 .syn.uuid.clock_seq = { 0x9f, 0xe8},
+	 .syn.uuid.node = { 0x8, 0x0, 0x2b, 0x10, 0x48, 0x60},
+	 .syn.ver_major = 0x2,
+	 .syn.ver_minor = 0x0,
+	 .ack_result = DCERPC_BIND_ACK_RES_ACCEPT,
+	  },
 	{
-		.syn.uuid.time_low = 0x6CB71C2C,
-		.syn.uuid.time_mid = 0x9812,
-		.syn.uuid.time_hi_and_version = 0x4540,
-		.syn.uuid.clock_seq = {0x0, 0x0},
-		.syn.uuid.node = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
-		.syn.ver_major = 0x1,
-		.syn.ver_minor = 0x0,
-		.ack_result = DCERPC_BIND_ACK_RES_NEGOTIATE_ACK,
-	},
+	 .syn.uuid.time_low = 0x6CB71C2C,
+	 .syn.uuid.time_mid = 0x9812,
+	 .syn.uuid.time_hi_and_version = 0x4540,
+	 .syn.uuid.clock_seq = { 0x0, 0x0},
+	 .syn.uuid.node = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+	 .syn.ver_major = 0x1,
+	 .syn.ver_minor = 0x0,
+	 .ack_result = DCERPC_BIND_ACK_RES_NEGOTIATE_ACK,
+	  },
 };
 
 /*
@@ -99,9 +99,9 @@ static struct usmbd_rpc_pipe *rpc_pipe_l
 {
 	struct usmbd_rpc_pipe *pipe;
 
-	g_rw_lock_reader_lock(&pipes_table_lock);
-	pipe = g_hash_table_lookup(pipes_table, &id);
-	g_rw_lock_reader_unlock(&pipes_table_lock);
+	pthread_rwlock_wrlock(&pipes_table_lock);
+	pipe = list_get(&pipes_table, id);
+	pthread_rwlock_unlock(&pipes_table_lock);
 
 	return pipe;
 }
@@ -137,8 +137,7 @@ static struct usmbd_dcerpc *dcerpc_alloc
 }
 
 static struct usmbd_dcerpc *dcerpc_ext_alloc(unsigned int flags,
-					     void *payload,
-					     int payload_sz)
+					     void *payload, int payload_sz)
 {
 	struct usmbd_dcerpc *dce;
 
@@ -179,16 +178,16 @@ static void __rpc_pipe_free(struct usmbd
 	rpc_pipe_reset(pipe);
 	if (pipe->dce)
 		dcerpc_free(pipe->dce);
-	g_array_free(pipe->entries, 1);
+	list_clear(&pipe->entries);
 	free(pipe);
 }
 
 static void rpc_pipe_free(struct usmbd_rpc_pipe *pipe)
 {
 	if (pipe->id != (unsigned int)-1) {
-		g_rw_lock_writer_lock(&pipes_table_lock);
-		g_hash_table_remove(pipes_table, &(pipe->id));
-		g_rw_lock_writer_unlock(&pipes_table_lock);
+		pthread_rwlock_wrlock(&pipes_table_lock);
+		list_remove(&pipes_table, pipe->id);
+		pthread_rwlock_unlock(&pipes_table_lock);
 	}
 
 	__rpc_pipe_free(pipe);
@@ -203,7 +202,7 @@ static struct usmbd_rpc_pipe *rpc_pipe_a
 		return NULL;
 
 	pipe->id = -1;
-	pipe->entries = g_array_new(0, 0, sizeof(void *));
+	list_init(&pipe->entries);
 	if (!pipe->entries) {
 		rpc_pipe_free(pipe);
 		return NULL;
@@ -220,28 +219,28 @@ static struct usmbd_rpc_pipe *rpc_pipe_a
 		return NULL;
 
 	pipe->id = id;
-	g_rw_lock_writer_lock(&pipes_table_lock);
-	ret = g_hash_table_insert(pipes_table, &(pipe->id), pipe);
-	g_rw_lock_writer_unlock(&pipes_table_lock);
-
+	pthread_rwlock_wrlock(&pipes_table_lock);
+	ret = list_add(&pipes_table, pipe, pipe->id);
 	if (!ret) {
 		pipe->id = (unsigned int)-1;
 		rpc_pipe_free(pipe);
 		pipe = NULL;
 	}
+	pthread_rwlock_unlock(&pipes_table_lock);
+
 	return pipe;
 }
 
-static void free_hash_entry(gpointer k, gpointer s, gpointer user_data)
+static void free_hash_entry(void *s, unsigned long long id, void *user_data)
 {
 	__rpc_pipe_free(s);
 }
 
 static void __clear_pipes_table(void)
 {
-	g_rw_lock_writer_lock(&pipes_table_lock);
-	g_hash_table_foreach(pipes_table, free_hash_entry, NULL);
-	g_rw_lock_writer_unlock(&pipes_table_lock);
+	pthread_rwlock_wrlock(&pipes_table_lock);
+	list_foreach(&pipes_table, free_hash_entry, NULL);
+	pthread_rwlock_unlock(&pipes_table_lock);
 }
 
 static void align_offset(struct usmbd_dcerpc *dce, size_t n)
@@ -305,7 +304,7 @@ int ndr_write_##name(struct usmbd_dcerpc
 	return 0;							\
 }
 
-NDR_WRITE_INT(int8,  __u8, htobe_n, htole_n);
+NDR_WRITE_INT(int8, __u8, htobe_n, htole_n);
 NDR_WRITE_INT(int16, __u16, htobe16, htole16);
 NDR_WRITE_INT(int32, __u32, htobe32, htole32);
 NDR_WRITE_INT(int64, __u64, htobe64, htole64);
@@ -324,7 +323,7 @@ type ndr_read_##name(struct usmbd_dcerpc
 	return ret;							\
 }
 
-NDR_READ_INT(int8,  __u8, betoh_n, letoh_n);
+NDR_READ_INT(int8, __u8, betoh_n, letoh_n);
 NDR_READ_INT(int16, __u16, be16toh, le16toh);
 NDR_READ_INT(int32, __u32, be32toh, le32toh);
 NDR_READ_INT(int64, __u64, be64toh, le64toh);
@@ -384,9 +383,9 @@ int ndr_read_bytes(struct usmbd_dcerpc *
 
 int ndr_write_vstring(struct usmbd_dcerpc *dce, char *value)
 {
-	gchar *out;
-	gsize bytes_read = 0;
-	gsize bytes_written = 0;
+	char *out;
+	size_t bytes_read = 0;
+	size_t bytes_written = 0;
 
 	size_t raw_len;
 	char *raw_value = value;
@@ -407,8 +406,7 @@ int ndr_write_vstring(struct usmbd_dcerp
 			     raw_len,
 			     charset,
 			     USMBD_CHARSET_DEFAULT,
-			     &bytes_read,
-			     &bytes_written);
+			     &bytes_read, &bytes_written);
 	if (!out)
 		return -EINVAL;
 
@@ -428,21 +426,21 @@ int ndr_write_vstring(struct usmbd_dcerp
 	ret |= ndr_write_bytes(dce, out, bytes_written);
 	auto_align_offset(dce);
 
-	g_free(out);
+	free(out);
 	return ret;
 }
 
 char *ndr_read_vstring(struct usmbd_dcerpc *dce)
 {
-	gchar *out;
-	gsize bytes_read = 0;
-	gsize bytes_written = 0;
+	char *out;
+	size_t bytes_read = 0;
+	size_t bytes_written = 0;
 
 	size_t raw_len;
 	int charset = USMBD_CHARSET_UTF16LE;
 
 	raw_len = ndr_read_int32(dce);
-	ndr_read_int32(dce); /* read in offset */
+	ndr_read_int32(dce);	/* read in offset */
 	ndr_read_int32(dce);
 
 	if (!(dce->flags & USMBD_DCERPC_LITTLE_ENDIAN))
@@ -459,9 +457,7 @@ char *ndr_read_vstring(struct usmbd_dcer
 	out = usmbd_gconvert(PAYLOAD_HEAD(dce),
 			     raw_len * 2,
 			     USMBD_CHARSET_DEFAULT,
-			     charset,
-			     &bytes_read,
-			     &bytes_written);
+			     charset, &bytes_read, &bytes_written);
 	if (!out)
 		return NULL;
 
@@ -528,9 +524,8 @@ static int __max_entries(struct usmbd_dc
 
 	current_size = 0;
 	for (i = 0; i < pipe->num_entries; i++) {
-		gpointer entry;
+		void *entry = list_get(&pipe->entries, i);
 
-		entry = g_array_index(pipe->entries,  gpointer, i);
 		current_size += dce->entry_size(dce, entry);
 
 		if (current_size < 4 * dce->payload_sz / 5)
@@ -547,21 +542,18 @@ int __ndr_write_array_of_structs(struct
 	int i;
 
 	for (i = 0; i < max_entry_nr; i++) {
-		gpointer entry;
+		void *entry = list_get(&pipe->entries, i);
 
-		entry = g_array_index(pipe->entries,  gpointer, i);
 		if (dce->entry_rep(dce, entry))
 			return USMBD_RPC_EBAD_DATA;
 	}
 
 	for (i = 0; i < max_entry_nr; i++) {
-		gpointer entry;
+		void *entry = list_get(&pipe->entries, i);
 
-		entry = g_array_index(pipe->entries,  gpointer, i);
 		if (dce->entry_data(dce, entry))
 			return USMBD_RPC_EBAD_DATA;
 	}
-
 	if (pipe->entry_processed) {
 		for (i = 0; i < max_entry_nr; i++)
 			pipe->entry_processed(pipe, 0);
@@ -627,10 +619,10 @@ int ndr_write_array_of_structs(struct us
 
 int rpc_init(void)
 {
-	pipes_table = g_hash_table_new(g_int_hash, g_int_equal);
+	list_init(&pipes_table);
 	if (!pipes_table)
 		return -ENOMEM;
-	g_rw_lock_init(&pipes_table_lock);
+	pthread_rwlock_init(&pipes_table_lock, NULL);
 	return 0;
 }
 
@@ -638,13 +630,12 @@ void rpc_destroy(void)
 {
 	if (pipes_table) {
 		__clear_pipes_table();
-		g_hash_table_destroy(pipes_table);
+		list_clear(&pipes_table);
 	}
-	g_rw_lock_clear(&pipes_table_lock);
+	pthread_rwlock_destroy(&pipes_table_lock);
 }
 
-static int dcerpc_hdr_write(struct usmbd_dcerpc *dce,
-			    struct dcerpc_header *hdr)
+static int dcerpc_hdr_write(struct usmbd_dcerpc *dce, struct dcerpc_header *hdr)
 {
 	ndr_write_int8(dce, hdr->rpc_vers);
 	ndr_write_int8(dce, hdr->rpc_vers_minor);
@@ -657,8 +648,7 @@ static int dcerpc_hdr_write(struct usmbd
 	return 0;
 }
 
-static int dcerpc_hdr_read(struct usmbd_dcerpc *dce,
-			   struct dcerpc_header *hdr)
+static int dcerpc_hdr_read(struct usmbd_dcerpc *dce, struct dcerpc_header *hdr)
 {
 	/* Common Type Header for the Serialization Stream */
 
@@ -908,7 +898,7 @@ static int dcerpc_bind_ack_return(struct
 
 	ndr_write_int16(dce, strlen(addr));
 	ndr_write_bytes(dce, addr, strlen(addr));
-	align_offset(dce, 4); /* [flag(NDR_ALIGN4)]    DATA_BLOB _pad1; */
+	align_offset(dce, 4);	/* [flag(NDR_ALIGN4)]    DATA_BLOB _pad1; */
 
 	num_trans = dce->bi_req.num_contexts;
 	ndr_write_int8(dce, num_trans);
@@ -968,7 +958,7 @@ static int dcerpc_bind_return(struct usm
 
 	if (!ack) {
 		pr_err("Unsupported transfer syntax\n");
-		ret =  dcerpc_bind_nack_return(pipe);
+		ret = dcerpc_bind_nack_return(pipe);
 	} else {
 		ret = dcerpc_bind_ack_return(pipe);
 	}
@@ -986,20 +976,19 @@ int rpc_restricted_context(struct usmbd_
 }
 
 int rpc_ioctl_request(struct usmbd_rpc_command *req,
-		      struct usmbd_rpc_command *resp,
-		      int max_resp_sz)
+		      struct usmbd_rpc_command *resp, int max_resp_sz)
 {
 	int ret;
 
 	ret = rpc_write_request(req, resp);
 	if (ret == USMBD_RPC_OK)
-		return rpc_read_request(req, resp, max_resp_sz);
+		ret = rpc_read_request(req, resp, max_resp_sz);
+
 	return ret;
 }
 
 int rpc_read_request(struct usmbd_rpc_command *req,
-		     struct usmbd_rpc_command *resp,
-		     int max_resp_sz)
+		     struct usmbd_rpc_command *resp, int max_resp_sz)
 {
 	int ret = USMBD_RPC_ENOTIMPLEMENTED;
 	struct usmbd_rpc_pipe *pipe;
@@ -1008,7 +997,7 @@ int rpc_read_request(struct usmbd_rpc_co
 	pipe = rpc_pipe_lookup(req->handle);
 	if (!pipe || !pipe->dce) {
 		pr_err("RPC: no pipe or pipe has no associated DCE [%d]\n",
-			req->handle);
+		       req->handle);
 		return USMBD_RPC_EBAD_FID;
 	}
 
@@ -1047,7 +1036,7 @@ int rpc_write_request(struct usmbd_rpc_c
 
 	if (pipe->num_entries)
 		pr_err("RPC: A call on unflushed pipe. Pending %d\n",
-			pipe->num_entries);
+		       pipe->num_entries);
 
 	dce = pipe->dce;
 	dce->rpc_req = req;
@@ -1092,8 +1081,7 @@ int rpc_open_request(struct usmbd_rpc_co
 
 	pipe->dce = dcerpc_ext_alloc(USMBD_DCERPC_LITTLE_ENDIAN |
 				     USMBD_DCERPC_ALIGN4,
-				     req->payload,
-				     req->payload_sz);
+				     req->payload, req->payload_sz);
 	if (!pipe->dce) {
 		rpc_pipe_free(pipe);
 		return USMBD_RPC_ENOMEM;
diff -urpN ksmbd-tools-3.1.0/usmbd/rpc_srvsvc.c ksmbd-tools-3.1.0.new/usmbd/rpc_srvsvc.c
--- ksmbd-tools-3.1.0/usmbd/rpc_srvsvc.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/usmbd/rpc_srvsvc.c	2020-01-26 13:58:13.876726005 +0400
@@ -7,7 +7,6 @@
 
 #include <memory.h>
 #include <endian.h>
-#include <glib.h>
 #include <errno.h>
 #include <linux/usmbd_server.h>
 
@@ -40,19 +39,19 @@ static int __share_type(struct usmbd_sha
 {
 	if (test_share_flag(share, USMBD_SHARE_FLAG_PIPE))
 		return SHARE_TYPE_IPC;
-	if (!g_ascii_strncasecmp(share->name, "IPC", strlen("IPC")))
+	if (!strncasecmp(share->name, "IPC", strlen("IPC")))
 		return SHARE_TYPE_IPC;
 	return SHARE_TYPE_DISKTREE;
 }
 
-static int __share_entry_size_ctr0(struct usmbd_dcerpc *dce, gpointer entry)
+static int __share_entry_size_ctr0(struct usmbd_dcerpc *dce, void *entry)
 {
 	struct usmbd_share *share = entry;
 
 	return strlen(share->name) * 2 + 4 * sizeof(__u32);
 }
 
-static int __share_entry_size_ctr1(struct usmbd_dcerpc *dce, gpointer entry)
+static int __share_entry_size_ctr1(struct usmbd_dcerpc *dce, void *entry)
 {
 	struct usmbd_share *share = entry;
 	int sz = 0;
@@ -71,33 +70,33 @@ static int __share_entry_size_ctr1(struc
  * An embedded reference pointer is represented in two parts, a 4 octet
  * value in place and a possibly deferred representation of the referent.
  */
-static int __share_entry_rep_ctr0(struct usmbd_dcerpc *dce, gpointer entry)
+static int __share_entry_rep_ctr0(struct usmbd_dcerpc *dce, void *entry)
 {
 	dce->num_pointers++;
-	return ndr_write_int32(dce, dce->num_pointers); /* ref pointer */
+	return ndr_write_int32(dce, dce->num_pointers);	/* ref pointer */
 }
 
-static int __share_entry_rep_ctr1(struct usmbd_dcerpc *dce, gpointer entry)
+static int __share_entry_rep_ctr1(struct usmbd_dcerpc *dce, void *entry)
 {
 	struct usmbd_share *share = entry;
 	int ret;
 
 	dce->num_pointers++;
-	ret = ndr_write_int32(dce, dce->num_pointers); /* ref pointer */
+	ret = ndr_write_int32(dce, dce->num_pointers);	/* ref pointer */
 	ret |= ndr_write_int32(dce, __share_type(share));
 	dce->num_pointers++;
-	ret |= ndr_write_int32(dce, dce->num_pointers); /* ref pointer */
+	ret |= ndr_write_int32(dce, dce->num_pointers);	/* ref pointer */
 	return ret;
 }
 
-static int __share_entry_data_ctr0(struct usmbd_dcerpc *dce, gpointer entry)
+static int __share_entry_data_ctr0(struct usmbd_dcerpc *dce, void *entry)
 {
 	struct usmbd_share *share = entry;
 
 	return ndr_write_vstring(dce, share->name);
 }
 
-static int __share_entry_data_ctr1(struct usmbd_dcerpc *dce, gpointer entry)
+static int __share_entry_data_ctr1(struct usmbd_dcerpc *dce, void *entry)
 {
 	struct usmbd_share *share = entry;
 	int ret;
@@ -107,20 +106,18 @@ static int __share_entry_data_ctr1(struc
 	return ret;
 }
 
-static int __share_entry_null_rep_ctr0(struct usmbd_dcerpc *dce,
-				       gpointer entry)
+static int __share_entry_null_rep_ctr0(struct usmbd_dcerpc *dce, void *entry)
 {
-	return ndr_write_int32(dce, 0); /* ref pointer */
+	return ndr_write_int32(dce, 0);	/* ref pointer */
 }
 
-static int __share_entry_null_rep_ctr1(struct usmbd_dcerpc *dce,
-				       gpointer entry)
+static int __share_entry_null_rep_ctr1(struct usmbd_dcerpc *dce, void *entry)
 {
 	int ret;
 
-	ret = ndr_write_int32(dce, 0); /* ref pointer */
+	ret = ndr_write_int32(dce, 0);	/* ref pointer */
 	ret |= ndr_write_int32(dce, 0);
-	ret |= ndr_write_int32(dce, 0); /* ref pointer */
+	ret |= ndr_write_int32(dce, 0);	/* ref pointer */
 	return ret;
 }
 
@@ -128,8 +125,9 @@ static int __share_entry_processed(struc
 {
 	struct usmbd_share *share;
 
-	share = g_array_index(pipe->entries,  gpointer, i);
-	pipe->entries = g_array_remove_index(pipe->entries, i);
+	share = list_get(&pipe->entries, i);
+
+	list_remove_dec(&pipe->entries, i);
 	pipe->num_entries--;
 	pipe->num_processed++;
 	put_usmbd_share(share);
@@ -137,7 +135,8 @@ static int __share_entry_processed(struc
 	return 0;
 }
 
-static void __enum_all_shares(gpointer key, gpointer value, gpointer user_data)
+static void __enum_all_shares(void *value, unsigned long long id,
+			      void *user_data)
 {
 	struct usmbd_rpc_pipe *pipe = (struct usmbd_rpc_pipe *)user_data;
 	struct usmbd_share *share = (struct usmbd_share *)value;
@@ -154,14 +153,13 @@ static void __enum_all_shares(gpointer k
 		put_usmbd_share(share);
 		return;
 	}
-
-	pipe->entries = g_array_append_val(pipe->entries, share);
+	list_append(&pipe->entries, share);
 	pipe->num_entries++;
 }
 
 static int srvsvc_share_enum_all_invoke(struct usmbd_rpc_pipe *pipe)
 {
-	for_each_usmbd_share(__enum_all_shares, pipe);
+	foreach_usmbd_share(__enum_all_shares, pipe);
 	pipe->entry_processed = __share_entry_processed;
 	return 0;
 }
@@ -199,7 +197,7 @@ static int srvsvc_share_get_info_invoke(
 		}
 	}
 
-	pipe->entries = g_array_append_val(pipe->entries, share);
+	list_append(&pipe->entries, share);
 	pipe->num_entries++;
 	pipe->entry_processed = __share_entry_processed;
 	return 0;
@@ -253,7 +251,7 @@ static int srvsvc_share_get_info_return(
 		dce->entry_rep = __share_entry_null_rep_ctr1;
 	} else {
 		pr_err("Unsupported share info level (read): %d\n",
-			dce->si_req.level);
+		       dce->si_req.level);
 		dce->entry_rep = NULL;
 		return USMBD_RPC_EINVALID_LEVEL;
 	}
@@ -277,13 +275,12 @@ static int srvsvc_parse_share_info_req(s
 		hdr->level = ndr_read_union_int32(dce);
 		if (hdr->level == -EINVAL)
 			return -EINVAL;
-		ndr_read_int32(dce); // read container pointer ref id
-		ndr_read_int32(dce); // read container array size
-		ptr = ndr_read_int32(dce); // read container array pointer
-					   // it should be null
+		ndr_read_int32(dce);	// read container pointer ref id
+		ndr_read_int32(dce);	// read container array size
+		ptr = ndr_read_int32(dce);	// read container array pointer
+		// it should be null
 		if (ptr != 0x00) {
-			pr_err("SRVSVC: container array pointer is %x\n",
-				ptr);
+			pr_err("SRVSVC: container array pointer is %x\n", ptr);
 			return -EINVAL;
 		}
 		hdr->max_size = ndr_read_int32(dce);
@@ -320,8 +317,7 @@ static int srvsvc_share_info_invoke(stru
 	return ret;
 }
 
-static int srvsvc_clear_headers(struct usmbd_rpc_pipe *pipe,
-				int status)
+static int srvsvc_clear_headers(struct usmbd_rpc_pipe *pipe, int status)
 {
 	if (status == USMBD_RPC_EMORE_DATA)
 		return 0;
@@ -358,12 +354,13 @@ static int srvsvc_share_info_return(stru
 		dce->entry_data = __share_entry_data_ctr1;
 	} else {
 		pr_err("Unsupported share info level (write): %d\n",
-			dce->si_req.level);
+		       dce->si_req.level);
 		rpc_pipe_reset(pipe);
 	}
 
 	if (dce->req_hdr.opnum == SRVSVC_OPNUM_GET_SHARE_INFO)
 		status = srvsvc_share_get_info_return(pipe);
+
 	if (dce->req_hdr.opnum == SRVSVC_OPNUM_SHARE_ENUM_ALL)
 		status = srvsvc_share_enum_all_return(pipe);
 
@@ -404,8 +401,7 @@ static int srvsvc_invoke(struct usmbd_rp
 }
 
 static int srvsvc_return(struct usmbd_rpc_pipe *pipe,
-			 struct usmbd_rpc_command *resp,
-			 int max_resp_sz)
+			 struct usmbd_rpc_command *resp, int max_resp_sz)
 {
 	struct usmbd_dcerpc *dce = pipe->dce;
 	int ret;
@@ -422,7 +418,7 @@ static int srvsvc_return(struct usmbd_rp
 		break;
 	default:
 		pr_err("SRVSVC: unsupported RETURN method %d\n",
-			dce->req_hdr.opnum);
+		       dce->req_hdr.opnum);
 		ret = USMBD_RPC_EBAD_FUNC;
 		break;
 	}
@@ -430,8 +426,7 @@ static int srvsvc_return(struct usmbd_rp
 }
 
 int rpc_srvsvc_read_request(struct usmbd_rpc_pipe *pipe,
-			    struct usmbd_rpc_command *resp,
-			    int max_resp_sz)
+			    struct usmbd_rpc_command *resp, int max_resp_sz)
 {
 	return srvsvc_return(pipe, resp, max_resp_sz);
 }
diff -urpN ksmbd-tools-3.1.0/usmbd/rpc_wkssvc.c ksmbd-tools-3.1.0.new/usmbd/rpc_wkssvc.c
--- ksmbd-tools-3.1.0/usmbd/rpc_wkssvc.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/usmbd/rpc_wkssvc.c	2020-01-25 02:01:29.299043469 +0400
@@ -7,7 +7,6 @@
 
 #include <memory.h>
 #include <endian.h>
-#include <glib.h>
 #include <errno.h>
 #include <linux/usmbd_server.h>
 
@@ -36,7 +35,7 @@ static int wkssvc_clear_headers(struct u
 }
 
 static int __netwksta_entry_rep_ctr100(struct usmbd_dcerpc *dce,
-				       gpointer entry)
+				       void *entry)
 {
 	int ret = 0;
 
@@ -58,7 +57,7 @@ static int __netwksta_entry_rep_ctr100(s
 }
 
 static int __netwksta_entry_data_ctr100(struct usmbd_dcerpc *dce,
-					gpointer entry)
+					void *entry)
 {
 	int ret = 0;
 
diff -urpN ksmbd-tools-3.1.0/usmbd/usmbd.c ksmbd-tools-3.1.0.new/usmbd/usmbd.c
--- ksmbd-tools-3.1.0/usmbd/usmbd.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/usmbd/usmbd.c	2020-01-26 13:58:13.876726005 +0400
@@ -30,7 +30,7 @@
 #include <management/session.h>
 #include <management/tree_conn.h>
 
-static int no_detach = 0;
+static int no_detach;
 int usmbd_health_status;
 static pid_t worker_pid;
 static int lock_fd = -1;
@@ -216,15 +216,15 @@ static void worker_process_free(void)
 	 */
 	ipc_destroy();
 	rpc_destroy();
-	wp_destroy();
 	sm_destroy();
+	wp_destroy();
 	shm_destroy();
 	usm_destroy();
 }
 
 static void child_sig_handler(int signo)
 {
-	static volatile int fatal_delivered = 0;
+	static volatile int fatal_delivered;
 
 	if (signo == SIGHUP) {
 		/*
@@ -240,7 +240,7 @@ static void child_sig_handler(int signo)
 	pr_err("Child received signal: %d (%s)\n",
 		signo, strsignal(signo));
 
-	if (!g_atomic_int_compare_and_exchange(&fatal_delivered, 0, 1))
+	if (!atomic_int_compare_and_exchange(&fatal_delivered, 0, 1))
 		return;
 
 	usmbd_health_status &= ~USMBD_HEALTH_RUNNING;
@@ -296,13 +296,16 @@ static int worker_process_init(void)
 
 	setup_signals(child_sig_handler);
 	set_logger_app_name("usmbd-worker");
-
 	ret = usm_init();
 	if (ret) {
 		pr_err("Failed to init user management\n");
 		goto out;
 	}
-
+	ret = wp_init();
+	if (ret) {
+		pr_err("Failed to init worker\n");
+		goto out;
+	}
 	ret = shm_init();
 	if (ret) {
 		pr_err("Failed to init net share management\n");
@@ -321,12 +324,6 @@ static int worker_process_init(void)
 		goto out;
 	}
 
-	ret = wp_init();
-	if (ret) {
-		pr_err("Failed to init worker threads pool\n");
-		goto out;
-	}
-
 	ret = rpc_init();
 	if (ret) {
 		pr_err("Failed to init RPC subsystem\n");
@@ -495,10 +492,10 @@ int main(int argc, char *argv[])
 			pr_debug("TCP port option override\n");
 			break;
 		case 'c':
-			smbconf = g_strdup(optarg);
+			smbconf = strdup(optarg);
 			break;
 		case 'u':
-			pwddb = g_strdup(optarg);
+			pwddb = strdup(optarg);
 			break;
 		case 'n':
 			if (!optarg)
diff -urpN ksmbd-tools-3.1.0/usmbd/worker.c ksmbd-tools-3.1.0.new/usmbd/worker.c
--- ksmbd-tools-3.1.0/usmbd/worker.c	2020-01-22 18:12:55.000000000 +0400
+++ ksmbd-tools-3.1.0.new/usmbd/worker.c	2020-01-26 13:58:13.876726005 +0400
@@ -5,7 +5,8 @@
  *   linux-cifsd-devel@lists.sourceforge.net
  */
 #include <memory.h>
-#include <glib.h>
+#include <pthread.h>
+#include <semaphore.h>
 #include <errno.h>
 #include <linux/usmbd_server.h>
 
@@ -19,7 +20,7 @@
 #include <management/tree_conn.h>
 
 #define MAX_WORKER_THREADS	4
-static GThreadPool *pool;
+static sem_t semaphore;
 
 #define VALID_IPC_MSG(m, t)					\
 	({							\
@@ -156,7 +157,7 @@ static int rpc_request(struct usmbd_ipc_
 	req = USMBD_IPC_MSG_PAYLOAD(msg);
 	if (req->flags & USMBD_RPC_METHOD_RETURN)
 		resp_msg = ipc_msg_alloc(USMBD_IPC_MAX_MESSAGE_SIZE -
-				sizeof(struct usmbd_rpc_command));
+					 sizeof(struct usmbd_rpc_command));
 	else
 		resp_msg = ipc_msg_alloc(sizeof(struct usmbd_rpc_command));
 	if (!resp_msg)
@@ -193,7 +194,7 @@ out:
 	return 0;
 }
 
-static void worker_pool_fn(gpointer event, gpointer user_data)
+static void *worker_pool_fn(void *event)
 {
 	struct usmbd_ipc_msg *msg = (struct usmbd_ipc_msg *)event;
 
@@ -232,38 +233,35 @@ static void worker_pool_fn(gpointer even
 	}
 
 	ipc_msg_free(msg);
+	sem_post(&semaphore);
+	return NULL;
 }
 
 int wp_ipc_msg_push(struct usmbd_ipc_msg *msg)
 {
-	return g_thread_pool_push(pool, msg, NULL);
-}
+	pthread_attr_t attr;
+	pthread_t thread;
+
+	sem_wait(&semaphore);
+	pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	if (pthread_create(&thread, &attr, worker_pool_fn, msg) != 0) {
+		pthread_attr_destroy(&attr);
+		sem_post(&semaphore);
+		pr_err("error while creating worker thread\n");
+		return -1;
+	}
+	pthread_attr_destroy(&attr);
+	return 0;
 
-void wp_destroy(void)
-{
-	if (pool)
-		g_thread_pool_free(pool, 1, 1);
 }
 
 int wp_init(void)
 {
-	GError *err;
-
-	pool = g_thread_pool_new(worker_pool_fn,
-				 NULL,
-				 MAX_WORKER_THREADS,
-				 0,
-				 &err);
-	if (!pool) {
-		if (err) {
-			pr_err("Can't create pool: %s\n", err->message);
-			g_error_free(err);
-		}
-		goto out_error;
-	}
+	return sem_init(&semaphore, 0, MAX_WORKER_THREADS);
+}
 
-	return 0;
-out_error:
-	wp_destroy();
-	return -ENOMEM;
+void wp_destroy(void)
+{
+	sem_destroy(&semaphore);
 }
