--- /dev/null	Mon Aug  5 17:15:09 2019
+++ new/usr/src/cmd/mdb/common/modules/libmlsvc/mlsvc.c	Mon Aug  5 17:15:09 2019
@@ -0,0 +1,197 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * mdb module for libmlsvc, which contains interesting data structures
+ * including: the share cache
+ */
+
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
+#include <mdb/mdb_ctf.h>
+
+#include <synch.h>
+#include <smbsrv/hash_table.h>
+#include <smbsrv/libsmb.h>
+#include <smbsrv/smb_share.h>
+
+#define	MLSVC_OBJNAME	"libmlsvc.so.1"
+#define	MLSVC_SCOPE	MLSVC_OBJNAME "`"
+
+#define	AFLAG		1
+#define	VFLAG		2
+
+typedef struct dump_shr_args {
+	uint_t dsa_opts;
+	uintptr_t dsa_hdl;
+	smb_share_t dsa_shr;
+} dump_shr_args_t;
+
+/*ARGSUSED*/
+static int
+dump_shr_cb(uintptr_t addr, const void *data, void *varg)
+{
+	dump_shr_args_t *args = varg;
+	const HT_ITEM *hi = data;
+	smb_share_t *shr = &args->dsa_shr;
+
+	if (hi->hi_data == NULL)
+		return (WALK_NEXT);
+
+	if ((hi->hi_flags & HT_DELETE) != 0 &&
+	    (args->dsa_opts & AFLAG) == 0)
+		return (WALK_NEXT);
+
+	if (args->dsa_opts & VFLAG) {
+		mdb_arg_t argv;
+		int flags = DCMD_ADDRSPEC;
+
+		argv.a_type = MDB_TYPE_STRING;
+		argv.a_un.a_str = MLSVC_SCOPE "smb_share_t";
+		/* Don't fail the walk if this fails. */
+		mdb_printf("%-?p ", hi->hi_data);
+		mdb_call_dcmd("print", (uintptr_t)hi->hi_data,
+		    flags, 1, &argv);
+	} else {
+		if (mdb_vread(shr, sizeof (*shr),
+		    (uintptr_t)hi->hi_data) == -1) {
+			mdb_warn("failed to read %s at %p",
+			    "smb_share_t", hi->hi_data);
+			return (WALK_NEXT);
+		}
+
+		mdb_printf("%-?p ", hi->hi_data);
+		mdb_printf("name=%s path=%s desc=\"%s\"\n",
+		    shr->shr_name, shr->shr_path, shr->shr_cmnt);
+	}
+
+	return (WALK_NEXT);
+}
+
+
+/*
+ * *************************** Top level dcmds ****************************
+ */
+
+typedef struct mdb_smb_shr_cache {
+	HT_HANDLE	*sc_cache;
+	rwlock_t	sc_cache_lck;
+	mutex_t		sc_mtx;
+	cond_t		sc_cv;
+	uint32_t	sc_state;
+	uint32_t	sc_nops;
+} mdb_smb_shr_cache_t;
+
+
+static void
+smb_shr_cache_help(void)
+{
+	mdb_printf(
+	    "Displays the list of shares in the smbd smb_shr_cache.\n"
+	    "With -a, also show deleted entries.\n"
+	    "With -v, print full smb_share_t objects.\n\n");
+}
+
+/*
+ * ::smb_shr_cache
+ */
+/*ARGSUSED*/
+static int
+smb_shr_cache_dcmd(uintptr_t addr, uint_t flags, int argc,
+    const mdb_arg_t *argv)
+{
+	dump_shr_args_t *args;
+	mdb_smb_shr_cache_t *ssc;
+
+	args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC);
+
+	if (mdb_getopts(argc, argv,
+	    'a', MDB_OPT_SETBITS, AFLAG, &args->dsa_opts,
+	    'v', MDB_OPT_SETBITS, VFLAG, &args->dsa_opts,
+	    NULL) != argc)
+		return (DCMD_USAGE);
+
+	if (!(flags & DCMD_ADDRSPEC)) {
+		GElf_Sym	sym;
+
+		/* Locate the shr hash head. */
+		if (mdb_lookup_by_obj(MLSVC_OBJNAME, "smb_shr_cache", &sym)) {
+			mdb_warn("failed to lookup `smb_shr_cache'\n");
+			return (DCMD_ERR);
+		}
+		addr = sym.st_value;
+	}
+
+	ssc = mdb_zalloc(sizeof (*ssc), UM_SLEEP | UM_GC);
+	if (mdb_ctf_vread(ssc, MLSVC_SCOPE "smb_shr_cache_t",
+	    "mdb_smb_shr_cache_t", addr, 0) < 0) {
+		mdb_warn("failed to read smb_shr_cache at %p", addr);
+		return (DCMD_ERR);
+	}
+
+	/* Now walk HT_HANDLE *sc_cache */
+	args->dsa_hdl = (uintptr_t)ssc->sc_cache;
+
+	if (mdb_pwalk(MLSVC_SCOPE "smb_ht_walker",
+	    dump_shr_cb, args, args->dsa_hdl) == -1) {
+		mdb_warn("cannot walk smb_shr_cache list");
+		return (DCMD_ERR);
+	}
+	return (DCMD_OK);
+}
+
+
+
+/*
+ * MDB module linkage information:
+ *
+ * We declare a list of structures describing our dcmds, a list of structures
+ * describing our walkers and a function named _mdb_init to return a pointer
+ * to our module information.
+ */
+static const mdb_dcmd_t dcmds[] = {
+
+	/* Avoiding name conflict with smbsrv`smb_shr_cache */
+	{   "smbd_shr_cache",
+	    "[-av]",
+	    "print SMB share cache",
+	    smb_shr_cache_dcmd,
+	    smb_shr_cache_help },
+
+	{ NULL }
+};
+
+int smb_ht_walk_init(mdb_walk_state_t *wsp);
+int smb_ht_walk_step(mdb_walk_state_t *wsp);
+
+static const mdb_walker_t walkers[] = {
+	{   "smb_ht_walker",
+	    "walk an smb_hash_t structure",
+	    smb_ht_walk_init,
+	    smb_ht_walk_step,
+	    NULL,
+	    NULL },
+	{ NULL }
+};
+
+static const mdb_modinfo_t modinfo = {
+	MDB_API_VERSION, dcmds, walkers
+};
+
+const mdb_modinfo_t *
+_mdb_init(void)
+{
+	return (&modinfo);
+}
