diff options
| author | Gordon Ross <gwr@nexenta.com> | 2015-06-02 22:38:13 -0400 |
|---|---|---|
| committer | Gordon Ross <gwr@nexenta.com> | 2019-05-18 19:46:03 -0400 |
| commit | bd49ed4555a9b0a9c4989b5985c9fba26da21457 (patch) | |
| tree | 78cde078f12766a88ac5af42397f959e31b216cc | |
| parent | 764c8bd85562491d470a20cc0353ca8b79069361 (diff) | |
| download | illumos-joyent-bd49ed4555a9b0a9c4989b5985c9fba26da21457.tar.gz | |
10963 smbsrv mdb module should lookup enum values
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Approved by: Joshua M. Clulow <josh@sysmgr.org>
| -rw-r--r-- | usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c | 1336 |
1 files changed, 917 insertions, 419 deletions
diff --git a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c index c79d0f8f9e..d074a71134 100644 --- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c +++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c @@ -26,11 +26,14 @@ #include <mdb/mdb_modapi.h> #include <mdb/mdb_ks.h> +#include <mdb/mdb_ctf.h> +#include <sys/note.h> #include <sys/thread.h> #include <sys/taskq.h> #include <smbsrv/smb_vops.h> #include <smbsrv/smb.h> #include <smbsrv/smb_ktypes.h> +#include <smbsrv/smb_token.h> #ifndef _KMDB #include "smbsrv_pcap.h" @@ -42,6 +45,8 @@ #define SMBSRV_OBJNAME "libfksmbsrv.so.1" #endif +#define SMBSRV_SCOPE SMBSRV_OBJNAME "`" + #define SMB_DCMD_INDENT 2 #define ACE_TYPE_TABLEN (ACE_ALL_TYPES + 1) #define ACE_TYPE_ENTRY(_v_) {_v_, #_v_} @@ -61,6 +66,22 @@ #define SMB_OPT_ALL_OBJ 0x000000FF /* + * Use CTF to set var = OFFSETOF(typ, mem) if possible, otherwise + * fall back to just OFFSETOF. The fall back is more convenient + * than trying to return an error where this is used, and also + * let's us find out at compile time if we're referring to any + * typedefs or member names that don't exist. Without that + * OFFSETOF fall back, we'd only find out at run time. + */ +#define GET_OFFSET(var, typ, mem) do { \ + var = mdb_ctf_offsetof_by_name(#typ, #mem); \ + if (var < 0) { \ + mdb_warn("cannot lookup: " #typ " ." #mem); \ + var = (int)OFFSETOF(typ, mem); \ + } \ +_NOTE(CONSTCOND) } while (0) + +/* * Structure associating an ACE type to a string. */ typedef struct { @@ -81,7 +102,7 @@ typedef struct { */ typedef struct { uint_t ex_mask; - size_t ex_offset; + int (*ex_offset)(void); const char *ex_dcmd; const char *ex_name; } smb_exp_t; @@ -107,6 +128,72 @@ static smb_mdb_opts_t smb_opts[SMB_MDB_MAX_OPTS] = { "-v", SMB_OPT_VERBOSE } }; +/* + * These access mask bits are generic enough they could move into the + * genunix mdb module or somewhere so they could be shared. + */ +static const mdb_bitmask_t +nt_access_bits[] = { + { "READ_DATA", + FILE_READ_DATA, + FILE_READ_DATA }, + { "WRITE_DATA", + FILE_WRITE_DATA, + FILE_WRITE_DATA }, + { "APPEND_DATA", + FILE_APPEND_DATA, + FILE_APPEND_DATA }, + { "READ_EA", + FILE_READ_EA, + FILE_READ_EA }, + { "WRITE_EA", + FILE_WRITE_EA, + FILE_WRITE_EA }, + { "EXECUTE", + FILE_EXECUTE, + FILE_EXECUTE }, + { "DELETE_CHILD", + FILE_DELETE_CHILD, + FILE_DELETE_CHILD }, + { "READ_ATTR", + FILE_READ_ATTRIBUTES, + FILE_READ_ATTRIBUTES }, + { "WRITE_ATTR", + FILE_WRITE_ATTRIBUTES, + FILE_WRITE_ATTRIBUTES }, + { "DELETE", + DELETE, + DELETE }, + { "READ_CTRL", + READ_CONTROL, + READ_CONTROL }, + { "WRITE_DAC", + WRITE_DAC, + WRITE_DAC }, + { "WRITE_OWNER", + WRITE_OWNER, + WRITE_OWNER }, + { "SYNCH", + SYNCHRONIZE, + SYNCHRONIZE }, + { "ACC_SEC", + ACCESS_SYSTEM_SECURITY, + ACCESS_SYSTEM_SECURITY }, + { "MAX_ALLOWED", + MAXIMUM_ALLOWED, + MAXIMUM_ALLOWED }, + { "GEN_X", + GENERIC_EXECUTE, + GENERIC_EXECUTE }, + { "GEN_W", + GENERIC_WRITE, + GENERIC_WRITE }, + { "GEN_R", + GENERIC_READ, + GENERIC_READ }, + { NULL, 0, 0 } +}; + static smb_com_entry_t smb_com[256] = { SMB_COM_ENTRY(SMB_COM_CREATE_DIRECTORY, "No"), @@ -397,6 +484,7 @@ static int smb_obj_expand(uintptr_t, uint_t, const smb_exp_t *, ulong_t); static int smb_obj_list(const char *, uint_t, uint_t); static int smb_worker_findstack(uintptr_t); static void smb_inaddr_ntop(smb_inaddr_t *, char *, size_t); +static void get_enum(char *, size_t, const char *, int, const char *); typedef int (*dump_func_t)(struct mbuf_chain *, int32_t, smb_inaddr_t *, uint16_t, smb_inaddr_t *, uint16_t, @@ -407,6 +495,54 @@ static int smb_req_dump(struct mbuf_chain *, int32_t, static int smb_req_dump_m(uintptr_t, const void *, void *); /* + * Until the mdb on our customer machines has the fix for: + * NEX-3907 mdb_ctf_vread fails in dcmds run via mdb_pwalk_dcmd + * (a.k.a. https://www.illumos.org/issues/5998) + * we need to avoid mdb_pwalk_dcmd here or mdb_ctf_vread fails. + * Using mdb_pwalk instead works OK. + * + * Please remove this work-around once the mdb fix is rolled out. + */ +#ifndef ILLUMOS_5998_FIXED +#define mdb_pwalk_dcmd(walker, dcmd, argc, argv, addr) \ + smb_pwalk_dcmd(walker, dcmd, argc, argv, addr) + +struct smb_pwalk_dcmd_cb { + const char *cmd; + int flags; + int argc; + const mdb_arg_t *argv; +}; + +static int +pwalk_dcmd(uintptr_t addr, const void *data, void *varg) +{ + struct smb_pwalk_dcmd_cb *cb = varg; + int ret; + _NOTE(ARGUNUSED(data)); + + ret = mdb_call_dcmd(cb->cmd, addr, cb->flags, cb->argc, cb->argv); + cb->flags &= ~DCMD_LOOPFIRST; + + return (ret); +} + +static int +smb_pwalk_dcmd(const char *wname, const char *dcname, + int argc, const mdb_arg_t *argv, uintptr_t addr) +{ + struct smb_pwalk_dcmd_cb cb; + + cb.cmd = dcname; + cb.flags = DCMD_LOOP | DCMD_LOOPFIRST | DCMD_ADDRSPEC; + cb.argc = argc; + cb.argv = argv; + + return (mdb_pwalk(wname, pwalk_dcmd, &cb, addr)); +} +#endif /* !ILLUMOS_5998_FIXED */ + +/* * ***************************************************************************** * ****************************** Top level DCMD ******************************* * ***************************************************************************** @@ -447,6 +583,7 @@ smblist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) uint_t opts = 0; int new_argc; mdb_arg_t new_argv[SMB_MDB_MAX_OPTS]; + int ll_off; if (smb_dcmd_getopt(&opts, argc, argv)) return (DCMD_USAGE); @@ -463,7 +600,8 @@ smblist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_ERR); } - addr = (uintptr_t)sym.st_value + OFFSETOF(smb_llist_t, ll_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + addr = (uintptr_t)sym.st_value + ll_off; if (mdb_pwalk_dcmd("list", "smbsrv", new_argc, new_argv, addr)) { mdb_warn("cannot walk smb_server list"); @@ -478,14 +616,34 @@ smblist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * ***************************************************************************** */ -static const char *smb_server_state[SMB_SERVER_STATE_SENTINEL] = +typedef struct mdb_smb_server { + smb_server_state_t sv_state; + zoneid_t sv_zid; +} mdb_smb_server_t; + +static int +smb_server_exp_off_nbt_list(void) { - "CREATED", - "CONFIGURED", - "RUNNING", - "STOPPING", - "DELETING" -}; + int svd_off, lds_off, ll_off; + + /* OFFSETOF(smb_server_t, sv_nbt_daemon.ld_session_list.ll_list); */ + GET_OFFSET(svd_off, smb_server_t, sv_nbt_daemon); + GET_OFFSET(lds_off, smb_listener_daemon_t, ld_session_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + return (svd_off + lds_off + ll_off); +} + +static int +smb_server_exp_off_tcp_list(void) +{ + int svd_off, lds_off, ll_off; + + /* OFFSETOF(smb_server_t, sv_tcp_daemon.ld_session_list.ll_list); */ + GET_OFFSET(svd_off, smb_server_t, sv_tcp_daemon); + GET_OFFSET(lds_off, smb_listener_daemon_t, ld_session_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + return (svd_off + lds_off + ll_off); +} /* * List of objects that can be expanded under a server structure. @@ -493,10 +651,10 @@ static const char *smb_server_state[SMB_SERVER_STATE_SENTINEL] = static const smb_exp_t smb_server_exp[] = { { SMB_OPT_ALL_OBJ, - OFFSETOF(smb_server_t, sv_nbt_daemon.ld_session_list.ll_list), + smb_server_exp_off_nbt_list, "smbsess", "smb_session"}, { SMB_OPT_ALL_OBJ, - OFFSETOF(smb_server_t, sv_tcp_daemon.ld_session_list.ll_list), + smb_server_exp_off_tcp_list, "smbsess", "smb_session"}, { 0, 0, NULL, NULL } }; @@ -522,11 +680,12 @@ smbsrv_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_SERVER)) || !(opts & SMB_OPT_WALK)) { - smb_server_t *sv; - const char *state; + mdb_smb_server_t *sv; + char state[40]; - sv = mdb_alloc(sizeof (smb_server_t), UM_SLEEP | UM_GC); - if (mdb_vread(sv, sizeof (smb_server_t), addr) == -1) { + sv = mdb_zalloc(sizeof (*sv), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(sv, SMBSRV_SCOPE "smb_server_t", + "mdb_smb_server_t", addr, 0) < 0) { mdb_warn("failed to read smb_server at %p", addr); return (DCMD_ERR); } @@ -549,10 +708,9 @@ smbsrv_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) "%</u>%</b>\n", "SERVER", "ZONE", "STATE"); - if (sv->sv_state >= SMB_SERVER_STATE_SENTINEL) - state = "UNKNOWN"; - else - state = smb_server_state[sv->sv_state]; + get_enum(state, sizeof (state), + "smb_server_state_t", sv->sv_state, + "SMB_SERVER_STATE_"); mdb_printf("%-?p %-4d %-32s \n", addr, sv->sv_zid, state); @@ -569,30 +727,75 @@ smbsrv_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * ***************************************************************************** */ -static const char *smb_session_state[SMB_SESSION_STATE_SENTINEL] = +typedef struct mdb_smb_session { + uint64_t s_kid; + smb_session_state_t s_state; + uint32_t s_flags; + uint16_t s_local_port; + uint16_t s_remote_port; + smb_inaddr_t ipaddr; + smb_inaddr_t local_ipaddr; + int dialect; + + smb_slist_t s_req_list; + smb_llist_t s_xa_list; + smb_llist_t s_user_list; + smb_llist_t s_tree_list; + + volatile uint32_t s_tree_cnt; + volatile uint32_t s_file_cnt; + volatile uint32_t s_dir_cnt; + + char workstation[SMB_PI_MAX_HOST]; +} mdb_smb_session_t; + +static int +smb_session_exp_off_req_list(void) { - "INITIALIZED", - "DISCONNECTED", - "CONNECTED", - "ESTABLISHED", - "NEGOTIATED", - "TERMINATED" -}; + int rl_off, sl_off; + + /* OFFSETOF(smb_session_t, s_req_list.sl_list); */ + GET_OFFSET(rl_off, smb_session_t, s_req_list); + GET_OFFSET(sl_off, smb_slist_t, sl_list); + return (rl_off + sl_off); +} + +static int +smb_session_exp_off_user_list(void) +{ + int ul_off, ll_off; + + /* OFFSETOF(smb_session_t, s_user_list.ll_list); */ + GET_OFFSET(ul_off, smb_session_t, s_user_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + return (ul_off + ll_off); +} + +static int +smb_session_exp_off_tree_list(void) +{ + int tl_off, ll_off; + + /* OFFSETOF(smb_session_t, s_tree_list.ll_list); */ + GET_OFFSET(tl_off, smb_session_t, s_tree_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + return (tl_off + ll_off); +} /* * List of objects that can be expanded under a session structure. */ static const smb_exp_t smb_session_exp[] = { - { SMB_OPT_REQUEST, - OFFSETOF(smb_session_t, s_req_list.sl_list), - "smbreq", "smb_request"}, { SMB_OPT_USER, - OFFSETOF(smb_session_t, s_user_list.ll_list), + smb_session_exp_off_user_list, "smbuser", "smb_user"}, { SMB_OPT_TREE | SMB_OPT_OFILE | SMB_OPT_ODIR, - OFFSETOF(smb_session_t, s_tree_list.ll_list), + smb_session_exp_off_tree_list, "smbtree", "smb_tree"}, + { SMB_OPT_REQUEST, + smb_session_exp_off_req_list, + "smbreq", "smb_request"}, { 0, 0, NULL, NULL} }; @@ -636,20 +839,21 @@ smbsess_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) char cipaddr[INET6_ADDRSTRLEN]; char lipaddr[INET6_ADDRSTRLEN]; int ipaddrstrlen = INET6_ADDRSTRLEN; - smb_session_t *se; - const char *state; + mdb_smb_session_t *se; + char state[40]; indent = SMB_DCMD_INDENT; - se = mdb_alloc(sizeof (*se), UM_SLEEP | UM_GC); - if (mdb_vread(se, sizeof (*se), addr) == -1) { + se = mdb_zalloc(sizeof (*se), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(se, SMBSRV_SCOPE "smb_session_t", + "mdb_smb_session_t", addr, 0) < 0) { mdb_warn("failed to read smb_session at %p", addr); return (DCMD_ERR); } - if (se->s_state >= SMB_SESSION_STATE_SENTINEL) - state = "INVALID"; - else - state = smb_session_state[se->s_state]; + + get_enum(state, sizeof (state), + "smb_session_state_t", se->s_state, + "SMB_SESSION_STATE_"); if (se->ipaddr.a_family == AF_INET) ipaddrstrlen = INET_ADDRSTRLEN; @@ -699,25 +903,44 @@ smbsess_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * ***************************************************************************** */ -static const char *smb_request_state[SMB_REQ_STATE_SENTINEL] = -{ - "FREE", - "INITIALIZING", - "SUBMITTED", - "ACTIVE", - "WAITING_EVENT", - "EVENT_OCCURRED", - "WAITING_LOCK", - "COMPLETED", - "CANCELED", - "CLEANED_UP" -}; +typedef struct mdb_smb_request { + smb_req_state_t sr_state; + smb_session_t *session; + struct mbuf_chain command; + struct mbuf_chain reply; + + unsigned char first_smb_com; + unsigned char smb_com; + uint16_t smb2_cmd_code; + uint64_t smb2_messageid; + + uint16_t smb_tid; + uint32_t smb_pid; + uint16_t smb_uid; + uint16_t smb_mid; + uint16_t smb_fid; + + struct smb_tree *tid_tree; + struct smb_ofile *fid_ofile; + smb_user_t *uid_user; + + kthread_t *sr_worker; + hrtime_t sr_time_submitted; + hrtime_t sr_time_active; + hrtime_t sr_time_start; + +} mdb_smb_request_t; #define SMB_REQUEST_BANNER \ - "%<b>%<u>%-?s %-?s %-14s %-14s %-16s %-32s%</u>%</b>\n" + "%<b>%<u>%-?s %-14s %-?s %-16s %-16s%</u>%</b>\n" #define SMB_REQUEST_FORMAT \ - "%-?p %-?p %-14lld %-14lld %-16s %s\n" + "%-?p 0x%-12llx %-?p %-16s %s\n" +/* + * ::smbreq + * + * smbreq dcmd - Print out smb_request_t + */ static int smbreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { @@ -734,47 +957,22 @@ smbreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_REQUEST)) || !(opts & SMB_OPT_WALK)) { - smb_request_t *sr; - const char *state; + mdb_smb_request_t *sr; + char state[40]; const char *cur_cmd_name; uint_t cur_cmd_code; - uint64_t waiting; - uint64_t running; + uint64_t msg_id; - sr = mdb_alloc(sizeof (*sr), UM_SLEEP | UM_GC); - if (mdb_vread(sr, sizeof (*sr), addr) == -1) { + sr = mdb_zalloc(sizeof (*sr), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(sr, SMBSRV_SCOPE "smb_request_t", + "mdb_smb_request_t", addr, 0) < 0) { mdb_warn("failed to read smb_request at %p", addr); return (DCMD_ERR); } - if (sr->sr_magic != SMB_REQ_MAGIC) { - mdb_warn("not an smb_request_t (%p)>", addr); - return (DCMD_ERR); - } - waiting = 0; - running = 0; - /* - * Note: mdb_gethrtime() is only available in kmdb - */ -#ifdef _KERNEL - if (sr->sr_time_submitted != 0) { - if (sr->sr_time_active != 0) { - waiting = sr->sr_time_active - - sr->sr_time_submitted; - running = mdb_gethrtime() - - sr->sr_time_active; - } else { - waiting = mdb_gethrtime() - - sr->sr_time_submitted; - } - } - waiting /= NANOSEC; - running /= NANOSEC; -#endif /* _KERNEL */ - if (sr->sr_state >= SMB_REQ_STATE_SENTINEL) - state = "INVALID"; - else - state = smb_request_state[sr->sr_state]; + get_enum(state, sizeof (state), + "smb_req_state_t", sr->sr_state, + "SMB_REQ_STATE_"); if (sr->smb2_cmd_code != 0) { /* SMB2 request */ @@ -782,10 +980,12 @@ smbreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (cur_cmd_code > SMB2_INVALID_CMD) cur_cmd_code = SMB2_INVALID_CMD; cur_cmd_name = smb2_cmd_names[cur_cmd_code]; + msg_id = sr->smb2_messageid; } else { /* SMB1 request */ cur_cmd_code = sr->smb_com & 0xFF; cur_cmd_name = smb_com[cur_cmd_code].smb_com; + msg_id = sr->smb_mid; } if (opts & SMB_OPT_VERBOSE) { @@ -825,23 +1025,39 @@ smbreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) "PID: %u\n", sr->smb_pid); - if (sr->smb2_messageid != 0) { + mdb_printf( + "MID: 0x%llx\n", + msg_id); + + /* + * Note: mdb_gethrtime() is only available in kmdb + */ +#ifdef _KERNEL + if (sr->sr_time_submitted != 0) { + uint64_t waiting = 0; + uint64_t running = 0; + + if (sr->sr_time_active != 0) { + waiting = sr->sr_time_active - + sr->sr_time_submitted; + running = mdb_gethrtime() - + sr->sr_time_active; + } else { + waiting = mdb_gethrtime() - + sr->sr_time_submitted; + } + waiting /= NANOSEC; + running /= NANOSEC; + mdb_printf( - "MID: 0x%llx\n\n", - sr->smb2_messageid); - } else { + "waiting time: %lld\n", + waiting); + mdb_printf( - "MID: %u\n\n", - sr->smb_mid); + "running time: %lld\n", + running); } - - mdb_printf( - "waiting time: %lld\n", - waiting); - - mdb_printf( - "running time: %lld\n", - running); +#endif /* _KERNEL */ mdb_printf( "worker thread: %p\n", @@ -851,19 +1067,17 @@ smbreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (DCMD_HDRSPEC(flags)) mdb_printf( SMB_REQUEST_BANNER, - "ADDR", + "REQUEST", + "MSG_ID", "WORKER", - "WAITING(s)", - "RUNNING(s)", "STATE", "COMMAND"); mdb_printf( SMB_REQUEST_FORMAT, addr, + msg_id, sr->sr_worker, - waiting, - running, state, cur_cmd_name); } @@ -899,8 +1113,8 @@ static int smbreq_dump_dcmd(uintptr_t rqaddr, uint_t flags, int argc, const mdb_arg_t *argv) { - smb_session_t *ssn; - smb_request_t *sr; + mdb_smb_session_t *ssn; + mdb_smb_request_t *sr; char *outfile = NULL; dump_func_t dump_func; uint64_t msgid; @@ -933,29 +1147,23 @@ smbreq_dump_dcmd(uintptr_t rqaddr, uint_t flags, int argc, /* * Get the smb_request_t, for the cmd/reply messages. */ - sr = mdb_alloc(sizeof (*sr), UM_SLEEP | UM_GC); - if (mdb_vread(sr, sizeof (*sr), rqaddr) == -1) { + sr = mdb_zalloc(sizeof (*sr), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(sr, SMBSRV_SCOPE "smb_request_t", + "mdb_smb_request_t", rqaddr, 0) < 0) { mdb_warn("failed to read smb_request at %p", rqaddr); return (DCMD_ERR); } - if (sr->sr_magic != SMB_REQ_MAGIC) { - mdb_warn("not an smb_request_t (%p)>", rqaddr); - return (DCMD_ERR); - } /* * Get the session too, for the IP addresses & ports. */ ssnaddr = (uintptr_t)sr->session; - ssn = mdb_alloc(sizeof (*ssn), UM_SLEEP | UM_GC); - if (mdb_vread(ssn, sizeof (*ssn), ssnaddr) == -1) { + ssn = mdb_zalloc(sizeof (*ssn), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(ssn, SMBSRV_SCOPE "smb_session_t", + "mdb_smb_session_t", ssnaddr, 0) < 0) { mdb_warn("failed to read smb_request at %p", ssnaddr); return (DCMD_ERR); } - if (ssn->s_magic != SMB_SESSION_MAGIC) { - mdb_warn("not an smb_session_t (%p)>", ssnaddr); - return (DCMD_ERR); - } #ifndef _KMDB if (outfile != NULL) { @@ -1079,13 +1287,61 @@ smb_req_dump_m(uintptr_t m_addr, const void *data, void *arg) * ****************************** smb_user_t *********************************** * ***************************************************************************** */ +typedef struct mdb_smb_user { + smb_user_state_t u_state; + + struct smb_server *u_server; + smb_session_t *u_session; + + uint16_t u_name_len; + char *u_name; + uint16_t u_domain_len; + char *u_domain; + time_t u_logon_time; + cred_t *u_cred; + cred_t *u_privcred; + + uint32_t u_refcnt; + uint32_t u_flags; + uint32_t u_privileges; + uint16_t u_uid; +} mdb_smb_user_t; + +static const mdb_bitmask_t +user_flag_bits[] = { + { "ANON", + SMB_USER_FLAG_ANON, + SMB_USER_FLAG_ANON }, + { "GUEST", + SMB_USER_FLAG_GUEST, + SMB_USER_FLAG_GUEST }, + { "POWER_USER", + SMB_USER_FLAG_POWER_USER, + SMB_USER_FLAG_POWER_USER }, + { "BACKUP_OP", + SMB_USER_FLAG_BACKUP_OPERATOR, + SMB_USER_FLAG_BACKUP_OPERATOR }, + { "ADMIN", + SMB_USER_FLAG_ADMIN, + SMB_USER_FLAG_ADMIN }, + { NULL, 0, 0 } +}; -static const char *smb_user_state[SMB_USER_STATE_SENTINEL] = -{ - "LOGGING_ON", - "LOGGED_ON", - "LOGGING_OFF", - "LOGGED_OFF" +static const mdb_bitmask_t +user_priv_bits[] = { + { "TAKE_OWNER", + SMB_USER_PRIV_TAKE_OWNERSHIP, + SMB_USER_PRIV_TAKE_OWNERSHIP }, + { "BACKUP", + SMB_USER_PRIV_BACKUP, + SMB_USER_PRIV_BACKUP }, + { "RESTORE", + SMB_USER_PRIV_RESTORE, + SMB_USER_PRIV_RESTORE }, + { "SECURITY", + SMB_USER_PRIV_SECURITY, + SMB_USER_PRIV_SECURITY }, + { NULL, 0, 0 } }; static void @@ -1116,11 +1372,12 @@ smbuser_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_USER)) || !(opts & SMB_OPT_WALK)) { - smb_user_t *user; + mdb_smb_user_t *user; char *account; - user = mdb_alloc(sizeof (*user), UM_SLEEP | UM_GC); - if (mdb_vread(user, sizeof (*user), addr) == -1) { + user = mdb_zalloc(sizeof (*user), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(user, SMBSRV_SCOPE "smb_user_t", + "mdb_smb_user_t", addr, 0) < 0) { mdb_warn("failed to read smb_user at %p", addr); return (DCMD_ERR); } @@ -1138,19 +1395,21 @@ smbuser_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) user->u_name_len, (uintptr_t)user->u_name); if (opts & SMB_OPT_VERBOSE) { - const char *state; + char state[40]; - if (user->u_state >= SMB_USER_STATE_SENTINEL) - state = "INVALID"; - else - state = smb_user_state[user->u_state]; + get_enum(state, sizeof (state), + "smb_user_state_t", user->u_state, + "SMB_USER_STATE_"); mdb_printf("%<b>%<u>SMB user information (%p):" "%</u>%</b>\n", addr); mdb_printf("UID: %u\n", user->u_uid); mdb_printf("State: %d (%s)\n", user->u_state, state); - mdb_printf("Flags: 0x%08x\n", user->u_flags); - mdb_printf("Privileges: 0x%08x\n", user->u_privileges); + mdb_printf("Flags: 0x%08x <%b>\n", user->u_flags, + user->u_flags, user_flag_bits); + mdb_printf("Privileges: 0x%08x <%b>\n", + user->u_privileges, + user->u_privileges, user_priv_bits); mdb_printf("Credential: %p\n", user->u_cred); mdb_printf("Reference Count: %d\n", user->u_refcnt); mdb_printf("User Account: %s\n\n", account); @@ -1175,12 +1434,45 @@ smbuser_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * ***************************************************************************** */ -static const char *smb_tree_state[SMB_TREE_STATE_SENTINEL] = +typedef struct mdb_smb_tree { + smb_tree_state_t t_state; + + smb_node_t *t_snode; + smb_llist_t t_ofile_list; + smb_llist_t t_odir_list; + + uint32_t t_refcnt; + uint32_t t_flags; + int32_t t_res_type; + uint16_t t_tid; + uint16_t t_umask; + char t_sharename[MAXNAMELEN]; + char t_resource[MAXPATHLEN]; + char t_typename[SMB_TYPENAMELEN]; + char t_volume[SMB_VOLNAMELEN]; +} mdb_smb_tree_t; + +static int +smb_tree_exp_off_ofile_list(void) { - "CONNECTED", - "DISCONNECTING", - "DISCONNECTED" -}; + int tf_off, ll_off; + + /* OFFSETOF(smb_tree_t, t_ofile_list.ll_list); */ + GET_OFFSET(tf_off, smb_tree_t, t_ofile_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + return (tf_off + ll_off); +} + +static int +smb_tree_exp_off_odir_list(void) +{ + int td_off, ll_off; + + /* OFFSETOF(smb_tree_t, t_odir_list.ll_list); */ + GET_OFFSET(td_off, smb_tree_t, t_odir_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + return (td_off + ll_off); +} /* * List of objects that can be expanded under a tree structure. @@ -1188,14 +1480,79 @@ static const char *smb_tree_state[SMB_TREE_STATE_SENTINEL] = static const smb_exp_t smb_tree_exp[] = { { SMB_OPT_OFILE, - OFFSETOF(smb_tree_t, t_ofile_list.ll_list), + smb_tree_exp_off_ofile_list, "smbofile", "smb_ofile"}, { SMB_OPT_ODIR, - OFFSETOF(smb_tree_t, t_odir_list.ll_list), + smb_tree_exp_off_odir_list, "smbodir", "smb_odir"}, { 0, 0, NULL, NULL} }; +static const mdb_bitmask_t +tree_flag_bits[] = { + { "RO", + SMB_TREE_READONLY, + SMB_TREE_READONLY }, + { "ACLS", + SMB_TREE_SUPPORTS_ACLS, + SMB_TREE_SUPPORTS_ACLS }, + { "STREAMS", + SMB_TREE_STREAMS, + SMB_TREE_STREAMS }, + { "CI", + SMB_TREE_CASEINSENSITIVE, + SMB_TREE_CASEINSENSITIVE }, + { "NO_CS", + SMB_TREE_NO_CASESENSITIVE, + SMB_TREE_NO_CASESENSITIVE }, + { "NO_EXPORT", + SMB_TREE_NO_EXPORT, + SMB_TREE_NO_EXPORT }, + { "OPLOCKS", + SMB_TREE_OPLOCKS, + SMB_TREE_OPLOCKS }, + { "SHORTNAMES", + SMB_TREE_SHORTNAMES, + SMB_TREE_SHORTNAMES }, + { "XVATTR", + SMB_TREE_XVATTR, + SMB_TREE_XVATTR }, + { "DIRENTFLAGS", + SMB_TREE_DIRENTFLAGS, + SMB_TREE_DIRENTFLAGS }, + { "ACL_CR", + SMB_TREE_ACLONCREATE, + SMB_TREE_ACLONCREATE }, + { "ACEMASK", + SMB_TREE_ACEMASKONACCESS, + SMB_TREE_ACEMASKONACCESS }, + { "NFS_MNT", + SMB_TREE_NFS_MOUNTED, + SMB_TREE_NFS_MOUNTED }, + { "UNICODE", + SMB_TREE_UNICODE_ON_DISK, + SMB_TREE_UNICODE_ON_DISK }, + { "CATIA", + SMB_TREE_CATIA, + SMB_TREE_CATIA }, + { "ABE", + SMB_TREE_ABE, + SMB_TREE_ABE }, + { "QUOTA", + SMB_TREE_QUOTA, + SMB_TREE_QUOTA }, + { "DFSROOT", + SMB_TREE_DFSROOT, + SMB_TREE_DFSROOT }, + { "SPARSE", + SMB_TREE_SPARSE, + SMB_TREE_SPARSE }, + { "XMNT", + SMB_TREE_TRAVERSE_MOUNTS, + SMB_TREE_TRAVERSE_MOUNTS }, + { NULL, 0, 0 } +}; + static void smbtree_help(void) { @@ -1228,22 +1585,22 @@ smbtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_TREE)) || !(opts & SMB_OPT_WALK)) { - smb_tree_t *tree; + mdb_smb_tree_t *tree; indent = SMB_DCMD_INDENT; - tree = mdb_alloc(sizeof (*tree), UM_SLEEP | UM_GC); - if (mdb_vread(tree, sizeof (*tree), addr) == -1) { + tree = mdb_zalloc(sizeof (*tree), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(tree, SMBSRV_SCOPE "smb_tree_t", + "mdb_smb_tree_t", addr, 0) < 0) { mdb_warn("failed to read smb_tree at %p", addr); return (DCMD_ERR); } if (opts & SMB_OPT_VERBOSE) { - const char *state; + char state[40]; - if (tree->t_state >= SMB_TREE_STATE_SENTINEL) - state = "INVALID"; - else - state = smb_tree_state[tree->t_state]; + get_enum(state, sizeof (state), + "smb_tree_state_t", tree->t_state, + "SMB_TREE_STATE_"); mdb_printf("%<b>%<u>SMB tree information (%p):" "%</u>%</b>\n\n", addr); @@ -1254,7 +1611,8 @@ smbtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("Type: %s\n", tree->t_typename); mdb_printf("Volume: %s\n", tree->t_volume); mdb_printf("Umask: %04x\n", tree->t_umask); - mdb_printf("Flags: %08x\n", tree->t_flags); + mdb_printf("Flags: %08x <%b>\n", tree->t_flags, + tree->t_flags, tree_flag_bits); mdb_printf("SMB Node: %llx\n", tree->t_snode); mdb_printf("Reference Count: %d\n\n", tree->t_refcnt); } else { @@ -1278,13 +1636,16 @@ smbtree_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * ***************************************************************************** */ -static const char *smb_odir_state[SMB_ODIR_STATE_SENTINEL] = -{ - "OPEN", - "IN_USE", - "CLOSING", - "CLOSED" -}; +typedef struct mdb_smb_odir { + smb_odir_state_t d_state; + smb_session_t *d_session; + smb_user_t *d_user; + smb_tree_t *d_tree; + smb_node_t *d_dnode; + uint16_t d_odid; + uint32_t d_refcnt; + char d_pattern[MAXNAMELEN]; +} mdb_smb_odir_t; static int smbodir_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) @@ -1303,20 +1664,20 @@ smbodir_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_ODIR)) || !(opts & SMB_OPT_WALK)) { - smb_odir_t *od; + mdb_smb_odir_t *od; - od = mdb_alloc(sizeof (*od), UM_SLEEP | UM_GC); - if (mdb_vread(od, sizeof (*od), addr) == -1) { + od = mdb_zalloc(sizeof (*od), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(od, SMBSRV_SCOPE "smb_odir_t", + "mdb_smb_odir_t", addr, 0) < 0) { mdb_warn("failed to read smb_odir at %p", addr); return (DCMD_ERR); } if (opts & SMB_OPT_VERBOSE) { - const char *state; + char state[40]; - if (od->d_state >= SMB_ODIR_STATE_SENTINEL) - state = "INVALID"; - else - state = smb_odir_state[od->d_state]; + get_enum(state, sizeof (state), + "smb_odir_state_t", od->d_state, + "SMB_ODIR_STATE_"); mdb_printf( "%<b>%<u>SMB odir information (%p):%</u>%</b>\n\n", @@ -1350,11 +1711,60 @@ smbodir_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * ***************************************************************************** */ -static const char *smb_ofile_state[SMB_OFILE_STATE_SENTINEL] = -{ - "OPEN", - "CLOSING", - "CLOSED" +typedef struct mdb_smb_ofile { + smb_ofile_state_t f_state; + + struct smb_server *f_server; + smb_session_t *f_session; + smb_user_t *f_user; + smb_tree_t *f_tree; + smb_node_t *f_node; + smb_odir_t *f_odir; + smb_opipe_t *f_pipe; + + uint32_t f_uniqid; + uint32_t f_refcnt; + uint32_t f_flags; + uint32_t f_granted_access; + uint32_t f_share_access; + + uint16_t f_fid; + uint16_t f_ftype; + uint64_t f_llf_pos; + int f_mode; + cred_t *f_cr; + pid_t f_pid; +} mdb_smb_ofile_t; + +static const mdb_bitmask_t +ofile_flag_bits[] = { + { "RO", + SMB_OFLAGS_READONLY, + SMB_OFLAGS_READONLY }, + { "EXEC", + SMB_OFLAGS_EXECONLY, + SMB_OFLAGS_EXECONLY }, + { "DELETE", + SMB_OFLAGS_SET_DELETE_ON_CLOSE, + SMB_OFLAGS_SET_DELETE_ON_CLOSE }, + { "POS_VALID", + SMB_OFLAGS_LLF_POS_VALID, + SMB_OFLAGS_LLF_POS_VALID }, + { NULL, 0, 0} +}; + +static const mdb_bitmask_t +smb_sharemode_bits[] = { + { "READ", + FILE_SHARE_READ, + FILE_SHARE_READ }, + { "WRITE", + FILE_SHARE_WRITE, + FILE_SHARE_WRITE }, + { "DELETE", + FILE_SHARE_DELETE, + FILE_SHARE_DELETE }, + { NULL, 0, 0} }; static int @@ -1374,20 +1784,20 @@ smbofile_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (((opts & SMB_OPT_WALK) && (opts & SMB_OPT_OFILE)) || !(opts & SMB_OPT_WALK)) { - smb_ofile_t *of; + mdb_smb_ofile_t *of; - of = mdb_alloc(sizeof (*of), UM_SLEEP | UM_GC); - if (mdb_vread(of, sizeof (*of), addr) == -1) { + of = mdb_zalloc(sizeof (*of), UM_SLEEP | UM_GC); + if (mdb_ctf_vread(of, SMBSRV_SCOPE "smb_ofile_t", + "mdb_smb_ofile_t", addr, 0) < 0) { mdb_warn("failed to read smb_ofile at %p", addr); return (DCMD_ERR); } if (opts & SMB_OPT_VERBOSE) { - const char *state; + char state[40]; - if (of->f_state >= SMB_OFILE_STATE_SENTINEL) - state = "INVALID"; - else - state = smb_ofile_state[of->f_state]; + get_enum(state, sizeof (state), + "smb_ofile_state_t", of->f_state, + "SMB_OFILE_STATE_"); mdb_printf( "%<b>%<u>SMB ofile information (%p):%</u>%</b>\n\n", @@ -1399,7 +1809,14 @@ smbofile_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) of->f_llf_pos, ((of->f_flags & SMB_OFLAGS_LLF_POS_VALID) ? "Valid" : "Invalid")); - mdb_printf("Flags: 0x%08x\n", of->f_flags); + mdb_printf("Flags: 0x%08x <%b>\n", of->f_flags, + of->f_flags, ofile_flag_bits); + mdb_printf("Granted Acc.: 0x%08x <%b>\n", + of->f_granted_access, + of->f_granted_access, nt_access_bits); + mdb_printf("Share Mode: 0x%08x <%b>\n", + of->f_share_access, + of->f_share_access, smb_sharemode_bits); mdb_printf("User: %p\n", of->f_user); mdb_printf("Tree: %p\n", of->f_tree); mdb_printf("Credential: %p\n\n", of->f_cr); @@ -1519,14 +1936,21 @@ smbshare_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) static int smb_kshare_walk_init(mdb_walk_state_t *wsp) { + int sv_exp_off, ex_sha_off, avl_tr_off; if (wsp->walk_addr == 0) { mdb_printf("require address of an smb_server_t\n"); return (WALK_ERR); } - wsp->walk_addr += - OFFSETOF(smb_server_t, sv_export.e_share_avl.avl_tree); + /* + * Using CTF to get the equivalent of: + * OFFSETOF(smb_server_t, sv_export.e_share_avl.avl_tree); + */ + GET_OFFSET(sv_exp_off, smb_server_t, sv_export); + GET_OFFSET(ex_sha_off, smb_export_t, e_share_avl); + GET_OFFSET(avl_tr_off, smb_avl_t, avl_tree); + wsp->walk_addr += (sv_exp_off + ex_sha_off + avl_tr_off); if (mdb_layered_walk("avl", wsp) == -1) { mdb_warn("failed to walk list of smb_kshare_t"); @@ -1645,14 +2069,21 @@ smbvfs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) static int smb_vfs_walk_init(mdb_walk_state_t *wsp) { + int sv_exp_off, ex_vfs_off, ll_off; if (wsp->walk_addr == 0) { mdb_printf("require address of an smb_server_t\n"); return (WALK_ERR); } - wsp->walk_addr += - OFFSETOF(smb_server_t, sv_export.e_vfs_list.ll_list); + /* + * Using CTF to get the equivalent of: + * OFFSETOF(smb_server_t, sv_export.e_vfs_list.ll_list); + */ + GET_OFFSET(sv_exp_off, smb_server_t, sv_export); + GET_OFFSET(ex_vfs_off, smb_export_t, e_vfs_list); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + wsp->walk_addr += (sv_exp_off + ex_vfs_off + ll_off); if (mdb_layered_walk("list", wsp) == -1) { mdb_warn("failed to walk list of smb_vfs_t"); @@ -1675,6 +2106,24 @@ smb_vfs_walk_step(mdb_walk_state_t *wsp) * ***************************************************************************** */ +typedef struct mdb_smb_node { + smb_node_state_t n_state; + uint32_t n_refcnt; + + uint32_t n_open_count; + uint32_t n_opening_count; + smb_llist_t n_ofile_list; + smb_llist_t n_lock_list; + volatile int flags; + smb_node_fcn_t n_fcn; + smb_oplock_t n_oplock; + struct smb_node *n_dnode; + struct smb_node *n_unode; + char od_name[MAXNAMELEN]; + vnode_t *vp; + smb_audit_buf_node_t *n_audit_buf; +} mdb_smb_node_t; + static void smbnode_help(void) { @@ -1698,7 +2147,7 @@ smbnode_help(void) static int smbnode_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - smb_node_t node; + mdb_smb_node_t node; int rc; int verbose = FALSE; int print_full_path = FALSE; @@ -1754,133 +2203,137 @@ smbnode_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * For each smb_node, we just need to read the smb_node_t struct, read * and then print out the following fields. */ - if (mdb_vread(&node, sizeof (node), addr) == sizeof (node)) { - (void) mdb_snprintf(od_name, sizeof (od_name), "%s", - node.od_name); - if (print_full_path) { - if (mdb_vread(&vnode, sizeof (vnode_t), - (uintptr_t)node.vp) == sizeof (vnode_t)) { - if (mdb_readstr(path_name, sizeof (path_name), - (uintptr_t)vnode.v_path) != 0) { - (void) mdb_snprintf(od_name, - sizeof (od_name), "N/A"); - } + if (mdb_ctf_vread(&node, SMBSRV_SCOPE "smb_node_t", + "mdb_smb_node_t", addr, 0) < 0) { + mdb_warn("failed to read struct smb_node at %p", addr); + return (DCMD_ERR); + } + + (void) mdb_snprintf(od_name, sizeof (od_name), "%s", + node.od_name); + if (print_full_path) { + if (mdb_vread(&vnode, sizeof (vnode_t), + (uintptr_t)node.vp) == sizeof (vnode_t)) { + if (mdb_readstr(path_name, sizeof (path_name), + (uintptr_t)vnode.v_path) != 0) { + (void) mdb_snprintf(od_name, + sizeof (od_name), "N/A"); } } - if (verbose) { - mdb_printf("VP: %p\n", node.vp); - mdb_printf("Name: %s\n", od_name); - if (print_full_path) - mdb_printf("V-node Path: %s\n", path_name); - mdb_printf("Ofiles: %u\n", node.n_ofile_list.ll_count); - mdb_printf("Range Locks: %u\n", - node.n_lock_list.ll_count); - if (node.n_lock_list.ll_count != 0) { - (void) mdb_inc_indent(SMB_DCMD_INDENT); - list_addr = addr + - OFFSETOF(smb_node_t, n_lock_list) + - OFFSETOF(smb_llist_t, ll_list); - if (mdb_pwalk_dcmd("list", "smblock", 0, - NULL, list_addr)) { - mdb_warn("failed to walk node's active" - " locks"); - } - (void) mdb_dec_indent(SMB_DCMD_INDENT); - } - if (node.n_oplock.ol_count == 0) { - mdb_printf("Opportunistic Locks: 0\n"); - } else { - oplock_addr = - addr + OFFSETOF(smb_node_t, n_oplock); - mdb_printf("Opportunistic Lock: %p\n", - oplock_addr); - rc = mdb_call_dcmd("smboplock", oplock_addr, - flags, argc, argv); - if (rc != DCMD_OK) - return (rc); + } + if (verbose) { + int nll_off, nol_off, ll_off; + + GET_OFFSET(nll_off, smb_node_t, n_lock_list); + GET_OFFSET(nol_off, smb_node_t, n_oplock); + GET_OFFSET(ll_off, smb_llist_t, ll_list); + + mdb_printf("VP: %p\n", node.vp); + mdb_printf("Name: %s\n", od_name); + if (print_full_path) + mdb_printf("V-node Path: %s\n", path_name); + mdb_printf("Ofiles: %u\n", node.n_ofile_list.ll_count); + mdb_printf("Range Locks: %u\n", + node.n_lock_list.ll_count); + if (node.n_lock_list.ll_count != 0) { + (void) mdb_inc_indent(SMB_DCMD_INDENT); + list_addr = addr + nll_off + ll_off; + if (mdb_pwalk_dcmd("list", "smblock", 0, + NULL, list_addr)) { + mdb_warn("failed to walk node's active" + " locks"); } - mdb_printf("Reference Count: %u\n\n", node.n_refcnt); + (void) mdb_dec_indent(SMB_DCMD_INDENT); + } + if (node.n_oplock.ol_count == 0) { + mdb_printf("Opportunistic Locks: 0\n"); } else { - mdb_printf("%-?p %-?p %-18s %-6d %-6d %-8d %-6d ", - addr, node.vp, od_name, node.n_ofile_list.ll_count, - node.n_lock_list.ll_count, - node.n_oplock.ol_count, node.n_refcnt); - - if (print_full_path) - mdb_printf("\t%s\n", path_name); + oplock_addr = addr + nol_off; + mdb_printf("Opportunistic Lock: %p\n", + oplock_addr); + rc = mdb_call_dcmd("smboplock", oplock_addr, + flags, argc, argv); + if (rc != DCMD_OK) + return (rc); } - if (stack_trace && node.n_audit_buf) { - int ctr; - smb_audit_buf_node_t *anb; + mdb_printf("Reference Count: %u\n\n", node.n_refcnt); + } else { + mdb_printf("%-?p %-?p %-18s %-6d %-6d %-8d %-6d ", + addr, node.vp, od_name, node.n_ofile_list.ll_count, + node.n_lock_list.ll_count, + node.n_oplock.ol_count, node.n_refcnt); - anb = mdb_alloc(sizeof (smb_audit_buf_node_t), - UM_SLEEP | UM_GC); + if (print_full_path) + mdb_printf("\t%s\n", path_name); + } + if (stack_trace && node.n_audit_buf) { + int ctr; + smb_audit_buf_node_t *anb; - if (mdb_vread(anb, sizeof (*anb), - (uintptr_t)node.n_audit_buf) != sizeof (*anb)) { - mdb_warn("failed to read audit buffer"); - return (DCMD_ERR); - } - ctr = anb->anb_max_index + 1; - anb->anb_index--; - anb->anb_index &= anb->anb_max_index; + anb = mdb_alloc(sizeof (smb_audit_buf_node_t), + UM_SLEEP | UM_GC); - while (ctr) { - smb_audit_record_node_t *anr; - - anr = anb->anb_records + anb->anb_index; - - if (anr->anr_depth) { - char c[MDB_SYM_NAMLEN]; - GElf_Sym sym; - int i; - - mdb_printf("\nRefCnt: %u\t", - anr->anr_refcnt); - - for (i = 0; - i < anr->anr_depth; - i++) { - if (mdb_lookup_by_addr( - anr->anr_stack[i], - MDB_SYM_FUZZY, - c, sizeof (c), - &sym) == -1) { - continue; - } - mdb_printf("%s+0x%1x", - c, - anr->anr_stack[i] - - (uintptr_t)sym.st_value); - ++i; - break; + if (mdb_vread(anb, sizeof (*anb), + (uintptr_t)node.n_audit_buf) != sizeof (*anb)) { + mdb_warn("failed to read audit buffer"); + return (DCMD_ERR); + } + ctr = anb->anb_max_index + 1; + anb->anb_index--; + anb->anb_index &= anb->anb_max_index; + + while (ctr) { + smb_audit_record_node_t *anr; + + anr = anb->anb_records + anb->anb_index; + + if (anr->anr_depth) { + char c[MDB_SYM_NAMLEN]; + GElf_Sym sym; + int i; + + mdb_printf("\nRefCnt: %u\t", + anr->anr_refcnt); + + for (i = 0; + i < anr->anr_depth; + i++) { + if (mdb_lookup_by_addr( + anr->anr_stack[i], + MDB_SYM_FUZZY, + c, sizeof (c), + &sym) == -1) { + continue; } + mdb_printf("%s+0x%1x", + c, + anr->anr_stack[i] - + (uintptr_t)sym.st_value); + ++i; + break; + } - while (i < anr->anr_depth) { - if (mdb_lookup_by_addr( - anr->anr_stack[i], - MDB_SYM_FUZZY, - c, sizeof (c), - &sym) == -1) { - ++i; - continue; - } - mdb_printf("\n\t\t%s+0x%1x", - c, - anr->anr_stack[i] - - (uintptr_t)sym.st_value); + while (i < anr->anr_depth) { + if (mdb_lookup_by_addr( + anr->anr_stack[i], + MDB_SYM_FUZZY, + c, sizeof (c), + &sym) == -1) { ++i; + continue; } - mdb_printf("\n"); + mdb_printf("\n\t\t%s+0x%1x", + c, + anr->anr_stack[i] - + (uintptr_t)sym.st_value); + ++i; } - anb->anb_index--; - anb->anb_index &= anb->anb_max_index; - ctr--; + mdb_printf("\n"); } + anb->anb_index--; + anb->anb_index &= anb->anb_max_index; + ctr--; } - } else { - mdb_warn("failed to read struct smb_node at %p", addr); - return (DCMD_ERR); } return (DCMD_OK); @@ -1894,8 +2347,9 @@ static int smb_node_walk_init(mdb_walk_state_t *wsp) { GElf_Sym sym; - int i; uintptr_t node_hash_table_addr; + int ll_off; + int i; if (wsp->walk_addr == 0) { if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_node_hash_table", @@ -1909,9 +2363,11 @@ smb_node_walk_init(mdb_walk_state_t *wsp) return (WALK_ERR); } + GET_OFFSET(ll_off, smb_llist_t, ll_list); + for (i = 0; i < SMBND_HASH_MASK + 1; i++) { wsp->walk_addr = node_hash_table_addr + - (i * sizeof (smb_llist_t)) + OFFSETOF(smb_llist_t, ll_list); + (i * sizeof (smb_llist_t)) + ll_off; if (mdb_layered_walk("list", wsp) == -1) { mdb_warn("failed to walk 'list'"); return (WALK_ERR); @@ -1934,10 +2390,27 @@ smb_node_walk_step(mdb_walk_state_t *wsp) * ***************************************************************************** */ +typedef struct mdb_smb_lock { + smb_slist_t l_conflict_list; + + smb_session_t *l_session; + smb_ofile_t *l_file; + struct smb_request *l_sr; + + uint32_t l_flags; + struct smb_lock *l_blocked_by; /* Debug info only */ + + uint32_t l_pid; + uint16_t l_uid; + uint32_t l_type; + uint64_t l_start; + uint64_t l_length; +} mdb_smb_lock_t; + static int smblock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - smb_lock_t lock; + mdb_smb_lock_t lock; int verbose = FALSE; uintptr_t list_addr; char *lock_type; @@ -1966,60 +2439,64 @@ smblock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) "CONFLICTS"); } - if (mdb_vread(&lock, sizeof (lock), addr) == sizeof (lock)) { - switch (lock.l_type) { - case SMB_LOCK_TYPE_READWRITE: - lock_type = "RW"; - break; - case SMB_LOCK_TYPE_READONLY: - lock_type = "RO"; - break; - default: - lock_type = "N/A"; - break; - } - if (verbose) { - mdb_printf("Type :\t%s (%u)\n", - lock_type, lock.l_type); - mdb_printf("Start :\t%llx\n", - lock.l_start); - mdb_printf("Length :\t%lx\n", - lock.l_length); - mdb_printf("Session :\t%p\n", - lock.l_session); - mdb_printf("File :\t%p\n", - lock.l_file); - mdb_printf("User ID :\t%u\n", - lock.l_uid); - mdb_printf("Process ID :\t%u\n", - lock.l_pid); - mdb_printf("Conflicts :\t%u\n", - lock.l_conflict_list.sl_count); - if (lock.l_conflict_list.sl_count != 0) { - (void) mdb_inc_indent(SMB_DCMD_INDENT); - list_addr = addr + - OFFSETOF(smb_lock_t, l_conflict_list) + - OFFSETOF(smb_slist_t, sl_list); - if (mdb_pwalk_dcmd("list", "smb_lock", - 0, NULL, list_addr)) { - mdb_warn("failed to walk conflict " - "locks "); - } - (void) mdb_dec_indent(SMB_DCMD_INDENT); + if (mdb_ctf_vread(&lock, SMBSRV_SCOPE "smb_lock_t", + "mdb_smb_lock_t", addr, 0) < 0) { + mdb_warn("failed to read struct smb_request at %p", addr); + return (DCMD_ERR); + } + + switch (lock.l_type) { + case SMB_LOCK_TYPE_READWRITE: + lock_type = "RW"; + break; + case SMB_LOCK_TYPE_READONLY: + lock_type = "RO"; + break; + default: + lock_type = "N/A"; + break; + } + if (verbose) { + int lcl_off, sl_off; + + GET_OFFSET(lcl_off, smb_lock_t, l_conflict_list); + GET_OFFSET(sl_off, smb_slist_t, sl_list); + + mdb_printf("Type :\t%s (%u)\n", + lock_type, lock.l_type); + mdb_printf("Start :\t%llx\n", + lock.l_start); + mdb_printf("Length :\t%lx\n", + lock.l_length); + mdb_printf("Session :\t%p\n", + lock.l_session); + mdb_printf("File :\t%p\n", + lock.l_file); + mdb_printf("User ID :\t%u\n", + lock.l_uid); + mdb_printf("Process ID :\t%u\n", + lock.l_pid); + mdb_printf("Conflicts :\t%u\n", + lock.l_conflict_list.sl_count); + if (lock.l_conflict_list.sl_count != 0) { + (void) mdb_inc_indent(SMB_DCMD_INDENT); + list_addr = addr + lcl_off + sl_off; + if (mdb_pwalk_dcmd("list", "smb_lock", + 0, NULL, list_addr)) { + mdb_warn("failed to walk conflict " + "locks "); } - mdb_printf("Blocked by :\t%p\n", - lock.l_blocked_by); - mdb_printf("Flags :\t0x%x\n", - lock.l_flags); - mdb_printf("\n"); - } else { - mdb_printf("%?p %4s %16llx %08lx %9x", addr, - lock_type, lock.l_start, lock.l_length, - lock.l_conflict_list.sl_count); + (void) mdb_dec_indent(SMB_DCMD_INDENT); } + mdb_printf("Blocked by :\t%p\n", + lock.l_blocked_by); + mdb_printf("Flags :\t0x%x\n", + lock.l_flags); + mdb_printf("\n"); } else { - mdb_warn("failed to read struct smb_request at %p", addr); - return (DCMD_ERR); + mdb_printf("%?p %4s %16llx %08lx %9x", addr, + lock_type, lock.l_start, lock.l_length, + lock.l_conflict_list.sl_count); } return (DCMD_OK); @@ -2030,12 +2507,23 @@ smblock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * ************************** smb_oplock_grant_t ******************************* * ***************************************************************************** */ + +typedef struct mdb_smb_oplock_grant { + uint8_t og_breaking; + uint8_t og_level; + uint16_t og_fid; + uint16_t og_tid; + uint16_t og_uid; + struct smb_session *og_session; + struct smb_ofile *og_ofile; +} mdb_smb_oplock_grant_t; + /*ARGSUSED*/ static int smboplockgrant_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - smb_oplock_grant_t grant; + mdb_smb_oplock_grant_t grant; char *level; if (!(flags & DCMD_ADDRSPEC)) @@ -2050,24 +2538,28 @@ smboplockgrant_dcmd(uintptr_t addr, uint_t flags, int argc, "Grants:", "LEVEL", "OFILE"); } - if (mdb_vread(&grant, sizeof (grant), addr) == sizeof (grant)) { - switch (grant.og_level) { - case SMB_OPLOCK_EXCLUSIVE: - level = "EXCLUSIVE"; - break; - case SMB_OPLOCK_BATCH: - level = "BATCH"; - break; - case SMB_OPLOCK_LEVEL_II: - level = "LEVEL_II"; - break; - default: - level = "UNKNOWN"; - break; - } + if (mdb_ctf_vread(&grant, SMBSRV_SCOPE "smb_oplock_grant_t", + "mdb_smb_oplock_grant_t", addr, 0) < 0) { + mdb_warn("failed to read oplock grant at %p", addr); + return (DCMD_ERR); + } - mdb_printf("%-16p %-10s %-16p", addr, level, grant.og_ofile); + switch (grant.og_level) { + case SMB_OPLOCK_EXCLUSIVE: + level = "EXCLUSIVE"; + break; + case SMB_OPLOCK_BATCH: + level = "BATCH"; + break; + case SMB_OPLOCK_LEVEL_II: + level = "LEVEL_II"; + break; + default: + level = "UNKNOWN"; + break; } + + mdb_printf("%-16p %-10s %-16p", addr, level, grant.og_ofile); return (DCMD_OK); } @@ -2076,17 +2568,27 @@ smboplockgrant_dcmd(uintptr_t addr, uint_t flags, int argc, * ***************************** smb_oplock_t ********************************** * ***************************************************************************** */ + +typedef struct mdb_smb_oplock { + uint8_t ol_brk_pending; + uint8_t ol_break; + uint32_t ol_count; /* number of grants */ + list_t ol_grants; /* list of smb_oplock_grant_t */ +} mdb_smb_oplock_t; + /*ARGSUSED*/ static int smboplock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - smb_oplock_t oplock; + mdb_smb_oplock_t oplock; uintptr_t list_addr; + int og_off; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); - if (mdb_vread(&oplock, sizeof (oplock), addr) != sizeof (oplock)) { + if (mdb_ctf_vread(&oplock, SMBSRV_SCOPE "smb_oplock_t", + "mdb_smb_oplock_t", addr, 0) < 0) { mdb_warn("failed to read struct smb_oplock at %p", addr); return (DCMD_ERR); } @@ -2107,7 +2609,8 @@ smboplock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) break; } - list_addr = addr + OFFSETOF(smb_oplock_t, ol_grants); + GET_OFFSET(og_off, smb_oplock_t, ol_grants); + list_addr = addr + og_off; if (mdb_pwalk_dcmd("list", "smboplockgrant", argc, argv, list_addr)) { @@ -2205,43 +2708,6 @@ smb_mbuf_walk_step(mdb_walk_state_t *wsp) } /* - * ******************************************************************* - * ::smbstat - * - * Prints SMB requests statistics. - */ -/*ARGSUSED*/ -static int -smbstat_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - smb_server_t *sv; - - if (!(flags & DCMD_ADDRSPEC)) - return (DCMD_USAGE); - - sv = mdb_alloc(sizeof (*sv), UM_SLEEP | UM_GC); - if (mdb_vread(sv, sizeof (*sv), addr) == -1) { - mdb_warn("failed to read server object at %p", addr); - return (DCMD_ERR); - } - if (sv->sv_magic != SMB_SERVER_MAGIC) { - mdb_warn("not an smb_server_t (%p)>", addr); - return (DCMD_ERR); - } - mdb_printf( - "\n%<b> nbt tcp users trees files pipes%</b>\n" - "%5d %5d %5d %5d %5d %5d\n", - sv->sv_nbt_sess, - sv->sv_tcp_sess, - sv->sv_users, - sv->sv_trees, - sv->sv_files, - sv->sv_pipes); - - return (DCMD_OK); -} - -/* * ***************************************************************************** * ******************************** smb_ace_t ********************************** * ***************************************************************************** @@ -2351,12 +2817,15 @@ smbace_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) static int smb_ace_walk_init(mdb_walk_state_t *wsp) { + int sal_off; + if (wsp->walk_addr == 0) { mdb_printf("smb_ace walk only supports local walks\n"); return (WALK_ERR); } - wsp->walk_addr += OFFSETOF(smb_acl_t, sl_sorted); + GET_OFFSET(sal_off, smb_acl_t, sl_sorted); + wsp->walk_addr += sal_off; if (mdb_layered_walk("list", wsp) == -1) { mdb_warn("failed to walk list of ACEs"); @@ -2528,10 +2997,12 @@ smb_sid_print(uintptr_t addr) smb_sid_t sid; smb_sid_t *psid; size_t sid_size; - int i; uint64_t authority; + int ssa_off; + int i; - sid_size = OFFSETOF(smb_sid_t, sid_subauth); + GET_OFFSET(ssa_off, smb_sid_t, sid_subauth); + sid_size = ssa_off; if (mdb_vread(&sid, sid_size, addr) != sid_size) { mdb_warn("failed to read struct smb_sid at %p", addr); @@ -2684,6 +3155,7 @@ static int smb_obj_expand(uintptr_t addr, uint_t opts, const smb_exp_t *x, ulong_t indent) { int rc = 0; + int ex_off; int argc; mdb_arg_t argv[SMB_MDB_MAX_OPTS]; @@ -2692,12 +3164,13 @@ smb_obj_expand(uintptr_t addr, uint_t opts, const smb_exp_t *x, ulong_t indent) (void) mdb_inc_indent(indent); while (x->ex_dcmd) { if (x->ex_mask & opts) { + ex_off = (x->ex_offset)(); rc = mdb_pwalk_dcmd("list", x->ex_dcmd, argc, argv, - addr + x->ex_offset); + addr + ex_off); if (rc) { mdb_warn("failed to walk the list of %s in %p", - x->ex_name, addr + x->ex_offset); + x->ex_name, addr + ex_off); break; } } @@ -2768,6 +3241,34 @@ smb_inaddr_ntop(smb_inaddr_t *ina, char *buf, size_t sz) } /* + * Get the name for an enum value + */ +static void +get_enum(char *out, size_t size, const char *type_str, int val, + const char *prefix) +{ + mdb_ctf_id_t type_id; + const char *cp; + + if (mdb_ctf_lookup_by_name(type_str, &type_id) != 0) + goto errout; + if (mdb_ctf_type_resolve(type_id, &type_id) != 0) + goto errout; + if ((cp = mdb_ctf_enum_name(type_id, val)) == NULL) + goto errout; + if (prefix != NULL) { + size_t len = strlen(prefix); + if (strncmp(cp, prefix, len) == 0) + cp += len; + } + (void) strncpy(out, cp, size); + return; + +errout: + mdb_snprintf(out, size, "? (%d)", val); +} + +/* * MDB module linkage information: * * We declare a list of structures describing our dcmds, a list of structures @@ -2839,9 +3340,6 @@ static const mdb_dcmd_t dcmds[] = { { "smboplockgrant", NULL, "print smb_oplock_grant_t information", smboplockgrant_dcmd }, - { "smbstat", NULL, - "print all smb dispatched requests statistics", - smbstat_dcmd }, { "smbace", "[-v]", "print smb_ace_t information", smbace_dcmd }, |
