14bff34e3Sthurlow /* 24bff34e3Sthurlow * CDDL HEADER START 34bff34e3Sthurlow * 44bff34e3Sthurlow * The contents of this file are subject to the terms of the 54bff34e3Sthurlow * Common Development and Distribution License (the "License"). 64bff34e3Sthurlow * You may not use this file except in compliance with the License. 74bff34e3Sthurlow * 84bff34e3Sthurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94bff34e3Sthurlow * or http://www.opensolaris.org/os/licensing. 104bff34e3Sthurlow * See the License for the specific language governing permissions 114bff34e3Sthurlow * and limitations under the License. 124bff34e3Sthurlow * 134bff34e3Sthurlow * When distributing Covered Code, include this CDDL HEADER in each 144bff34e3Sthurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154bff34e3Sthurlow * If applicable, add the following below this CDDL HEADER, with the 164bff34e3Sthurlow * fields enclosed by brackets "[]" replaced with your own identifying 174bff34e3Sthurlow * information: Portions Copyright [yyyy] [name of copyright owner] 184bff34e3Sthurlow * 194bff34e3Sthurlow * CDDL HEADER END 204bff34e3Sthurlow */ 214bff34e3Sthurlow 224bff34e3Sthurlow /* 23*430b4c46SGordon Ross * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 2402d09e03SGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 254bff34e3Sthurlow * Use is subject to license terms. 264bff34e3Sthurlow */ 274bff34e3Sthurlow 284bff34e3Sthurlow #include <sys/mdb_modapi.h> 294bff34e3Sthurlow #include <sys/types.h> 304bff34e3Sthurlow #include <sys/refstr_impl.h> 314bff34e3Sthurlow #include <sys/vnode.h> 324bff34e3Sthurlow #include <sys/vfs.h> 334bff34e3Sthurlow 34*430b4c46SGordon Ross #include <smbfs/smbfs.h> 35*430b4c46SGordon Ross #include <smbfs/smbfs_node.h> 364bff34e3Sthurlow 374bff34e3Sthurlow #define OPT_VERBOSE 0x0001 /* Be [-v]erbose in dcmd's */ 384bff34e3Sthurlow 394bff34e3Sthurlow /* 404bff34e3Sthurlow * This macro lets us easily use both sizeof (typename) 414bff34e3Sthurlow * and the string-ified typename for the error message. 424bff34e3Sthurlow */ 434bff34e3Sthurlow #define SMBFS_OBJ_FETCH(obj_addr, obj_type, dest, err) \ 444bff34e3Sthurlow if (mdb_vread(dest, sizeof (obj_type), ((uintptr_t)obj_addr)) \ 454bff34e3Sthurlow != sizeof (obj_type)) { \ 464bff34e3Sthurlow mdb_warn("error reading "#obj_type" at %p", obj_addr); \ 474bff34e3Sthurlow return (err); \ 484bff34e3Sthurlow } 494bff34e3Sthurlow 504bff34e3Sthurlow /* 514bff34e3Sthurlow * We need to read in a private copy 524bff34e3Sthurlow * of every string we want to print out. 534bff34e3Sthurlow */ 544bff34e3Sthurlow void 554bff34e3Sthurlow print_str(uintptr_t addr) 564bff34e3Sthurlow { 574bff34e3Sthurlow char buf[64]; 584bff34e3Sthurlow int len, mx = sizeof (buf) - 4; 594bff34e3Sthurlow 604bff34e3Sthurlow if ((len = mdb_readstr(buf, sizeof (buf), addr)) <= 0) { 614bff34e3Sthurlow mdb_printf(" (%p)", addr); 624bff34e3Sthurlow } else { 634bff34e3Sthurlow if (len > mx) 644bff34e3Sthurlow strcpy(&buf[mx], "..."); 654bff34e3Sthurlow mdb_printf(" %s", buf); 664bff34e3Sthurlow } 674bff34e3Sthurlow } 684bff34e3Sthurlow 694bff34e3Sthurlow /* 704bff34e3Sthurlow * Dcmd (and callback function) to print a summary of 714bff34e3Sthurlow * all "smbfs" entries in the VFS list. 724bff34e3Sthurlow */ 734bff34e3Sthurlow 744bff34e3Sthurlow typedef struct smbfs_vfs_cbdata { 754bff34e3Sthurlow int flags; 764bff34e3Sthurlow int printed_header; 774bff34e3Sthurlow uintptr_t vfsops; /* filter by vfs ops pointer */ 784bff34e3Sthurlow smbmntinfo_t smi; /* scratch space for smbfs_vfs_cb */ 794bff34e3Sthurlow } smbfs_vfs_cbdata_t; 804bff34e3Sthurlow 814bff34e3Sthurlow int 824bff34e3Sthurlow smbfs_vfs_cb(uintptr_t addr, const void *data, void *arg) 834bff34e3Sthurlow { 844bff34e3Sthurlow const vfs_t *vfs = data; 854bff34e3Sthurlow smbfs_vfs_cbdata_t *cbd = arg; 864bff34e3Sthurlow uintptr_t ta; 874bff34e3Sthurlow 884bff34e3Sthurlow /* Filter by matching smbfs ops vector. */ 894bff34e3Sthurlow if (cbd->vfsops && cbd->vfsops != (uintptr_t)vfs->vfs_op) { 904bff34e3Sthurlow return (WALK_NEXT); 914bff34e3Sthurlow } 924bff34e3Sthurlow 934bff34e3Sthurlow if (cbd->printed_header == 0) { 944bff34e3Sthurlow cbd->printed_header = 1; 954bff34e3Sthurlow mdb_printf("// vfs_t smbmntinfo_t mnt_path\n"); 964bff34e3Sthurlow } 974bff34e3Sthurlow 984bff34e3Sthurlow mdb_printf(" %-p", addr); /* vfs_t */ 994bff34e3Sthurlow mdb_printf(" %-p", (uintptr_t)vfs->vfs_data); 1004bff34e3Sthurlow /* 1014bff34e3Sthurlow * Note: vfs_mntpt is a refstr_t. 1024bff34e3Sthurlow * Advance to string member. 1034bff34e3Sthurlow */ 1044bff34e3Sthurlow ta = (uintptr_t)vfs->vfs_mntpt; 1054bff34e3Sthurlow ta += OFFSETOF(struct refstr, rs_string); 1064bff34e3Sthurlow print_str(ta); 1074bff34e3Sthurlow mdb_printf("\n"); 1084bff34e3Sthurlow 1094bff34e3Sthurlow if (cbd->flags & OPT_VERBOSE) { 1104bff34e3Sthurlow mdb_inc_indent(2); 1114bff34e3Sthurlow /* Don't fail the walk if this fails. */ 1124bff34e3Sthurlow if (mdb_vread(&cbd->smi, sizeof (cbd->smi), 1134bff34e3Sthurlow (uintptr_t)vfs->vfs_data) == -1) { 1144bff34e3Sthurlow mdb_warn("error reading smbmntinfo_t at %p", 1154bff34e3Sthurlow (uintptr_t)vfs->vfs_data); 1164bff34e3Sthurlow } else { 1174bff34e3Sthurlow /* Interesting parts of smbmntinfo_t */ 1184bff34e3Sthurlow mdb_printf("smi_share: %p, smi_root: %p\n", 1194bff34e3Sthurlow cbd->smi.smi_share, cbd->smi.smi_root); 1204bff34e3Sthurlow } 1214bff34e3Sthurlow mdb_dec_indent(2); 1224bff34e3Sthurlow } 1234bff34e3Sthurlow 1244bff34e3Sthurlow return (WALK_NEXT); 1254bff34e3Sthurlow } 1264bff34e3Sthurlow 1274bff34e3Sthurlow int 1284bff34e3Sthurlow smbfs_vfs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1294bff34e3Sthurlow { 1304bff34e3Sthurlow smbfs_vfs_cbdata_t *cbd; 1314bff34e3Sthurlow vfs_t *vfs; 1324bff34e3Sthurlow 1334bff34e3Sthurlow cbd = mdb_zalloc(sizeof (*cbd), UM_SLEEP | UM_GC); 1344bff34e3Sthurlow 1354bff34e3Sthurlow /* 1364bff34e3Sthurlow * Get the ops address here, so things work 1374bff34e3Sthurlow * even if the smbfs module is loaded later 1384bff34e3Sthurlow * than this mdb module. 1394bff34e3Sthurlow */ 1404bff34e3Sthurlow if (mdb_readvar(&cbd->vfsops, "smbfs_vfsops") == -1) { 1414bff34e3Sthurlow mdb_warn("failed to find 'smbfs_vfsops'\n"); 1424bff34e3Sthurlow return (DCMD_ERR); 1434bff34e3Sthurlow } 1444bff34e3Sthurlow 1454bff34e3Sthurlow if (mdb_getopts(argc, argv, 1464bff34e3Sthurlow 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd->flags, 1474bff34e3Sthurlow NULL) != argc) { 1484bff34e3Sthurlow return (DCMD_USAGE); 1494bff34e3Sthurlow } 1504bff34e3Sthurlow 1514bff34e3Sthurlow if (!(flags & DCMD_ADDRSPEC)) { 1524bff34e3Sthurlow if (mdb_walk("genunix`vfs", smbfs_vfs_cb, cbd) 1534bff34e3Sthurlow == -1) { 1544bff34e3Sthurlow mdb_warn("can't walk smbfs vfs"); 1554bff34e3Sthurlow return (DCMD_ERR); 1564bff34e3Sthurlow } 1574bff34e3Sthurlow return (DCMD_OK); 1584bff34e3Sthurlow } 1594bff34e3Sthurlow 1604bff34e3Sthurlow vfs = mdb_alloc(sizeof (*vfs), UM_SLEEP | UM_GC); 1614bff34e3Sthurlow SMBFS_OBJ_FETCH(addr, vfs_t, vfs, DCMD_ERR); 1624bff34e3Sthurlow smbfs_vfs_cb(addr, vfs, cbd); 1634bff34e3Sthurlow return (DCMD_OK); 1644bff34e3Sthurlow } 1654bff34e3Sthurlow 1664bff34e3Sthurlow void 1674bff34e3Sthurlow smbfs_vfs_help(void) 1684bff34e3Sthurlow { 1694bff34e3Sthurlow mdb_printf( 1704bff34e3Sthurlow "Display addresses of the mounted smbfs structures\n" 1714bff34e3Sthurlow "and the pathname of the mountpoint\n" 1724bff34e3Sthurlow "\nOptions:\n" 1734bff34e3Sthurlow " -v display details of the smbmntinfo\n"); 1744bff34e3Sthurlow } 1754bff34e3Sthurlow 1764bff34e3Sthurlow /* 1774bff34e3Sthurlow * Dcmd (and callback function) to print a summary of 17802d09e03SGordon Ross * all smbnodes in the node "hash" (cache) AVL tree. 1794bff34e3Sthurlow */ 1804bff34e3Sthurlow 18102d09e03SGordon Ross typedef struct smbfs_node_cbdata { 1824bff34e3Sthurlow int flags; 1834bff34e3Sthurlow int printed_header; 18402d09e03SGordon Ross vnode_t vn; 18502d09e03SGordon Ross } smbfs_node_cbdata_t; 1864bff34e3Sthurlow 1874bff34e3Sthurlow int 18802d09e03SGordon Ross smbfs_node_cb(uintptr_t addr, const void *data, void *arg) 1894bff34e3Sthurlow { 1904bff34e3Sthurlow const smbnode_t *np = data; 19102d09e03SGordon Ross smbfs_node_cbdata_t *cbd = arg; 1924bff34e3Sthurlow 1934bff34e3Sthurlow if (cbd->printed_header == 0) { 1944bff34e3Sthurlow cbd->printed_header = 1; 19502d09e03SGordon Ross mdb_printf("// vnode smbnode rpath\n"); 1964bff34e3Sthurlow } 1974bff34e3Sthurlow 1984bff34e3Sthurlow mdb_printf(" %-p", (uintptr_t)np->r_vnode); 19902d09e03SGordon Ross mdb_printf(" %-p", addr); /* smbnode */ 2004bff34e3Sthurlow print_str((uintptr_t)np->n_rpath); 2014bff34e3Sthurlow mdb_printf("\n"); 2024bff34e3Sthurlow 2034bff34e3Sthurlow if (cbd->flags & OPT_VERBOSE) { 2044bff34e3Sthurlow mdb_inc_indent(2); 2054bff34e3Sthurlow /* Don't fail the walk if this fails. */ 2064bff34e3Sthurlow if (mdb_vread(&cbd->vn, sizeof (cbd->vn), 2074bff34e3Sthurlow (uintptr_t)np->r_vnode) == -1) { 2084bff34e3Sthurlow mdb_warn("error reading vnode_t at %p", 2094bff34e3Sthurlow (uintptr_t)np->r_vnode); 2104bff34e3Sthurlow } else { 2114bff34e3Sthurlow /* Interesting parts of vnode_t */ 21202d09e03SGordon Ross mdb_printf("v_type=%d v_count=%d", 21302d09e03SGordon Ross cbd->vn.v_type, cbd->vn.v_count); 2144bff34e3Sthurlow mdb_printf("\n"); 2154bff34e3Sthurlow } 2164bff34e3Sthurlow mdb_dec_indent(2); 2174bff34e3Sthurlow } 2184bff34e3Sthurlow 2194bff34e3Sthurlow return (WALK_NEXT); 2204bff34e3Sthurlow } 2214bff34e3Sthurlow 2224bff34e3Sthurlow int 22302d09e03SGordon Ross smbfs_node_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2244bff34e3Sthurlow { 22502d09e03SGordon Ross smbfs_node_cbdata_t *cbd; 2264bff34e3Sthurlow 2274bff34e3Sthurlow cbd = mdb_zalloc(sizeof (*cbd), UM_SLEEP | UM_GC); 2284bff34e3Sthurlow 2294bff34e3Sthurlow if (mdb_getopts(argc, argv, 2304bff34e3Sthurlow 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd->flags, 23102d09e03SGordon Ross NULL) != argc) { 2324bff34e3Sthurlow return (DCMD_USAGE); 2334bff34e3Sthurlow } 2344bff34e3Sthurlow 2354bff34e3Sthurlow if (!(flags & DCMD_ADDRSPEC)) { 23602d09e03SGordon Ross mdb_warn("expect an smbmntinfo_t addr"); 23702d09e03SGordon Ross return (DCMD_USAGE); 23802d09e03SGordon Ross } 23902d09e03SGordon Ross addr += OFFSETOF(smbmntinfo_t, smi_hash_avl); 24002d09e03SGordon Ross 24102d09e03SGordon Ross if (mdb_pwalk("genunix`avl", smbfs_node_cb, cbd, addr) == -1) { 24202d09e03SGordon Ross mdb_warn("cannot walk smbfs nodes"); 2434bff34e3Sthurlow return (DCMD_ERR); 2444bff34e3Sthurlow } 2454bff34e3Sthurlow 2464bff34e3Sthurlow return (DCMD_OK); 2474bff34e3Sthurlow } 2484bff34e3Sthurlow 2494bff34e3Sthurlow void 25002d09e03SGordon Ross smbfs_node_help(void) 2514bff34e3Sthurlow { 2524bff34e3Sthurlow mdb_printf("Options:\n" 2534bff34e3Sthurlow " -v be verbose when displaying smbnodes\n"); 2544bff34e3Sthurlow } 2554bff34e3Sthurlow 2564bff34e3Sthurlow static const mdb_dcmd_t dcmds[] = { 25702d09e03SGordon Ross { 25802d09e03SGordon Ross "smbfs_vfs", "?[-v]", 2594bff34e3Sthurlow "show smbfs-mounted vfs structs", 26002d09e03SGordon Ross smbfs_vfs_dcmd, smbfs_vfs_help 26102d09e03SGordon Ross }, 26202d09e03SGordon Ross { 26302d09e03SGordon Ross "smbfs_node", "?[-v]", 26402d09e03SGordon Ross "given an smbmntinfo_t, list smbnodes", 26502d09e03SGordon Ross smbfs_node_dcmd, smbfs_node_help 26602d09e03SGordon Ross }, 2674bff34e3Sthurlow {NULL} 2684bff34e3Sthurlow }; 2694bff34e3Sthurlow 2704bff34e3Sthurlow static const mdb_walker_t walkers[] = { 2714bff34e3Sthurlow {NULL} 2724bff34e3Sthurlow }; 2734bff34e3Sthurlow 2744bff34e3Sthurlow static const mdb_modinfo_t modinfo = { 2754bff34e3Sthurlow MDB_API_VERSION, 2764bff34e3Sthurlow dcmds, 2774bff34e3Sthurlow walkers 2784bff34e3Sthurlow }; 2794bff34e3Sthurlow 2804bff34e3Sthurlow const mdb_modinfo_t * 2814bff34e3Sthurlow _mdb_init(void) 2824bff34e3Sthurlow { 2834bff34e3Sthurlow return (&modinfo); 2844bff34e3Sthurlow } 285