Mercurial > illumos > illumos-gate
changeset 13937:6b4f289e7094
3465 ::walk ... | ::<dcmd> misinterprets input as symbol names
3466 ::tsd should handle missing/NULL values better
3467 mdb_ctf_vread() could be more useful
3468 mdb enhancements for zfs development
3470 ::whatis does not print callers from KMF_LITE
3473 mdb_get_module() returns wrong module
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Eric Schrock <eric.schrock@delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Dan McDonald <danmcd@nexenta.com>
author | Matthew Ahrens <mahrens@delphix.com> |
---|---|
date | Wed, 30 Jan 2013 15:02:58 -0800 |
parents | 60077db1e2cc |
children | c99b1993453c |
files | usr/src/cmd/mdb/common/mdb/mdb.c usr/src/cmd/mdb/common/mdb/mdb_cmds.c usr/src/cmd/mdb/common/mdb/mdb_ctf.c usr/src/cmd/mdb/common/mdb/mdb_ctf.h usr/src/cmd/mdb/common/mdb/mdb_frame.h usr/src/cmd/mdb/common/mdb/mdb_modapi.c usr/src/cmd/mdb/common/mdb/mdb_print.c usr/src/cmd/mdb/common/modules/conf/mapfile-extern usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c usr/src/cmd/mdb/common/modules/genunix/kmem.c usr/src/cmd/mdb/common/modules/genunix/tsd.c usr/src/cmd/mdb/common/modules/libc/libc.c usr/src/cmd/mdb/common/modules/zfs/zfs.c usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c usr/src/uts/common/fs/zfs/sys/refcount.h |
diffstat | 17 files changed, 802 insertions(+), 328 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/mdb/mdb.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/mdb/mdb.c Wed Jan 30 15:02:58 2013 -0800 @@ -1391,7 +1391,8 @@ return (NULL); if (mdb.m_frame->f_wcbs && mdb.m_frame->f_wcbs->w_walker && - mdb.m_frame->f_wcbs->w_walker->iwlk_modp) + mdb.m_frame->f_wcbs->w_walker->iwlk_modp && + !mdb.m_frame->f_cbactive) return (mdb.m_frame->f_wcbs->w_walker->iwlk_modp); if (mdb.m_frame->f_cp && mdb.m_frame->f_cp->c_dcmd)
--- a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c Wed Jan 30 15:02:58 2013 -0800 @@ -2080,7 +2080,7 @@ static int walk_step(uintptr_t addr, const void *data, void *private) { - mdb_printf("%lr\n", addr); + mdb_printf("%#lr\n", addr); return (WALK_NEXT); }
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c Wed Jan 30 15:02:58 2013 -0800 @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2013 by Delphix. All rights reserved. + */ #include <mdb/mdb_ctf.h> #include <mdb/mdb_ctf_impl.h> @@ -740,12 +743,44 @@ return (0); } +/* + * Returns offset in _bits_ in *retp. + */ int mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp) { return (mdb_ctf_member_info(id, member, retp, NULL)); } +/* + * Returns offset in _bytes_, or -1 on failure. + */ +int +mdb_ctf_offsetof_by_name(const char *type, const char *member) +{ + mdb_ctf_id_t id; + ulong_t off; + + if (mdb_ctf_lookup_by_name(type, &id) == -1) { + mdb_warn("couldn't find type %s", type); + return (-1); + } + + if (mdb_ctf_offsetof(id, member, &off) == -1) { + mdb_warn("couldn't find member %s of type %s", member, type); + return (-1); + } + if (off % 8 != 0) { + mdb_warn("member %s of type %s is an unsupported bitfield\n", + member, type); + return (-1); + } + off /= 8; + + return (off); +} + + /*ARGSUSED*/ static int num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) @@ -927,6 +962,19 @@ return (mbc.mbc_total); } +static void +mdb_ctf_warn(uint_t flags, const char *format, ...) +{ + va_list alist; + + if (flags & MDB_CTF_VREAD_QUIET) + return; + + va_start(alist, format); + vwarn(format, alist); + va_end(alist); +} + /* * Check if two types are structurally the same rather than logically * the same. That is to say that two types are equal if they have the @@ -1016,11 +1064,13 @@ typedef struct member { char *m_modbuf; char *m_tgtbuf; + const char *m_tgtname; mdb_ctf_id_t m_tgtid; uint_t m_flags; } member_t; -static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *, uint_t); +static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *, + const char *, uint_t); static int member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data) @@ -1030,29 +1080,66 @@ mdb_ctf_id_t tgtmid; char *tgtbuf = mp->m_tgtbuf; ulong_t tgtoff; + char tgtname[128]; + + (void) mdb_snprintf(tgtname, sizeof (tgtname), + "member %s of type %s", name, mp->m_tgtname); if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) { - if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT) - return (0); - else - return (set_errno(EMDB_CTFNOMEMB)); + mdb_ctf_warn(mp->m_flags, + "could not find %s\n", tgtname); + return (set_errno(EMDB_CTFNOMEMB)); } return (vread_helper(modmid, modbuf + modoff / NBBY, - tgtmid, tgtbuf + tgtoff / NBBY, mp->m_flags)); + tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags)); } +typedef struct enum_value { + int *ev_modbuf; + const char *ev_name; +} enum_value_t; + +static int +enum_cb(const char *name, int value, void *data) +{ + enum_value_t *ev = data; + + if (strcmp(name, ev->ev_name) == 0) { + *ev->ev_modbuf = value; + return (1); + } + return (0); +} static int vread_helper(mdb_ctf_id_t modid, char *modbuf, - mdb_ctf_id_t tgtid, char *tgtbuf, uint_t flags) + mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags) { size_t modsz, tgtsz; int modkind, tgtkind; member_t mbr; + enum_value_t ev; int ret; mdb_ctf_arinfo_t tar, mar; int i; + char typename[128]; + char mdbtypename[128]; + ctf_encoding_t tgt_encoding, mod_encoding; + boolean_t signed_int = B_FALSE; + + if (mdb_ctf_type_name(tgtid, typename, sizeof (typename)) == NULL) { + (void) mdb_snprintf(typename, sizeof (typename), + "#%ul", mdb_ctf_type_id(tgtid)); + } + if (mdb_ctf_type_name(modid, + mdbtypename, sizeof (mdbtypename)) == NULL) { + (void) mdb_snprintf(mdbtypename, sizeof (mdbtypename), + "#%ul", mdb_ctf_type_id(modid)); + } + + if (tgtname == NULL) + tgtname = ""; /* * Resolve the types to their canonical form. @@ -1060,38 +1147,113 @@ (void) mdb_ctf_type_resolve(modid, &modid); (void) mdb_ctf_type_resolve(tgtid, &tgtid); - if ((modkind = mdb_ctf_type_kind(modid)) == -1) + if ((modkind = mdb_ctf_type_kind(modid)) == -1) { + mdb_ctf_warn(flags, + "couldn't determine type kind of mdb module type %s\n", + mdbtypename); return (-1); /* errno is set for us */ - if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) + } + if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) { + mdb_ctf_warn(flags, + "couldn't determine type kind of %s\n", typename); return (-1); /* errno is set for us */ + } - if (tgtkind != modkind) + if (tgtkind != modkind) { + mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n", + typename, tgtname); return (set_errno(EMDB_INCOMPAT)); + } + + if ((modsz = mdb_ctf_type_size(modid)) == -1UL) { + mdb_ctf_warn(flags, "couldn't determine type size of " + "mdb module type %s\n", mdbtypename); + return (-1); /* errno is set for us */ + } + if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) { + mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n", + typename, tgtname); + return (-1); /* errno is set for us */ + } switch (modkind) { case CTF_K_INTEGER: case CTF_K_FLOAT: - case CTF_K_POINTER: - if ((modsz = mdb_ctf_type_size(modid)) == -1UL) + /* + * Must determine if the target and module types have the same + * encoding before we can copy them. + */ + if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) { + mdb_ctf_warn(flags, + "couldn't determine encoding of type %s (%s)\n", + typename, tgtname); return (-1); /* errno is set for us */ + } + if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) { + mdb_ctf_warn(flags, "couldn't determine encoding of " + "mdb module type %s\n", mdbtypename); + return (-1); /* errno is set for us */ + } - if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) - return (-1); /* errno is set for us */ - + if (modkind == CTF_K_INTEGER) { + if ((tgt_encoding.cte_format & CTF_INT_SIGNED) != + (mod_encoding.cte_format & CTF_INT_SIGNED)) { + mdb_ctf_warn(flags, + "signedness mismatch between type " + "%s (%s) and mdb module type %s\n", + typename, tgtname, mdbtypename); + return (set_errno(EMDB_INCOMPAT)); + } + signed_int = + ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0); + } else if (tgt_encoding.cte_format != mod_encoding.cte_format) { + mdb_ctf_warn(flags, + "encoding mismatch (%#x != %#x) between type " + "%s (%s) and mdb module type %s\n", + tgt_encoding.cte_format, mod_encoding.cte_format, + typename, tgtname, mdbtypename); + return (set_errno(EMDB_INCOMPAT)); + } + /* FALLTHROUGH */ + case CTF_K_POINTER: /* * If the sizes don't match we need to be tricky to make * sure that the caller gets the correct data. */ if (modsz < tgtsz) { - if (!(flags & MDB_CTF_VREAD_IGNORE_GROW)) - return (set_errno(EMDB_INCOMPAT)); + mdb_ctf_warn(flags, "size of type %s (%s) is too " + "large for mdb module type %s\n", + typename, tgtname, mdbtypename); + return (set_errno(EMDB_INCOMPAT)); + } else if (modsz > tgtsz) { + /* BEGIN CSTYLED */ + /* + * Fill modbuf with 1's for sign extension if target + * buf is a signed integer and its value is negative. + * + * S = sign bit (in most-significant byte) + * + * BIG ENDIAN DATA + * +--------+--------+--------+--------+ + * |S | | | | + * +--------+--------+--------+--------+ + * 0 1 ... sz-1 sz + * + * LITTLE ENDIAN DATA + * +--------+--------+--------+--------+ + * | | | |S | + * +--------+--------+--------+--------+ + * 0 1 ... sz-1 sz + */ + /* END CSTYLED */ #ifdef _BIG_ENDIAN - bcopy(tgtbuf + tgtsz - modsz, modbuf, modsz); + if (signed_int && (tgtbuf[0] & 0x80) != 0) #else - bcopy(tgtbuf, modbuf, modsz); + if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0) #endif - } else if (modsz > tgtsz) { - bzero(modbuf, modsz); + (void) memset(modbuf, 0xFF, modsz); + else + bzero(modbuf, modsz); #ifdef _BIG_ENDIAN bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz); #else @@ -1103,11 +1265,53 @@ return (0); + case CTF_K_ENUM: + if (modsz != tgtsz || modsz != sizeof (int)) { + mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n", + typename, tgtname); + return (set_errno(EMDB_INCOMPAT)); + } + + /* + * Default to the same value as in the target. + */ + bcopy(tgtbuf, modbuf, sizeof (int)); + + /* LINTED */ + i = *(int *)tgtbuf; + + /* LINTED */ + ev.ev_modbuf = (int *)modbuf; + ev.ev_name = mdb_ctf_enum_name(tgtid, i); + if (ev.ev_name == NULL) { + mdb_ctf_warn(flags, + "unexpected value %u of enum type %s (%s)\n", + i, typename, tgtname); + return (set_errno(EMDB_INCOMPAT)); + } + + ret = mdb_ctf_enum_iter(modid, enum_cb, &ev); + if (ret == 0) { + /* value not found */ + mdb_ctf_warn(flags, + "unexpected value %s (%u) of enum type %s (%s)\n", + ev.ev_name, i, typename, tgtname); + return (set_errno(EMDB_INCOMPAT)); + } else if (ret == 1) { + /* value found */ + return (0); + } else if (ret == -1) { + mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n", + typename, tgtname); + } + return (ret); + case CTF_K_STRUCT: mbr.m_modbuf = modbuf; mbr.m_tgtbuf = tgtbuf; mbr.m_tgtid = tgtid; mbr.m_flags = flags; + mbr.m_tgtname = typename; return (mdb_ctf_member_iter(modid, member_cb, &mbr)); @@ -1116,21 +1320,18 @@ /* * Unions are a little tricky. The only time it's truly * safe to read in a union is if no part of the union or - * any of its component types have changed. We allow the - * consumer to ignore unions. The correct use of this - * feature is to read the containing structure, figure - * out which component of the union is valid, compute + * any of its component types have changed. The correct + * use of this feature is to read the containing structure, + * figure out which component of the union is valid, compute * the location of that in the target and then read in * that part of the structure. */ - if (flags & MDB_CTF_VREAD_IGNORE_UNIONS) - return (0); - if (!type_equals(modid, tgtid)) + if (!type_equals(modid, tgtid)) { + mdb_ctf_warn(flags, "inexact match for union %s (%s)\n", + typename, tgtname); return (set_errno(EMDB_INCOMPAT)); - - modsz = mdb_ctf_type_size(modid); - tgtsz = mdb_ctf_type_size(tgtid); + } ASSERT(modsz == tgtsz); @@ -1139,23 +1340,42 @@ return (0); case CTF_K_ARRAY: - if (mdb_ctf_array_info(tgtid, &tar) != 0) + if (mdb_ctf_array_info(tgtid, &tar) != 0) { + mdb_ctf_warn(flags, + "couldn't get array info for %s (%s)\n", + typename, tgtname); return (-1); /* errno is set for us */ - if (mdb_ctf_array_info(modid, &mar) != 0) + } + if (mdb_ctf_array_info(modid, &mar) != 0) { + mdb_ctf_warn(flags, + "couldn't get array info for mdb module type %s\n", + mdbtypename); return (-1); /* errno is set for us */ + } - if (tar.mta_nelems != mar.mta_nelems) + if (tar.mta_nelems != mar.mta_nelems) { + mdb_ctf_warn(flags, + "unexpected array size (%u) for type %s (%s)\n", + tar.mta_nelems, typename, tgtname); return (set_errno(EMDB_INCOMPAT)); + } - if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) + if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) { + mdb_ctf_warn(flags, "couldn't determine type size of " + "mdb module type %s\n", mdbtypename); return (-1); /* errno is set for us */ - - if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) + } + if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) { + mdb_ctf_warn(flags, + "couldn't determine size of %s (%s)\n", + typename, tgtname); return (-1); /* errno is set for us */ + } for (i = 0; i < tar.mta_nelems; i++) { ret = vread_helper(mar.mta_contents, modbuf + i * modsz, - tar.mta_contents, tgtbuf + i * tgtsz, flags); + tar.mta_contents, tgtbuf + i * tgtsz, + tgtname, flags); if (ret != 0) return (ret); @@ -1164,12 +1384,67 @@ return (0); } + mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n", + modkind, typename, tgtname); return (set_errno(EMDB_INCOMPAT)); } - +/* + * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's + * virtual address space. However, mdb_ctf_vread() can be used to safely + * read a complex type (e.g. a struct) from the target, even if MDB was compiled + * against a different definition of that type (e.g. when debugging a crash + * dump from an older release). + * + * Callers can achieve this by defining their own type which corresponds to the + * type in the target, but contains only the members that the caller requires. + * Using the CTF type information embedded in the target, mdb_ctf_vread will + * find the required members in the target and fill in the caller's structure. + * The members are located by name, and their types are verified to be + * compatible. + * + * By convention, the caller will declare a type with the name "mdb_<type>", + * where <type> is the name of the type in the target (e.g. mdb_zio_t). This + * type will contain the members that the caller is interested in. For example: + * + * typedef struct mdb_zio { + * enum zio_type io_type; + * void *io_waiter; + * struct { + * struct { + * void *list_next; + * } list_head; + * } io_parent_list; + * int io_error; + * } mdb_zio_t; + * + * mdb_zio_t zio; + * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0); + * + * If a given MDB module has different dcmds or walkers that need to read + * different members from the same struct, then different "mdb_" types + * should be declared for each caller. By convention, these types should + * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t + * for ::findstack. If the MDB module is compiled from several source files, + * one must be especially careful to not define different types with the + * same name in different source files, because the compiler can not detect + * this error. + * + * Enums will also be translated by name, so the mdb module will receive + * the enum value it expects even if the target has renumbered the enum. + * Warning: it will therefore only work with enums are only used to store + * legitimate enum values (not several values or-ed together). + * + * By default, if mdb_ctf_vread() can not find any members or enum values, + * it will print a descriptive message (with mdb_warn()) and fail. + * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message. + * Additional flags can be used to ignore specific types of translation + * failure, but should be used with caution, because they will silently leave + * the caller's buffer uninitialized. + */ int -mdb_ctf_vread(void *modbuf, const char *typename, uintptr_t addr, uint_t flags) +mdb_ctf_vread(void *modbuf, const char *target_typename, + const char *mdb_typename, uintptr_t addr, uint_t flags) { ctf_file_t *mfp; ctf_id_t mid; @@ -1179,44 +1454,67 @@ mdb_ctf_id_t modid; mdb_module_t *mod; - if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) + if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) { + mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n", + mod->mod_name); return (set_errno(EMDB_NOCTF)); + } - if ((mid = ctf_lookup_by_name(mfp, typename)) == CTF_ERR) { - mdb_dprintf(MDB_DBG_CTF, "couldn't find module's ctf data\n"); + if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) { + mdb_ctf_warn(flags, "couldn't find ctf data for " + "type %s in mdb module %s\n", + mdb_typename, mod->mod_name); return (set_errno(ctf_to_errno(ctf_errno(mfp)))); } set_ctf_id(&modid, mfp, mid); - if (mdb_ctf_lookup_by_name(typename, &tgtid) != 0) { - mdb_dprintf(MDB_DBG_CTF, "couldn't find target's ctf data\n"); + if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) { + mdb_ctf_warn(flags, + "couldn't find type %s in target's ctf data\n", + target_typename); return (set_errno(EMDB_NOCTF)); } /* * Read the data out of the target's address space. */ - if ((size = mdb_ctf_type_size(tgtid)) == -1UL) + if ((size = mdb_ctf_type_size(tgtid)) == -1UL) { + mdb_ctf_warn(flags, "couldn't determine size of type %s\n", + target_typename); return (-1); /* errno is set for us */ + } tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC); - if (mdb_vread(tgtbuf, size, addr) < 0) + if (mdb_vread(tgtbuf, size, addr) < 0) { + mdb_ctf_warn(flags, "couldn't read %s from %p\n", + target_typename, addr); return (-1); /* errno is set for us */ + } - return (vread_helper(modid, modbuf, tgtid, tgtbuf, flags)); + return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags)); } +/* + * Note: mdb_ctf_readsym() doesn't take separate parameters for the name + * of the target's type vs the mdb module's type. Use with complicated + * types (e.g. structs) may result in unnecessary failure if a member of + * the struct has been changed in the target, but is not actually needed + * by the mdb module. Use mdb_lookup_by_name() + mdb_ctf_vread() to + * avoid this problem. + */ int mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags) { GElf_Sym sym; - if (mdb_lookup_by_name(name, &sym) != 0) + if (mdb_lookup_by_name(name, &sym) != 0) { + mdb_ctf_warn(flags, "couldn't find symbol %s\n", name); return (-1); /* errno is set for us */ + } - return (mdb_ctf_vread(buf, typename, sym.st_value, flags)); + return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags)); } ctf_file_t *
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.h Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.h Wed Jan 30 15:02:58 2013 -0800 @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2013 by Delphix. All rights reserved. + */ #ifndef _MDB_CTF_H #define _MDB_CTF_H @@ -108,17 +111,15 @@ ulong_t *, mdb_ctf_id_t *); extern int mdb_ctf_offsetof(mdb_ctf_id_t, const char *, ulong_t *); extern int mdb_ctf_num_members(mdb_ctf_id_t); +extern int mdb_ctf_offsetof_by_name(const char *, const char *); extern ssize_t mdb_ctf_offset_to_name(mdb_ctf_id_t, ulong_t, char *, size_t, int, mdb_ctf_id_t *, ulong_t *); -#define MDB_CTF_VREAD_IGNORE_GROW 0x01 -#define MDB_CTF_VREAD_IGNORE_ABSENT 0x02 -#define MDB_CTF_VREAD_IGNORE_UNIONS 0x04 +#define MDB_CTF_VREAD_QUIET 0x100 -#define MDB_CTF_VREAD_IGNORE_ALL 0x07 - -extern int mdb_ctf_vread(void *, const char *, uintptr_t, uint_t); +extern int mdb_ctf_vread(void *, const char *, const char *, + uintptr_t, uint_t); extern int mdb_ctf_readsym(void *, const char *, const char *, uint_t); #ifdef _MDB
--- a/usr/src/cmd/mdb/common/mdb/mdb_frame.h Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/mdb/mdb_frame.h Wed Jan 30 15:02:58 2013 -0800 @@ -26,8 +26,6 @@ #ifndef _MDB_FRAME_H #define _MDB_FRAME_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <mdb/mdb_module.h> #include <mdb/mdb_addrvec.h> #include <mdb/mdb_list.h> @@ -67,6 +65,7 @@ struct mdb_lex_state *f_lstate; /* Current lex state */ uintmax_t f_dot; /* Value of '.' */ mdb_bool_t pipe; /* frame has pipe context */ + uint_t f_cbactive; /* true iff a callback is active */ } mdb_frame_t; #ifdef _MDB
--- a/usr/src/cmd/mdb/common/mdb/mdb_modapi.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/mdb/mdb_modapi.c Wed Jan 30 15:02:58 2013 -0800 @@ -510,16 +510,44 @@ return (rval); } +typedef struct pwalk_step { + mdb_walk_cb_t ps_cb; + void *ps_private; +} pwalk_step_t; + +static int +pwalk_step(uintptr_t addr, const void *data, void *private) +{ + pwalk_step_t *psp = private; + int ret; + + mdb.m_frame->f_cbactive = B_TRUE; + ret = psp->ps_cb(addr, data, psp->ps_private); + mdb.m_frame->f_cbactive = B_FALSE; + + return (ret); +} + int -mdb_pwalk(const char *name, mdb_walk_cb_t func, void *data, uintptr_t addr) +mdb_pwalk(const char *name, mdb_walk_cb_t func, void *private, uintptr_t addr) { mdb_iwalker_t *iwp = mdb_walker_lookup(name); + pwalk_step_t p; if (func == NULL) return (set_errno(EINVAL)); - if (iwp != NULL) - return (walk_common(mdb_wcb_create(iwp, func, data, addr))); + p.ps_cb = func; + p.ps_private = private; + + if (iwp != NULL) { + int ret; + int cbactive = mdb.m_frame->f_cbactive; + mdb.m_frame->f_cbactive = B_FALSE; + ret = walk_common(mdb_wcb_create(iwp, pwalk_step, &p, addr)); + mdb.m_frame->f_cbactive = cbactive; + return (ret); + } return (-1); /* errno is set for us */ }
--- a/usr/src/cmd/mdb/common/mdb/mdb_print.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/mdb/mdb_print.c Wed Jan 30 15:02:58 2013 -0800 @@ -696,8 +696,7 @@ int cmd_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - mdb_ctf_id_t id; - ulong_t offset; + int offset; uintptr_t a, tmp; int ret; @@ -730,34 +729,21 @@ if (ret != 0) return (ret); - if (mdb_ctf_lookup_by_name(buf, &id) != 0) { - mdb_warn("failed to look up type %s", buf); + argv++; + argc--; + + member = argv->a_un.a_str; + offset = mdb_ctf_offsetof_by_name(buf, member); + if (offset == -1) return (DCMD_ABORT); - } argv++; argc--; - if (argc < 1 || argv->a_type != MDB_TYPE_STRING) - return (DCMD_USAGE); - - member = argv->a_un.a_str; - - argv++; - argc--; - - if (mdb_ctf_offsetof(id, member, &offset) != 0) { - mdb_warn("failed to find member %s of type %s", - member, buf); - return (DCMD_ABORT); - } - - if (offset % (sizeof (uintptr_t) * NBBY) != 0) { + if (offset % (sizeof (uintptr_t)) != 0) { mdb_warn("%s is not a word-aligned member\n", member); return (DCMD_ABORT); } - - offset /= NBBY; } /*
--- a/usr/src/cmd/mdb/common/modules/conf/mapfile-extern Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/modules/conf/mapfile-extern Wed Jan 30 15:02:58 2013 -0800 @@ -1,5 +1,6 @@ # # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012 by Delphix. All rights reserved. # # CDDL HEADER START # @@ -60,7 +61,10 @@ mdb_ctf_lookup_by_addr { FLAGS = EXTERN }; mdb_ctf_lookup_by_name { FLAGS = EXTERN }; mdb_ctf_member_iter { FLAGS = EXTERN }; + mdb_ctf_module_lookup { FLAGS = EXTERN }; mdb_ctf_offsetof { FLAGS = EXTERN }; + mdb_ctf_offsetof_by_name { FLAGS = EXTERN }; + mdb_ctf_readsym { FLAGS = EXTERN }; mdb_ctf_type_cmp { FLAGS = EXTERN }; mdb_ctf_type_invalidate { FLAGS = EXTERN }; mdb_ctf_type_kind { FLAGS = EXTERN };
--- a/usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c Wed Jan 30 15:02:58 2013 -0800 @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <mdb/mdb_modapi.h> @@ -126,11 +127,21 @@ return (levels); } +typedef struct mdb_findstack_kthread { + struct _sobj_ops *t_sobj_ops; + uint_t t_state; + ushort_t t_flag; + ushort_t t_schedflag; + caddr_t t_stk; + caddr_t t_stkbase; + label_t t_pcb; +} mdb_findstack_kthread_t; + /*ARGSUSED*/ int stacks_findstack(uintptr_t addr, findstack_info_t *fsip, uint_t print_warnings) { - kthread_t thr; + mdb_findstack_kthread_t thr; size_t stksz; uintptr_t ubase, utop; uintptr_t kbase, ktop; @@ -142,11 +153,8 @@ fsip->fsi_depth = 0; fsip->fsi_overflow = 0; - bzero(&thr, sizeof (thr)); - if (mdb_ctf_vread(&thr, "kthread_t", addr, - MDB_CTF_VREAD_IGNORE_ALL) == -1) { - if (print_warnings) - mdb_warn("couldn't read thread at %p\n", addr); + if (mdb_ctf_vread(&thr, "kthread_t", "mdb_findstack_kthread_t", + addr, print_warnings ? 0 : MDB_CTF_VREAD_QUIET) == -1) { fsip->fsi_failed = FSI_FAIL_BADTHREAD; return (DCMD_ERR); }
--- a/usr/src/cmd/mdb/common/modules/genunix/kmem.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/modules/genunix/kmem.c Wed Jan 30 15:02:58 2013 -0800 @@ -25,6 +25,7 @@ /* * Copyright 2011 Joyent, Inc. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <mdb/mdb_param.h> @@ -2161,8 +2162,10 @@ /* validate the buffer state and read in the callers */ stat = (intptr_t)bt.bt_bufctl ^ bt.bt_bxstat; - if (stat != KMEM_BUFTAG_ALLOC || stat != KMEM_BUFTAG_FREE || - mdb_vread(callers, count * sizeof (pc_t), + if (stat != KMEM_BUFTAG_ALLOC && stat != KMEM_BUFTAG_FREE) + return; + + if (mdb_vread(callers, count * sizeof (pc_t), btaddr + offsetof(kmem_buftag_lite_t, bt_history)) == -1) return;
--- a/usr/src/cmd/mdb/common/modules/genunix/tsd.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/modules/genunix/tsd.c Wed Jan 30 15:02:58 2013 -0800 @@ -23,8 +23,9 @@ * Copyright (c) 2000-2001 by Sun Microsystems, Inc. * All rights reserved. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ #include <sys/thread.h> #include "tsd.h" @@ -84,7 +85,7 @@ struct tsd_thread tsdata, *ts = &tsdata; uintptr_t key = NULL; uintptr_t eladdr; - void *element; + void *element = NULL; if (mdb_getopts(argc, argv, 'k', MDB_OPT_UINTPTR, &key, NULL) != argc) return (DCMD_USAGE); @@ -97,22 +98,16 @@ return (DCMD_ERR); } - if (t->t_tsd == NULL) { - if (flags & DCMD_PIPE) - return (DCMD_OK); - mdb_warn("no tsd on thread\n"); - return (DCMD_ERR); - } + if (t->t_tsd == NULL) + goto out; if (mdb_vread(ts, sizeof (*ts), (uintptr_t)t->t_tsd) == -1) { mdb_warn("failed to read tsd at %p", t->t_tsd); return (DCMD_ERR); } - if (key > ts->ts_nkeys) { - mdb_warn("key out of range\n"); - return (DCMD_ERR); - } + if (key > ts->ts_nkeys) + goto out; eladdr = (uintptr_t)(ts->ts_value + key - 1); if (mdb_vread(&element, sizeof (element), eladdr) == -1) { @@ -120,6 +115,10 @@ return (DCMD_ERR); } +out: + if (element == NULL && (flags & DCMD_PIPE)) + return (DCMD_OK); + mdb_printf("%p\n", element); return (DCMD_OK); }
--- a/usr/src/cmd/mdb/common/modules/libc/libc.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/modules/libc/libc.c Wed Jan 30 15:02:58 2013 -0800 @@ -21,10 +21,12 @@ /* * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/mdb_modapi.h> #include <mdb/mdb_whatis.h> +#include <mdb/mdb_ctf.h> #include <procfs.h> #include <ucontext.h> #include <siginfo.h> @@ -1019,17 +1021,13 @@ return (WALK_NEXT); } -/*ARGSUSED*/ static int -tid2ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +tid2ulwp_impl(uintptr_t tid_addr, uintptr_t *ulwp_addrp) { tid2ulwp_walk_t t2u; - if (argc != 0) - return (DCMD_USAGE); - bzero(&t2u, sizeof (t2u)); - t2u.t2u_tid = (lwpid_t)addr; + t2u.t2u_tid = (lwpid_t)tid_addr; if (mdb_walk("ulwp", (mdb_walk_cb_t)tid2ulwp_walk, &t2u) != 0) { mdb_warn("can't walk 'ulwp'"); @@ -1040,9 +1038,78 @@ mdb_warn("thread ID %d not found", t2u.t2u_tid); return (DCMD_ERR); } + *ulwp_addrp = t2u.t2u_lwp; + return (DCMD_OK); +} - mdb_printf("%p\n", t2u.t2u_lwp); +/*ARGSUSED*/ +static int +tid2ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + uintptr_t ulwp_addr; + int error; + + if (argc != 0) + return (DCMD_USAGE); + + error = tid2ulwp_impl(addr, &ulwp_addr); + if (error == DCMD_OK) + mdb_printf("%p\n", ulwp_addr); + return (error); +} + +typedef struct mdb_libc_ulwp { + void *ul_ftsd[TSD_NFAST]; + tsd_t *ul_stsd; +} mdb_libc_ulwp_t; + +/* + * Map from thread pointer to tsd for given key + */ +static int +d_tsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + mdb_libc_ulwp_t u; + uintptr_t ulwp_addr; + uintptr_t key = NULL; + void *element = NULL; + if (mdb_getopts(argc, argv, 'k', MDB_OPT_UINTPTR, &key, NULL) != argc) + return (DCMD_USAGE); + + if (!(flags & DCMD_ADDRSPEC) || key == NULL) + return (DCMD_USAGE); + + if (tid2ulwp_impl(addr, &ulwp_addr) != DCMD_OK) + return (DCMD_ERR); + + if (mdb_ctf_vread(&u, "ulwp_t", "mdb_libc_ulwp_t", ulwp_addr, 0) == -1) + return (DCMD_ERR); + + if (key < TSD_NFAST) { + element = u.ul_ftsd[key]; + } else if (u.ul_stsd != NULL) { + uint_t nalloc; + /* tsd_t is a union, so we can't use ctf_vread() on it. */ + if (mdb_vread(&nalloc, sizeof (nalloc), + (uintptr_t)&u.ul_stsd->tsd_nalloc) == -1) { + mdb_warn("failed to read tsd_t at %p", u.ul_stsd); + return (DCMD_ERR); + } + if (key < nalloc) { + if (mdb_vread(&element, sizeof (element), + (uintptr_t)&u.ul_stsd->tsd_data[key]) == -1) { + mdb_warn("failed to read tsd_t at %p", + u.ul_stsd); + return (DCMD_ERR); + } + } + } + + if (element == NULL && (flags & DCMD_PIPE)) + return (DCMD_OK); + + mdb_printf("%p\n", element); return (DCMD_OK); } @@ -1056,6 +1123,7 @@ { "ucontext", ":", "print ucontext_t structure", d_ucontext, NULL }, { "ulwp", ":", "print ulwp_t structure", d_ulwp, NULL }, { "uberdata", ":", "print uberdata_t structure", d_uberdata, NULL }, + { "tsd", ":-k key", "print tsd for this thread", d_tsd, NULL }, { NULL } };
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c Wed Jan 30 15:02:58 2013 -0800 @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Delphix. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -50,6 +50,8 @@ #define ZFS_OBJ_NAME "libzpool.so.1" #endif +#define ZFS_STRUCT "struct " ZFS_OBJ_NAME "`" + #ifndef _KERNEL int aok; #endif @@ -94,39 +96,13 @@ return (0); } -#define GETMEMB(addr, type, member, dest) \ - getmember(addr, #type, NULL, #member, sizeof (dest), &(dest)) +#define GETMEMB(addr, structname, member, dest) \ + getmember(addr, ZFS_STRUCT structname, NULL, #member, \ + sizeof (dest), &(dest)) #define GETMEMBID(addr, ctfid, member, dest) \ getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest)) -static int -getrefcount(uintptr_t addr, mdb_ctf_id_t *id, - const char *member, uint64_t *rc) -{ - static int gotid; - static mdb_ctf_id_t rc_id; - ulong_t off; - - if (!gotid) { - if (mdb_ctf_lookup_by_name("struct refcount", &rc_id) == -1) { - mdb_warn("couldn't find struct refcount"); - return (DCMD_ERR); - } - gotid = TRUE; - } - - if (mdb_ctf_offsetof(*id, member, &off) == -1) { - char name[64]; - mdb_ctf_type_name(*id, name, sizeof (name)); - mdb_warn("couldn't find member %s of type %s\n", member, name); - return (DCMD_ERR); - } - off /= 8; - - return (GETMEMBID(addr + off, &rc_id, rc_count, *rc)); -} - static boolean_t strisprint(const char *cp) { @@ -188,9 +164,8 @@ return (WALK_NEXT); } - static int -dataset_name(uintptr_t addr, char *buf) +mdb_dsl_dir_name(uintptr_t addr, char *buf) { static int gotid; static mdb_ctf_id_t dd_id; @@ -198,7 +173,7 @@ char dd_myname[MAXNAMELEN]; if (!gotid) { - if (mdb_ctf_lookup_by_name("struct dsl_dir", + if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dir", &dd_id) == -1) { mdb_warn("couldn't find struct dsl_dir"); return (DCMD_ERR); @@ -211,7 +186,7 @@ } if (dd_parent) { - if (dataset_name(dd_parent, buf)) + if (mdb_dsl_dir_name(dd_parent, buf)) return (DCMD_ERR); strcat(buf, "/"); } @@ -236,12 +211,12 @@ buf[0] = '\0'; if (!gotid) { - if (mdb_ctf_lookup_by_name("struct objset", + if (mdb_ctf_lookup_by_name(ZFS_STRUCT "objset", &os_id) == -1) { mdb_warn("couldn't find struct objset"); return (DCMD_ERR); } - if (mdb_ctf_lookup_by_name("struct dsl_dataset", + if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dataset", &ds_id) == -1) { mdb_warn("couldn't find struct dsl_dataset"); return (DCMD_ERR); @@ -263,7 +238,7 @@ return (DCMD_ERR); } - if (ds_dir && dataset_name(ds_dir, buf)) + if (ds_dir && mdb_dsl_dir_name(ds_dir, buf)) return (DCMD_ERR); if (ds_snapname[0]) { @@ -400,58 +375,53 @@ return (DCMD_OK); } +typedef struct mdb_dmu_buf_impl { + struct { + uint64_t db_object; + } db; + void *db_objset; + uint64_t db_level; + uint64_t db_blkid; + struct { + uint64_t rc_count; + } db_holds; +} mdb_dmu_buf_impl_t; + /* ARGSUSED */ static int dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - mdb_ctf_id_t id; - dmu_buf_t db; - uintptr_t objset; - uint8_t level; - uint64_t blkid; - uint64_t holds; + mdb_dmu_buf_impl_t db; char objectname[32]; char blkidname[32]; char path[MAXNAMELEN]; - if (DCMD_HDRSPEC(flags)) { + if (DCMD_HDRSPEC(flags)) mdb_printf(" addr object lvl blkid holds os\n"); - } - - if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &id) == -1) { - mdb_warn("couldn't find struct dmu_buf_impl_t"); + + if (mdb_ctf_vread(&db, ZFS_STRUCT "dmu_buf_impl", "mdb_dmu_buf_impl_t", + addr, 0) == -1) return (DCMD_ERR); - } - - if (GETMEMBID(addr, &id, db_objset, objset) || - GETMEMBID(addr, &id, db, db) || - GETMEMBID(addr, &id, db_level, level) || - GETMEMBID(addr, &id, db_blkid, blkid)) { - return (WALK_ERR); - } - - if (getrefcount(addr, &id, "db_holds", &holds)) { - return (WALK_ERR); - } - - if (db.db_object == DMU_META_DNODE_OBJECT) + + if (db.db.db_object == DMU_META_DNODE_OBJECT) (void) strcpy(objectname, "mdn"); else (void) mdb_snprintf(objectname, sizeof (objectname), "%llx", - (u_longlong_t)db.db_object); - - if (blkid == DMU_BONUS_BLKID) + (u_longlong_t)db.db.db_object); + + if (db.db_blkid == DMU_BONUS_BLKID) (void) strcpy(blkidname, "bonus"); else (void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx", - (u_longlong_t)blkid); - - if (objset_name(objset, path)) { - return (WALK_ERR); + (u_longlong_t)db.db_blkid); + + if (objset_name((uintptr_t)db.db_objset, path)) { + return (DCMD_ERR); } - mdb_printf("%p %8s %1u %9s %2llu %s\n", - addr, objectname, level, blkidname, holds, path); + mdb_printf("%p %8s %1u %9s %2llu %s\n", addr, + objectname, (int)db.db_level, blkidname, + db.db_holds.rc_count, path); return (DCMD_OK); } @@ -735,7 +705,7 @@ } } - if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &data.id) == -1) { + if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dmu_buf_impl", &data.id) == -1) { mdb_warn("couldn't find struct dmu_buf_impl_t"); return (DCMD_ERR); } @@ -801,7 +771,7 @@ } } - if (mdb_ctf_lookup_by_name("struct arc_buf_hdr", &data.id) == -1) { + if (mdb_ctf_lookup_by_name(ZFS_STRUCT "arc_buf_hdr", &data.id) == -1) { mdb_warn("couldn't find struct arc_buf_hdr"); return (DCMD_ERR); } @@ -821,6 +791,12 @@ return (DCMD_OK); } + +typedef struct dbgmsg_arg { + boolean_t da_verbose; + boolean_t da_address; +} dbgmsg_arg_t; + /* ARGSUSED */ static int dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg) @@ -829,12 +805,13 @@ static boolean_t gotid; static ulong_t off; - int *verbosep = arg; + dbgmsg_arg_t *da = arg; time_t timestamp; char buf[1024]; if (!gotid) { - if (mdb_ctf_lookup_by_name("struct zfs_dbgmsg", &id) == -1) { + if (mdb_ctf_lookup_by_name(ZFS_STRUCT "zfs_dbgmsg", &id) == + -1) { mdb_warn("couldn't find struct zfs_dbgmsg"); return (WALK_ERR); } @@ -856,12 +833,14 @@ return (DCMD_ERR); } - if (*verbosep) + if (da->da_address) + mdb_printf("%p ", addr); + if (da->da_verbose) mdb_printf("%Y ", timestamp); mdb_printf("%s\n", buf); - if (*verbosep) + if (da->da_verbose) (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); return (WALK_NEXT); @@ -872,10 +851,11 @@ dbgmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { GElf_Sym sym; - int verbose = FALSE; + dbgmsg_arg_t da = { 0 }; if (mdb_getopts(argc, argv, - 'v', MDB_OPT_SETBITS, TRUE, &verbose, + 'v', MDB_OPT_SETBITS, B_TRUE, &da.da_verbose, + 'a', MDB_OPT_SETBITS, B_TRUE, &da.da_address, NULL) != argc) return (DCMD_USAGE); @@ -884,7 +864,7 @@ return (DCMD_ERR); } - if (mdb_pwalk("list", dbgmsg_cb, &verbose, sym.st_value) != 0) { + if (mdb_pwalk("list", dbgmsg_cb, &da, sym.st_value) != 0) { mdb_warn("can't walk zfs_dbgmsgs"); return (DCMD_ERR); } @@ -1096,6 +1076,10 @@ return (DCMD_OK); } +typedef struct mdb_spa_config_spa { + nvlist_t *spa_config; +} mdb_spa_config_spa_t; + /* * ::spa_config * @@ -1107,15 +1091,14 @@ static int spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - spa_t spa; + mdb_spa_config_spa_t spa; if (argc != 0 || !(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); - if (mdb_vread(&spa, sizeof (spa), addr) == -1) { - mdb_warn("failed to read spa_t at %p", addr); + if (mdb_ctf_vread(&spa, ZFS_STRUCT "spa", "mdb_spa_config_spa_t", + addr, 0) == -1) return (DCMD_ERR); - } if (spa.spa_config == NULL) { mdb_printf("(none)\n"); @@ -1369,8 +1352,8 @@ ASSERT(mw->mw_nummss == 0); vdevp = mw->mw_vdevs[mw->mw_curvdev]; - if (GETMEMB(vdevp, struct vdev, vdev_ms, mssp) || - GETMEMB(vdevp, struct vdev, vdev_ms_count, mw->mw_nummss)) { + if (GETMEMB(vdevp, "vdev", vdev_ms, mssp) || + GETMEMB(vdevp, "vdev", vdev_ms_count, mw->mw_nummss)) { return (WALK_ERR); } @@ -1417,9 +1400,9 @@ mw = mdb_zalloc(sizeof (metaslab_walk_data_t), UM_SLEEP | UM_GC); - if (GETMEMB(wsp->walk_addr, struct spa, spa_root_vdev, root_vdevp) || - GETMEMB(root_vdevp, struct vdev, vdev_children, mw->mw_numvdevs) || - GETMEMB(root_vdevp, struct vdev, vdev_child, childp)) { + if (GETMEMB(wsp->walk_addr, "spa", spa_root_vdev, root_vdevp) || + GETMEMB(root_vdevp, "vdev", vdev_children, mw->mw_numvdevs) || + GETMEMB(root_vdevp, "vdev", vdev_child, childp)) { return (DCMD_ERR); } @@ -1482,11 +1465,11 @@ space_data_t *sd = arg; mdb_metaslab_t ms; - if (GETMEMB(addr, struct metaslab, ms_allocmap, ms.ms_allocmap) || - GETMEMB(addr, struct metaslab, ms_freemap, ms.ms_freemap) || - GETMEMB(addr, struct metaslab, ms_map, ms.ms_map) || - GETMEMB(addr, struct metaslab, ms_smo, ms.ms_smo) || - GETMEMB(addr, struct metaslab, ms_smo_syncing, ms.ms_smo_syncing)) { + if (GETMEMB(addr, "metaslab", ms_allocmap, ms.ms_allocmap) || + GETMEMB(addr, "metaslab", ms_freemap, ms.ms_freemap) || + GETMEMB(addr, "metaslab", ms_map, ms.ms_map) || + GETMEMB(addr, "metaslab", ms_smo, ms.ms_smo) || + GETMEMB(addr, "metaslab", ms_smo_syncing, ms.ms_smo_syncing)) { return (WALK_ERR); } @@ -1525,33 +1508,33 @@ space_data_t sd; int shift = 20; char *suffix = "M"; - int bits = FALSE; - - if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bits, NULL) != + int bytes = B_FALSE; + + if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bytes, NULL) != argc) return (DCMD_USAGE); if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); - if (bits) { + if (bytes) { shift = 0; suffix = ""; } - if (GETMEMB(addr, struct spa, spa_dsl_pool, spa.spa_dsl_pool) || - GETMEMB(addr, struct spa, spa_root_vdev, spa.spa_root_vdev) || - GETMEMB(spa.spa_root_vdev, struct vdev, vdev_children, children) || - GETMEMB(spa.spa_root_vdev, struct vdev, vdev_child, childaddr) || - GETMEMB(spa.spa_dsl_pool, struct dsl_pool, + if (GETMEMB(addr, "spa", spa_dsl_pool, spa.spa_dsl_pool) || + GETMEMB(addr, "spa", spa_root_vdev, spa.spa_root_vdev) || + GETMEMB(spa.spa_root_vdev, "vdev", vdev_children, children) || + GETMEMB(spa.spa_root_vdev, "vdev", vdev_child, childaddr) || + GETMEMB(spa.spa_dsl_pool, "dsl_pool", dp_root_dir, dp_root_dir) || - GETMEMB(dp_root_dir, struct dsl_dir, dd_phys, dd.dd_phys) || - GETMEMB(dp_root_dir, struct dsl_dir, + GETMEMB(dp_root_dir, "dsl_dir", dd_phys, dd.dd_phys) || + GETMEMB(dp_root_dir, "dsl_dir", dd_space_towrite, dd.dd_space_towrite) || - GETMEMB(dd.dd_phys, struct dsl_dir_phys, + GETMEMB(dd.dd_phys, "dsl_dir_phys", dd_used_bytes, dsp.dd_used_bytes) || - GETMEMB(dd.dd_phys, struct dsl_dir_phys, + GETMEMB(dd.dd_phys, "dsl_dir_phys", dd_compressed_bytes, dsp.dd_compressed_bytes) || - GETMEMB(dd.dd_phys, struct dsl_dir_phys, + GETMEMB(dd.dd_phys, "dsl_dir_phys", dd_uncompressed_bytes, dsp.dd_uncompressed_bytes)) { return (DCMD_ERR); } @@ -1749,13 +1732,25 @@ uint_t zpa_flags; } zio_print_args_t; +typedef struct mdb_zio { + enum zio_type io_type; + enum zio_stage io_stage; + void *io_waiter; + uint64_t io_timestamp; + void *io_spa; + struct { + struct { + void *list_next; + } list_head; + } io_parent_list; + int io_error; +} mdb_zio_t; + static int zio_child_cb(uintptr_t addr, const void *unknown, void *arg); static int -zio_print_cb(uintptr_t addr, const void *data, void *priv) +zio_print_cb(uintptr_t addr, const mdb_zio_t *zio, zio_print_args_t *zpa) { - const zio_t *zio = data; - zio_print_args_t *zpa = priv; mdb_ctf_id_t type_enum, stage_enum; int indent = zpa->zpa_current_depth; const char *type, *stage; @@ -1775,10 +1770,15 @@ else type = "?"; - if ((stage = mdb_ctf_enum_name(stage_enum, zio->io_stage)) != NULL) - stage += sizeof ("ZIO_STAGE_") - 1; - else - stage = "?"; + if (zio->io_error == 0) { + stage = mdb_ctf_enum_name(stage_enum, zio->io_stage); + if (stage != NULL) + stage += sizeof ("ZIO_STAGE_") - 1; + else + stage = "?"; + } else { + stage = "FAILED"; + } if (zpa->zpa_current_depth >= zpa->zpa_min_depth) { if (zpa->zpa_flags & DCMD_PIPE_OUT) { @@ -1797,9 +1797,11 @@ return (WALK_NEXT); if (zpa->zpa_type == ZIO_WALK_PARENT) - laddr = addr + OFFSETOF(zio_t, io_parent_list); + laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", + "io_parent_list"); else - laddr = addr + OFFSETOF(zio_t, io_child_list); + laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", + "io_child_list"); zpa->zpa_current_depth++; if (mdb_pwalk("list", zio_child_cb, zpa, laddr) != 0) { @@ -1816,7 +1818,7 @@ zio_child_cb(uintptr_t addr, const void *unknown, void *arg) { zio_link_t zl; - zio_t zio; + mdb_zio_t zio; uintptr_t ziop; zio_print_args_t *zpa = arg; @@ -1830,10 +1832,8 @@ else ziop = (uintptr_t)zl.zl_child; - if (mdb_vread(&zio, sizeof (zio_t), ziop) == -1) { - mdb_warn("failed to read zio_t at %p", ziop); + if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", ziop, 0) == -1) return (WALK_ERR); - } return (zio_print_cb(ziop, &zio, arg)); } @@ -1842,7 +1842,7 @@ static int zio_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - zio_t zio; + mdb_zio_t zio; zio_print_args_t zpa = { 0 }; if (!(flags & DCMD_ADDRSPEC)) @@ -1864,10 +1864,8 @@ zpa.zpa_max_depth = 1; } - if (mdb_vread(&zio, sizeof (zio_t), addr) == -1) { - mdb_warn("failed to read zio_t at %p", addr); + if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", addr, 0) == -1) return (DCMD_ERR); - } if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) mdb_printf("%<u>%-*s %-5s %-16s %-?s%</u>\n", ZIO_MAXWIDTH, @@ -2063,12 +2061,11 @@ static int zio_walk_step(mdb_walk_state_t *wsp) { - zio_t zio; - - if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) { - mdb_warn("failed to read zio_t at %p", wsp->walk_addr); + mdb_zio_t zio; + + if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", + wsp->walk_addr, 0) == -1) return (WALK_ERR); - } if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa) return (WALK_NEXT); @@ -2084,19 +2081,20 @@ static int zio_walk_root_step(mdb_walk_state_t *wsp) { - zio_t zio; - - if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) { - mdb_warn("failed to read zio_t at %p", wsp->walk_addr); + mdb_zio_t zio; + + if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", + wsp->walk_addr, 0) == -1) return (WALK_ERR); - } if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa) return (WALK_NEXT); /* If the parent list is not empty, ignore */ - if (zio.io_parent_list.list_head.list_next != - &((zio_t *)wsp->walk_addr)->io_parent_list.list_head) + if ((uintptr_t)zio.io_parent_list.list_head.list_next != + wsp->walk_addr + + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", "io_parent_list") + + mdb_ctf_offsetof_by_name("struct list", "list_head")) return (WALK_NEXT); return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); @@ -2179,8 +2177,8 @@ if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); - if (GETMEMB(addr, struct spa, spa_dsl_pool, addr) || - GETMEMB(addr, struct dsl_pool, dp_blkstats, addr) || + if (GETMEMB(addr, "spa", spa_dsl_pool, addr) || + GETMEMB(addr, "dsl_pool", dp_blkstats, addr) || mdb_vread(&stats, sizeof (zfs_all_blkstats_t), addr) == -1) { mdb_warn("failed to read data at %p;", addr); mdb_printf("maybe no stats? run \"zpool scrub\" first."); @@ -2334,10 +2332,16 @@ static int gotid; static mdb_ctf_id_t rc_id; ulong_t off; + boolean_t released = B_FALSE; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); + if (mdb_getopts(argc, argv, + 'r', MDB_OPT_SETBITS, B_TRUE, &released, + NULL) != argc) + return (DCMD_USAGE); + if (!gotid) { /* * The refcount structure is different when compiled debug @@ -2345,7 +2349,7 @@ * refcount definition from the ZFS module, in case it has * been compiled debug but genunix is nondebug. */ - if (mdb_ctf_lookup_by_name("struct " ZFS_OBJ_NAME "`refcount", + if (mdb_ctf_lookup_by_name(ZFS_STRUCT "refcount", &rc_id) == -1) { mdb_warn("couldn't find struct refcount"); return (DCMD_ERR); @@ -2353,10 +2357,15 @@ gotid = TRUE; } - if (GETMEMBID(addr, &rc_id, rc_count, rc_count) || - GETMEMBID(addr, &rc_id, rc_removed_count, rc_removed_count)) + if (GETMEMBID(addr, &rc_id, rc_count, rc_count)) return (DCMD_ERR); + if (GETMEMBID(addr, &rc_id, rc_removed_count, rc_removed_count)) { + mdb_printf("refcount_t at %p has %llu current holds\n", + addr, (longlong_t)rc_count); + return (DCMD_OK); + } + mdb_printf("refcount_t at %p has %llu current holds, " "%llu recently released holds\n", addr, (longlong_t)rc_count, (longlong_t)rc_removed_count); @@ -2368,12 +2377,14 @@ rc_list = addr + off/NBBY; mdb_pwalk("list", reference_cb, (void*)B_FALSE, rc_list); - if (rc_removed_count > 0) - mdb_printf("released holds:\n"); - if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1) - return (DCMD_ERR); - rc_removed = addr + off/NBBY; - mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed); + if (released) { + if (rc_removed_count > 0) + mdb_printf("released holds:\n"); + if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1) + return (DCMD_ERR); + rc_removed = addr + off/NBBY; + mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed); + } return (DCMD_OK); } @@ -2419,7 +2430,7 @@ { uintptr_t idx_table; - if (GETMEMB(addr, struct sa_idx_tab, sa_idx_tab, idx_table)) { + if (GETMEMB(addr, "sa_idx_tab", sa_idx_tab, idx_table)) { mdb_printf("can't find offset table in sa_idx_tab\n"); return (-1); } @@ -2457,22 +2468,22 @@ else return (DCMD_USAGE); - if (GETMEMB(addr, struct sa_handle, sa_bonus_tab, bonus_tab) || - GETMEMB(addr, struct sa_handle, sa_spill_tab, spill_tab) || - GETMEMB(addr, struct sa_handle, sa_os, os) || - GETMEMB(addr, struct sa_handle, sa_bonus, db_bonus) || - GETMEMB(addr, struct sa_handle, sa_spill, db_spill)) { + if (GETMEMB(addr, "sa_handle", sa_bonus_tab, bonus_tab) || + GETMEMB(addr, "sa_handle", sa_spill_tab, spill_tab) || + GETMEMB(addr, "sa_handle", sa_os, os) || + GETMEMB(addr, "sa_handle", sa_bonus, db_bonus) || + GETMEMB(addr, "sa_handle", sa_spill, db_spill)) { mdb_printf("Can't find necessary information in sa_handle " "in sa_handle\n"); return (DCMD_ERR); } - if (GETMEMB(os, struct objset, os_sa, os_sa)) { + if (GETMEMB(os, "objset", os_sa, os_sa)) { mdb_printf("Can't find os_sa in objset\n"); return (DCMD_ERR); } - if (GETMEMB(os_sa, struct sa_os, sa_num_attrs, attr_count)) { + if (GETMEMB(os_sa, "sa_os", sa_num_attrs, attr_count)) { mdb_printf("Can't find sa_num_attrs\n"); return (DCMD_ERR); } @@ -2488,7 +2499,7 @@ return (DCMD_ERR); } - if (GETMEMB(db_bonus, struct dmu_buf, db_data, db_data)) { + if (GETMEMB(db_bonus, "dmu_buf", db_data, db_data)) { mdb_printf("can't find db_data in bonus dbuf\n"); return (DCMD_ERR); } @@ -2503,7 +2514,7 @@ attr_count) == -1) { return (DCMD_ERR); } - if (GETMEMB(db_spill, struct dmu_buf, db_data, db_data)) { + if (GETMEMB(db_spill, "dmu_buf", db_data, db_data)) { mdb_printf("can't find db_data in spill dbuf\n"); return (DCMD_ERR); } @@ -2814,7 +2825,8 @@ return (WALK_ERR); } - wsp->walk_addr += OFFSETOF(zfs_acl_t, z_acl); + wsp->walk_addr += + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zfs_acl", "z_acl"); if (mdb_layered_walk("list", wsp) == -1) { mdb_warn("failed to walk 'list'\n"); @@ -2974,6 +2986,58 @@ return (status); } +typedef struct mdb_zfs_rrwlock { + kthread_t *rr_writer; + boolean_t rr_writer_wanted; +} mdb_zfs_rrwlock_t; + +static uint_t rrw_key; + +/* ARGSUSED */ +static int +rrwlock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + mdb_zfs_rrwlock_t rrw; + + if (rrw_key == 0) { + if (mdb_ctf_readsym(&rrw_key, "uint_t", "rrw_tsd_key", 0) == -1) + return (DCMD_ERR); + } + + if (mdb_ctf_vread(&rrw, "rrwlock_t", "mdb_zfs_rrwlock_t", addr, + 0) == -1) + return (DCMD_ERR); + + if (rrw.rr_writer != NULL) { + mdb_printf("write lock held by thread %p\n", rrw.rr_writer); + return (DCMD_OK); + } + + if (rrw.rr_writer_wanted) { + mdb_printf("writer wanted\n"); + } + + mdb_printf("anonymous references:\n"); + (void) mdb_call_dcmd("refcount", addr + + mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_anon_rcount"), + DCMD_ADDRSPEC, 0, NULL); + + mdb_printf("linked references:\n"); + (void) mdb_call_dcmd("refcount", addr + + mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_linked_rcount"), + DCMD_ADDRSPEC, 0, NULL); + + /* + * XXX This should find references from + * "::walk thread | ::tsd -v <rrw_key>", but there is no support + * for programmatic consumption of dcmds, so this would be + * difficult, potentially requiring reimplementing ::tsd (both + * user and kernel versions) in this MDB module. + */ + + return (DCMD_OK); +} + /* * MDB module linkage information: * @@ -3014,7 +3078,9 @@ "given a spa_t, print block type stats from last scrub", zfs_blkstats }, { "zfs_params", "", "print zfs tunable parameters", zfs_params }, - { "refcount", "", "print refcount_t holders", refcount }, + { "refcount", ":[-r]\n" + "\t-r display recently removed references", + "print refcount_t holders", refcount }, { "zap_leaf", "", "print zap_leaf_phys_t", zap_leaf }, { "zfs_aces", ":[-v]", "print all ACEs from a zfs_acl_t", zfs_acl_dump }, @@ -3024,33 +3090,35 @@ sa_attr_table}, { "sa_attr", ": attr_id", "print SA attribute address when given sa_handle_t", sa_attr_print}, - { "zfs_dbgmsg", ":[-v]", + { "zfs_dbgmsg", ":[-va]", "print zfs debug log", dbgmsg}, + { "rrwlock", ":", + "print rrwlock_t, including readers", rrwlock}, { NULL } }; static const mdb_walker_t walkers[] = { { "zms_freelist", "walk ZFS metaslab freelist", - freelist_walk_init, freelist_walk_step, NULL }, + freelist_walk_init, freelist_walk_step, NULL }, { "txg_list", "given any txg_list_t *, walk all entries in all txgs", - txg_list_walk_init, txg_list_walk_step, NULL }, + txg_list_walk_init, txg_list_walk_step, NULL }, { "txg_list0", "given any txg_list_t *, walk all entries in txg 0", - txg_list0_walk_init, txg_list_walk_step, NULL }, + txg_list0_walk_init, txg_list_walk_step, NULL }, { "txg_list1", "given any txg_list_t *, walk all entries in txg 1", - txg_list1_walk_init, txg_list_walk_step, NULL }, + txg_list1_walk_init, txg_list_walk_step, NULL }, { "txg_list2", "given any txg_list_t *, walk all entries in txg 2", - txg_list2_walk_init, txg_list_walk_step, NULL }, + txg_list2_walk_init, txg_list_walk_step, NULL }, { "txg_list3", "given any txg_list_t *, walk all entries in txg 3", - txg_list3_walk_init, txg_list_walk_step, NULL }, + txg_list3_walk_init, txg_list_walk_step, NULL }, { "zio", "walk all zio structures, optionally for a particular spa_t", - zio_walk_init, zio_walk_step, NULL }, - { "zio_root", "walk all root zio_t structures, optionally for a " - "particular spa_t", - zio_walk_init, zio_walk_root_step, NULL }, + zio_walk_init, zio_walk_step, NULL }, + { "zio_root", + "walk all root zio_t structures, optionally for a particular spa_t", + zio_walk_init, zio_walk_root_step, NULL }, { "spa", "walk all spa_t entries in the namespace", - spa_walk_init, spa_walk_step, NULL }, + spa_walk_init, spa_walk_step, NULL }, { "metaslab", "given a spa_t *, walk all metaslab_t structures", - metaslab_walk_init, metaslab_walk_step, NULL }, + metaslab_walk_init, metaslab_walk_step, NULL }, { "zfs_acl_node", "given a zfs_acl_t, walk all zfs_acl_nodes", zfs_acl_node_walk_init, zfs_acl_node_walk_step, NULL }, { "zfs_acl_node_aces", "given a zfs_acl_node_t, walk all ACEs",
--- a/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c Wed Jan 30 15:02:58 2013 -0800 @@ -22,8 +22,9 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ #include <mdb/mdb_modapi.h> #include <mdb/mdb_ks.h> @@ -51,7 +52,7 @@ * interesting bits from the binary, and stash them in the structure * defined below. */ -typedef struct domain { +typedef struct mdb_xpv_domain { short domain_id; int tot_pages; int max_pages; @@ -59,9 +60,9 @@ ulong_t domain_flags; char is_hvm; struct vcpu *vcpu[MAX_VIRT_CPUS]; - struct evtchn *evtchn[NR_EVTCHN_BUCKETS]; - struct domain *next_in_list; -} domain_t; + struct evtchn *evtchn[NR_EVTCHN_BUCKETS]; + struct domain *next_in_list; +} mdb_xpv_domain_t; static uintptr_t get_dom0_addr() @@ -110,7 +111,7 @@ domain_walk_step(mdb_walk_state_t *wsp) { domain_walk_t *dwp = (domain_walk_t *)wsp->walk_data; - struct domain dom; + mdb_xpv_domain_t dom; int status; if (wsp->walk_addr == NULL) @@ -119,11 +120,9 @@ status = wsp->walk_callback(wsp->walk_addr, (void *)wsp->walk_addr, wsp->walk_cbdata); - if (mdb_ctf_vread(&dom, "struct domain", wsp->walk_addr, - MDB_CTF_VREAD_IGNORE_ABSENT) != 0) { - mdb_warn("can't find next domain"); + if (mdb_ctf_vread(&dom, "struct domain", "mdb_xpv_domain_t", + wsp->walk_addr, 0) != 0) return (WALK_ERR); - } wsp->walk_addr = (uintptr_t)dom.next_in_list; dwp->dw_step = TRUE; @@ -199,7 +198,7 @@ int domain(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - domain_t dom; + mdb_xpv_domain_t dom; uintptr_t off, vcpu_addr, evtchn_addr; if (!mdb_ctf_type_valid(domain_type)) { @@ -220,11 +219,9 @@ "ADDR", "ID", "TPAGES", "MPAGES", "FLAGS", "HVM", "VCPU", "EVTCHN"); - if (mdb_ctf_vread(&dom, "struct domain", addr, - MDB_CTF_VREAD_IGNORE_ABSENT) != 0) { - mdb_warn("can't read domain information"); + if (mdb_ctf_vread(&dom, "struct domain", "mdb_xpv_domain_t", addr, + 0) != 0) return (DCMD_ERR); - } if (mdb_ctf_offsetof(domain_type, "vcpu", &off)) { mdb_warn("can't find per-domain vcpu information"); @@ -258,24 +255,23 @@ static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; +typedef struct mdb_xpv_panic_info { + int pi_version; +} mdb_xpv_panic_info_t; + const mdb_modinfo_t * _mdb_init(void) { - GElf_Sym sym; uintptr_t pip; - struct panic_info pi; + mdb_xpv_panic_info_t pi; - if (mdb_lookup_by_name("xpv_panic_info", &sym) < 0) - return (NULL); - - if (mdb_ctf_vread(&pip, "uintptr_t", sym.st_value, 0) == -1) { + if (mdb_readsym(&pip, sizeof (pip), "xpv_panic_info") == -1) { mdb_warn("failed to read xpv panic_info pointer"); return (NULL); } - if (mdb_ctf_vread(&pi, "struct panic_info", pip, 0) == -1) { - mdb_warn("failed to read xpv panic_info"); + if (mdb_ctf_vread(&pi, "struct panic_info", "mdb_xpv_panic_info_t", + pip, 0) == -1) return (NULL); - } if (pi.pi_version != PANIC_INFO_VERSION) { mdb_warn("unrecognized hypervisor panic format");
--- a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c Wed Jan 30 15:02:58 2013 -0800 @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2013 by Delphix. All rights reserved. + */ #include <mdb/mdb_modapi.h> #include <mdb/mdb_ks.h> @@ -32,7 +35,12 @@ #include "intr_common.h" -static shared_info_t shared_info; +typedef struct mdb_shared_info { + unsigned long evtchn_pending[sizeof (unsigned long) * NBBY]; + unsigned long evtchn_mask[sizeof (unsigned long) * NBBY]; +} mdb_shared_info_t; + +static mdb_shared_info_t shared_info; static int have_shared_info; static uintptr_t evtchn_cpus_addr; static struct av_head avec_tbl[NR_IRQS]; @@ -109,8 +117,8 @@ /* * It's normal for this to fail with a domain dump. */ - if (mdb_ctf_vread(&shared_info, "shared_info_t", - shared_info_addr, 0) != -1) + if (mdb_ctf_vread(&shared_info, "shared_info_t", "mdb_shared_info_t", + shared_info_addr, MDB_CTF_VREAD_QUIET) != -1) have_shared_info = 1; return (1); @@ -255,18 +263,20 @@ return (!!TEST_EVTCHN_BIT(i, &shared_info.evtchn_pending[0])); } +typedef struct mdb_xpv_psm_autovec { + dev_info_t *av_dip; +} mdb_xpv_psm_autovec_t; + static void print_bus(int irq) { char parent[7]; uintptr_t dip_addr; struct dev_info dev_info; - struct autovec avhp; + mdb_xpv_psm_autovec_t avhp; - bzero(&avhp, sizeof (avhp)); - - if (mdb_ctf_vread(&avhp, "struct autovec", - (uintptr_t)avec_tbl[irq].avh_link, 0) == -1) + if (mdb_ctf_vread(&avhp, "struct autovec", "mdb_xpv_psm_autovec_t", + (uintptr_t)avec_tbl[irq].avh_link, MDB_CTF_VREAD_QUIET) == -1) goto fail; dip_addr = (uintptr_t)avhp.av_dip;
--- a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c Wed Jan 30 15:02:58 2013 -0800 @@ -22,8 +22,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2013 by Delphix. All rights reserved. + */ #include <mdb/mdb_modapi.h> #include <mdb/mdb_ks.h> @@ -32,7 +33,12 @@ #include "intr_common.h" -static shared_info_t shared_info; +typedef struct mdb_shared_info { + unsigned long evtchn_pending[sizeof (unsigned long) * NBBY]; + unsigned long evtchn_mask[sizeof (unsigned long) * NBBY]; +} mdb_shared_info_t; + +static mdb_shared_info_t shared_info; static struct av_head avec_tbl[NR_IRQS]; static uint16_t shared_tbl[MAX_ISA_IRQ + 1]; static irq_info_t irq_tbl[NR_IRQS]; @@ -74,11 +80,9 @@ return (0); } - if (mdb_ctf_vread(&shared_info, "shared_info_t", - shared_info_addr, 0) == -1) { - mdb_warn("failed to read shared_info"); + if (mdb_ctf_vread(&shared_info, "shared_info_t", "mdb_shared_info_t", + shared_info_addr, 0) == -1) return (0); - } return (1); }
--- a/usr/src/uts/common/fs/zfs/sys/refcount.h Wed Jan 30 23:35:38 2013 +0100 +++ b/usr/src/uts/common/fs/zfs/sys/refcount.h Wed Jan 30 15:02:58 2013 -0800 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_REFCOUNT_H @@ -52,8 +53,8 @@ kmutex_t rc_mtx; list_t rc_list; list_t rc_removed; - int64_t rc_count; - int64_t rc_removed_count; + uint64_t rc_count; + uint64_t rc_removed_count; } refcount_t; /* Note: refcount_t must be initialized with refcount_create() */