1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 /* 17 * mdb module for libmlsvc, which contains interesting data structures 18 * including: the share cache 19 */ 20 21 #include <mdb/mdb_modapi.h> 22 #include <mdb/mdb_ks.h> 23 #include <mdb/mdb_ctf.h> 24 25 #include <synch.h> 26 #include <smbsrv/hash_table.h> 27 #include <smbsrv/libsmb.h> 28 #include <smbsrv/smb_share.h> 29 30 #define MLSVC_OBJNAME "libmlsvc.so.1" 31 #define MLSVC_SCOPE MLSVC_OBJNAME "`" 32 33 #define AFLAG 1 34 #define VFLAG 2 35 36 typedef struct dump_shr_args { 37 uint_t dsa_opts; 38 uintptr_t dsa_hdl; 39 smb_share_t dsa_shr; 40 } dump_shr_args_t; 41 42 /*ARGSUSED*/ 43 static int 44 dump_shr_cb(uintptr_t addr, const void *data, void *varg) 45 { 46 dump_shr_args_t *args = varg; 47 const HT_ITEM *hi = data; 48 smb_share_t *shr = &args->dsa_shr; 49 50 if (hi->hi_data == NULL) 51 return (WALK_NEXT); 52 53 if ((hi->hi_flags & HT_DELETE) != 0 && 54 (args->dsa_opts & AFLAG) == 0) 55 return (WALK_NEXT); 56 57 if (args->dsa_opts & VFLAG) { 58 mdb_arg_t argv; 59 int flags = DCMD_ADDRSPEC; 60 61 argv.a_type = MDB_TYPE_STRING; 62 argv.a_un.a_str = MLSVC_SCOPE "smb_share_t"; 63 /* Don't fail the walk if this fails. */ 64 mdb_printf("%-?p ", hi->hi_data); 65 mdb_call_dcmd("print", (uintptr_t)hi->hi_data, 66 flags, 1, &argv); 67 } else { 68 if (mdb_vread(shr, sizeof (*shr), 69 (uintptr_t)hi->hi_data) == -1) { 70 mdb_warn("failed to read %s at %p", 71 "smb_share_t", hi->hi_data); 72 return (WALK_NEXT); 73 } 74 75 mdb_printf("%-?p ", hi->hi_data); 76 mdb_printf("name=%s path=%s desc=\"%s\"\n", 77 shr->shr_name, shr->shr_path, shr->shr_cmnt); 78 } 79 80 return (WALK_NEXT); 81 } 82 83 84 /* 85 * *************************** Top level dcmds **************************** 86 */ 87 88 typedef struct mdb_smb_shr_cache { 89 HT_HANDLE *sc_cache; 90 rwlock_t sc_cache_lck; 91 mutex_t sc_mtx; 92 cond_t sc_cv; 93 uint32_t sc_state; 94 uint32_t sc_nops; 95 } mdb_smb_shr_cache_t; 96 97 98 static void 99 smb_shr_cache_help(void) 100 { 101 mdb_printf( 102 "Displays the list of shares in the smbd smb_shr_cache.\n" 103 "With -a, also show deleted entries.\n" 104 "With -v, print full smb_share_t objects.\n\n"); 105 } 106 107 /* 108 * ::smb_shr_cache 109 */ 110 /*ARGSUSED*/ 111 static int 112 smb_shr_cache_dcmd(uintptr_t addr, uint_t flags, int argc, 113 const mdb_arg_t *argv) 114 { 115 dump_shr_args_t *args; 116 mdb_smb_shr_cache_t *ssc; 117 118 args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC); 119 120 if (mdb_getopts(argc, argv, 121 'a', MDB_OPT_SETBITS, AFLAG, &args->dsa_opts, 122 'v', MDB_OPT_SETBITS, VFLAG, &args->dsa_opts, 123 NULL) != argc) 124 return (DCMD_USAGE); 125 126 if (!(flags & DCMD_ADDRSPEC)) { 127 GElf_Sym sym; 128 129 /* Locate the shr hash head. */ 130 if (mdb_lookup_by_obj(MLSVC_OBJNAME, "smb_shr_cache", &sym)) { 131 mdb_warn("failed to lookup `smb_shr_cache'\n"); 132 return (DCMD_ERR); 133 } 134 addr = sym.st_value; 135 } 136 137 ssc = mdb_zalloc(sizeof (*ssc), UM_SLEEP | UM_GC); 138 if (mdb_ctf_vread(ssc, MLSVC_SCOPE "smb_shr_cache_t", 139 "mdb_smb_shr_cache_t", addr, 0) < 0) { 140 mdb_warn("failed to read smb_shr_cache at %p", addr); 141 return (DCMD_ERR); 142 } 143 144 /* Now walk HT_HANDLE *sc_cache */ 145 args->dsa_hdl = (uintptr_t)ssc->sc_cache; 146 147 if (mdb_pwalk(MLSVC_SCOPE "smb_ht_walker", 148 dump_shr_cb, args, args->dsa_hdl) == -1) { 149 mdb_warn("cannot walk smb_shr_cache list"); 150 return (DCMD_ERR); 151 } 152 return (DCMD_OK); 153 } 154 155 156 157 /* 158 * MDB module linkage information: 159 * 160 * We declare a list of structures describing our dcmds, a list of structures 161 * describing our walkers and a function named _mdb_init to return a pointer 162 * to our module information. 163 */ 164 static const mdb_dcmd_t dcmds[] = { 165 166 /* Avoiding name conflict with smbsrv`smb_shr_cache */ 167 { "smbd_shr_cache", 168 "[-av]", 169 "print SMB share cache", 170 smb_shr_cache_dcmd, 171 smb_shr_cache_help }, 172 173 { NULL } 174 }; 175 176 int smb_ht_walk_init(mdb_walk_state_t *wsp); 177 int smb_ht_walk_step(mdb_walk_state_t *wsp); 178 179 static const mdb_walker_t walkers[] = { 180 { "smb_ht_walker", 181 "walk an smb_hash_t structure", 182 smb_ht_walk_init, 183 smb_ht_walk_step, 184 NULL, 185 NULL }, 186 { NULL } 187 }; 188 189 static const mdb_modinfo_t modinfo = { 190 MDB_API_VERSION, dcmds, walkers 191 }; 192 193 const mdb_modinfo_t * 194 _mdb_init(void) 195 { 196 return (&modinfo); 197 } 198