Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)

@@ -18,13 +18,14 @@
  *
  * CDDL HEADER END
  */
 
 /*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 
 #include <sys/mdb_modapi.h>
 #include <mdb/mdb_ctf.h>

@@ -33,10 +34,16 @@
 
 #include <netsmb/smb_conn.h>
 #include <netsmb/smb_rq.h>
 #include <netsmb/smb_pass.h>
 
+#ifdef _KERNEL
+#define NSMB_OBJNAME    "nsmb"
+#else
+#define NSMB_OBJNAME    "libfknsmb.so.1"
+#endif
+
 #define OPT_VERBOSE     0x0001  /* Be [-v]erbose in dcmd's */
 #define OPT_RECURSE     0x0002  /* recursive display */
 
 /*
  * We need to read in a private copy

@@ -64,16 +71,17 @@
  * Tricky: Exploit the "inheritance" of smb_connobj_t
  * with common functions for walk_init, walk_next.
  */
 typedef struct smb_co_walk_data {
         uintptr_t       pp;
-        int level;              /* SMBL_SM, SMBL_VC, SMBL_SHARE  */
+        int level;              /* SMBL_SM, SMBL_VC, SMBL_SHARE, ...  */
         int size;               /* sizeof (union member) */
         union co_u {
                 smb_connobj_t   co;     /* copy of the list element */
                 smb_vc_t        vc;
                 smb_share_t     ss;
+                smb_fh_t        fh;
         } u;
 } smb_co_walk_data_t;
 
 /*
  * Common walk_init for walking structs inherited

@@ -106,10 +114,13 @@
                 smbw->size = sizeof (smbw->u.vc);
                 break;
         case SMBL_SHARE:
                 smbw->size = sizeof (smbw->u.ss);
                 break;
+        case SMBL_FH:
+                smbw->size = sizeof (smbw->u.fh);
+                break;
         default:
                 smbw->size = sizeof (smbw->u);
                 break;
         }
 

@@ -144,11 +155,11 @@
                 mdb_warn("::walk smb_vc only supports global walks\n");
                 return (WALK_ERR);
         }
 
         /* Locate the VC list head. */
-        if (mdb_lookup_by_obj("nsmb", "smb_vclist", &sym)) {
+        if (mdb_lookup_by_obj(NSMB_OBJNAME, "smb_vclist", &sym)) {
                 mdb_warn("failed to lookup `smb_vclist'\n");
                 return (WALK_ERR);
         }
         wsp->walk_addr = sym.st_value;
 

@@ -172,10 +183,28 @@
 
         return (smb_co_walk_init(wsp, SMBL_SHARE));
 }
 
 /*
+ * Walk the file hande list below some share.
+ */
+int
+smb_fh_walk_init(mdb_walk_state_t *wsp)
+{
+
+        /*
+         * Initial walk_addr is address of parent (share)
+         */
+        if (wsp->walk_addr == 0) {
+                mdb_warn("::walk smb_fh does not support global walks\n");
+                return (WALK_ERR);
+        }
+
+        return (smb_co_walk_init(wsp, SMBL_FH));
+}
+
+/*
  * Common walk_step for walking structs inherited
  * from smb_connobj_t (smb_vc_t, smb_share_t)
  */
 int
 smb_co_walk_step(mdb_walk_state_t *wsp)

@@ -213,23 +242,55 @@
         int printed_header;
         mdb_ctf_id_t ctf_id;
 } smb_co_cbdata_t;
 
 /*
+ * Call-back function for walking a file handle list.
+ */
+/* ARGSUSED */
+int
+smb_fh_cb(uintptr_t addr, const void *data, void *arg)
+{
+        const smb_fh_t *fhp = data;
+        // smb_co_cbdata_t *cbd = arg;
+
+        mdb_inc_indent(2);
+        mdb_printf(" %-p", addr);
+        if (fhp->fh_fid2.fid_volatile != 0) {
+                mdb_printf("\t0x%llx\n",
+                    (long long) fhp->fh_fid2.fid_volatile);
+        } else {
+                mdb_printf("\t0x%x\n", fhp->fh_fid1);
+        }
+
+        mdb_dec_indent(2);
+
+        return (WALK_NEXT);
+}
+
+/*
  * Call-back function for walking a share list.
  */
 int
 smb_ss_cb(uintptr_t addr, const void *data, void *arg)
 {
         const smb_share_t *ssp = data;
         smb_co_cbdata_t *cbd = arg;
+        uint32_t tid;
 
-        mdb_printf(" %-p\t%s\n", addr, ssp->ss_name);
+        tid = ssp->ss2_tree_id;
+        if (tid == 0)
+                tid = ssp->ss_tid;
 
-        if (cbd->flags & OPT_VERBOSE) {
+        mdb_printf(" %-p\t0x%x\t%s\n", addr, tid, ssp->ss_name);
+
+        if (cbd->flags & OPT_RECURSE) {
                 mdb_inc_indent(2);
-                /* Anything wanted here? */
+                if (mdb_pwalk("nsmb_fh", smb_fh_cb, cbd, addr) < 0) {
+                        mdb_warn("failed to walk 'nsmb_fh'");
+                        /* Don't: return (WALK_ERR); */
+                }
                 mdb_dec_indent(2);
         }
 
         return (WALK_NEXT);
 }

@@ -406,10 +467,11 @@
         return (status);
 }
 
 typedef struct rqlist_cbdata {
         int printed_header;
+        int vcflags;
         uintptr_t uid;          /* optional filtering by UID */
 } rqlist_cbdata_t;
 
 int
 rqlist_cb(uintptr_t addr, const void *data, void *arg)

@@ -421,12 +483,17 @@
                 cbd->printed_header = 1;
                 mdb_printf("// smb_rq_t MID cmd sr_state sr_flags\n");
         }
 
         mdb_printf(" %-p", addr);       /* smb_rq_t */
+        if ((cbd->vcflags & SMBV_SMB2) != 0) {
+                mdb_printf(" x%04llx", (long long)rq->sr2_messageid);
+                mdb_printf(" x%02x", rq->sr2_command);
+        } else {
         mdb_printf(" x%04x", rq->sr_mid);
         mdb_printf(" x%02x", rq->sr_cmd);
+        }
         mdb_printf(" %d", rq->sr_state);
         mdb_printf(" x%x", rq->sr_flags);
         mdb_printf("\n");
 
         return (WALK_NEXT);

@@ -435,13 +502,24 @@
 /*ARGSUSED*/
 int
 rqlist_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 {
         rqlist_cbdata_t cbd;
+        smb_vc_t *vcp;
+        size_t vcsz;
 
         memset(&cbd, 0, sizeof (cbd));
 
+        /* Need the VC again to get  */
+        vcsz = sizeof (*vcp);
+        vcp = mdb_alloc(vcsz, UM_SLEEP | UM_GC);
+        if (mdb_vread(vcp, vcsz, addr) != vcsz) {
+                mdb_warn("cannot read VC from %p", addr);
+                return (DCMD_ERR);
+        }
+        cbd.vcflags = vcp->vc_flags;
+
         /*
          * Initial walk_addr is address of parent (VC)
          */
         if (!(flags & DCMD_ADDRSPEC)) {
                 mdb_warn("address required\n");

@@ -469,11 +547,11 @@
         if (wsp->walk_addr != NULL) {
                 mdb_warn("pwtree walk only supports global walks\n");
                 return (WALK_ERR);
         }
 
-        if (mdb_lookup_by_obj("nsmb", "smb_ptd", &sym) == -1) {
+        if (mdb_lookup_by_obj(NSMB_OBJNAME, "smb_ptd", &sym) == -1) {
                 mdb_warn("failed to find symbol 'smb_ptd'");
                 return (WALK_ERR);
         }
 
         wsp->walk_addr = (uintptr_t)sym.st_value;

@@ -598,10 +676,12 @@
 static const mdb_walker_t walkers[] = {
         { "nsmb_vc", "walk nsmb VC list",
                 smb_vc_walk_init, smb_co_walk_step, NULL },
         { "nsmb_ss", "walk nsmb share list for some VC",
                 smb_ss_walk_init, smb_co_walk_step, NULL },
+        { "nsmb_fh", "walk nsmb share list for some VC",
+                smb_fh_walk_init, smb_co_walk_step, NULL },
         { "nsmb_rqlist", "walk request list for some VC",
                 rqlist_walk_init, rqlist_walk_step, NULL },
         { "nsmb_pwtree", "walk passord AVL tree",
                 pwtree_walk_init, pwtree_walk_step, NULL },
         {NULL}