diff options
author | Matthew Ahrens <mahrens@delphix.com> | 2013-04-07 18:40:39 -0800 |
---|---|---|
committer | Christopher Siden <chris.siden@delphix.com> | 2013-04-07 19:40:39 -0700 |
commit | d5ee8a1311accef11ec2057f70da38d1dd687088 (patch) | |
tree | 4b6256dd397b75b1207456339e6d01f702a9960a | |
parent | b1fa6326238973aeaf12c34fcda75985b6c06be1 (diff) | |
download | illumos-joyent-d5ee8a1311accef11ec2057f70da38d1dd687088.tar.gz |
3654 zdb should print number of ganged blocks
3655 ::rrwlock and ::refcount print errors on non-debug kernels
3656 remove unused function zap_cursor_move_to_key()
3657 mdb_ctf_vread() should allow conversion of pointer to uintptr_t
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Approved by: Garrett D'Amore <garrett@damore.org>
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_ctf.c | 18 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/zfs/zfs.c | 148 | ||||
-rw-r--r-- | usr/src/cmd/zdb/zdb.c | 39 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zap.h | 7 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zap_impl.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zap.c | 25 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zap_micro.c | 40 |
7 files changed, 125 insertions, 154 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c index 360e7ad97e..8f43c8cb0f 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c @@ -1159,12 +1159,6 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf, return (-1); /* errno is set for us */ } - 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); @@ -1176,7 +1170,17 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf, return (-1); /* errno is set for us */ } - switch (modkind) { + if (tgtkind == CTF_K_POINTER && modkind == CTF_K_INTEGER && + strcmp(mdbtypename, "uintptr_t") == 0) { + /* allow them to convert a pointer to a uintptr_t */ + ASSERT(modsz == tgtsz); + } else if (tgtkind != modkind) { + mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n", + typename, tgtname); + return (set_errno(EMDB_INCOMPAT)); + } + + switch (tgtkind) { case CTF_K_INTEGER: case CTF_K_FLOAT: /* diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c index 792c9a1855..e2a05550c2 100644 --- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c +++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c @@ -380,7 +380,7 @@ typedef struct mdb_dmu_buf_impl { struct { uint64_t db_object; } db; - void *db_objset; + uintptr_t db_objset; uint64_t db_level; uint64_t db_blkid; struct { @@ -416,7 +416,7 @@ dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) (void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx", (u_longlong_t)db.db_blkid); - if (objset_name((uintptr_t)db.db_objset, path)) { + if (objset_name(db.db_objset, path)) { return (DCMD_ERR); } @@ -1078,7 +1078,7 @@ spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } typedef struct mdb_spa_config_spa { - nvlist_t *spa_config; + uintptr_t spa_config; } mdb_spa_config_spa_t; /* @@ -1101,12 +1101,12 @@ spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) addr, 0) == -1) return (DCMD_ERR); - if (spa.spa_config == NULL) { + if (spa.spa_config == 0) { mdb_printf("(none)\n"); return (DCMD_OK); } - return (mdb_call_dcmd("nvlist", (uintptr_t)spa.spa_config, flags, + return (mdb_call_dcmd("nvlist", spa.spa_config, flags, 0, NULL)); } @@ -1736,11 +1736,11 @@ typedef struct zio_print_args { typedef struct mdb_zio { enum zio_type io_type; enum zio_stage io_stage; - void *io_waiter; - void *io_spa; + uintptr_t io_waiter; + uintptr_t io_spa; struct { struct { - void *list_next; + uintptr_t list_next; } list_head; } io_parent_list; int io_error; @@ -1797,8 +1797,8 @@ zio_print_cb(uintptr_t addr, zio_print_args_t *zpa) } else { mdb_printf("%*s%-*p %-5s %-16s ", indent, "", ZIO_MAXWIDTH - indent, addr, type, stage); - if (zio.io_waiter) - mdb_printf("%-16p ", zio.io_waiter); + if (zio.io_waiter != 0) + mdb_printf("%-16lx ", zio.io_waiter); else mdb_printf("%-16s ", "-"); #ifdef _KERNEL @@ -2065,7 +2065,7 @@ spa_walk_step(mdb_walk_state_t *wsp) static int zio_walk_init(mdb_walk_state_t *wsp) { - wsp->walk_data = (void *)wsp->walk_addr; + wsp->walk_data = &wsp->walk_addr; if (mdb_layered_walk("zio_cache", wsp) == -1) { mdb_warn("failed to walk 'zio_cache'\n"); @@ -2079,12 +2079,13 @@ static int zio_walk_step(mdb_walk_state_t *wsp) { mdb_zio_t zio; + uintptr_t *spap = wsp->walk_data; 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) + if (*spap != 0 && *spap != zio.io_spa) return (WALK_NEXT); return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); @@ -2099,16 +2100,17 @@ static int zio_walk_root_step(mdb_walk_state_t *wsp) { mdb_zio_t zio; + uintptr_t *spap = wsp->walk_data; 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) + if (*spap != 0 && *spap != zio.io_spa) return (WALK_NEXT); /* If the parent list is not empty, ignore */ - if ((uintptr_t)zio.io_parent_list.list_head.list_next != + if (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")) @@ -2288,41 +2290,35 @@ zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_OK); } +typedef struct mdb_reference { + uintptr_t ref_holder; + uintptr_t ref_removed; + uint64_t ref_number; +} mdb_reference_t; + /* ARGSUSED */ static int reference_cb(uintptr_t addr, const void *ignored, void *arg) { - static int gotid; - static mdb_ctf_id_t ref_id; - uintptr_t ref_holder; - uintptr_t ref_removed; - uint64_t ref_number; + mdb_reference_t ref; boolean_t holder_is_str = B_FALSE; char holder_str[128]; boolean_t removed = (boolean_t)arg; - if (!gotid) { - if (mdb_ctf_lookup_by_name("struct reference", &ref_id) == -1) { - mdb_warn("couldn't find struct reference"); - return (WALK_ERR); - } - gotid = TRUE; - } - - if (GETMEMBID(addr, &ref_id, ref_holder, ref_holder) || - GETMEMBID(addr, &ref_id, ref_removed, ref_removed) || - GETMEMBID(addr, &ref_id, ref_number, ref_number)) - return (WALK_ERR); + if (mdb_ctf_vread(&ref, "reference_t", "mdb_reference_t", addr, + 0) == -1) + return (DCMD_ERR); - if (mdb_readstr(holder_str, sizeof (holder_str), ref_holder) != -1) + if (mdb_readstr(holder_str, sizeof (holder_str), + ref.ref_holder) != -1) holder_is_str = strisprint(holder_str); if (removed) mdb_printf("removed "); mdb_printf("reference "); - if (ref_number != 1) - mdb_printf("with count=%llu ", ref_number); - mdb_printf("with tag %p", (void*)ref_holder); + if (ref.ref_number != 1) + mdb_printf("with count=%llu ", ref.ref_number); + mdb_printf("with tag %lx", ref.ref_holder); if (holder_is_str) mdb_printf(" \"%s\"", holder_str); mdb_printf(", held at:\n"); @@ -2331,7 +2327,7 @@ reference_cb(uintptr_t addr, const void *ignored, void *arg) if (removed) { mdb_printf("removed at:\n"); - (void) mdb_call_dcmd("whatis", ref_removed, + (void) mdb_call_dcmd("whatis", ref.ref_removed, DCMD_ADDRSPEC, 0, NULL); } @@ -2340,15 +2336,26 @@ reference_cb(uintptr_t addr, const void *ignored, void *arg) return (WALK_NEXT); } +typedef struct mdb_refcount { + uint64_t rc_count; +} mdb_refcount_t; + +typedef struct mdb_refcount_removed { + uint64_t rc_removed_count; +} mdb_refcount_removed_t; + +typedef struct mdb_refcount_tracked { + boolean_t rc_tracked; +} mdb_refcount_tracked_t; + /* ARGSUSED */ static int refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - uint64_t rc_count, rc_removed_count; - uintptr_t rc_list, rc_removed; - static int gotid; - static mdb_ctf_id_t rc_id; - ulong_t off; + mdb_refcount_t rc; + mdb_refcount_removed_t rcr; + mdb_refcount_tracked_t rct; + int off; boolean_t released = B_FALSE; if (!(flags & DCMD_ADDRSPEC)) @@ -2359,48 +2366,41 @@ refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) NULL) != argc) return (DCMD_USAGE); - if (!gotid) { - /* - * The refcount structure is different when compiled debug - * vs nondebug. Therefore, we want to make sure we get the - * refcount definition from the ZFS module, in case it has - * been compiled debug but genunix is nondebug. - */ - if (mdb_ctf_lookup_by_name(ZFS_STRUCT "refcount", - &rc_id) == -1) { - mdb_warn("couldn't find struct refcount"); - return (DCMD_ERR); - } - gotid = TRUE; - } - - if (GETMEMBID(addr, &rc_id, rc_count, rc_count)) + if (mdb_ctf_vread(&rc, "refcount_t", "mdb_refcount_t", addr, + 0) == -1) 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); + if (mdb_ctf_vread(&rcr, "refcount_t", "mdb_refcount_removed_t", addr, + MDB_CTF_VREAD_QUIET) == -1) { + mdb_printf("refcount_t at %p has %llu holds (untracked)\n", + addr, (longlong_t)rc.rc_count); return (DCMD_OK); } + if (mdb_ctf_vread(&rct, "refcount_t", "mdb_refcount_tracked_t", addr, + MDB_CTF_VREAD_QUIET) == -1) { + /* If this is an old target, it might be tracked. */ + rct.rc_tracked = B_TRUE; + } + 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); + addr, (longlong_t)rc.rc_count, (longlong_t)rcr.rc_removed_count); - if (rc_count > 0) + if (rct.rc_tracked && rc.rc_count > 0) mdb_printf("current holds:\n"); - if (mdb_ctf_offsetof(rc_id, "rc_list", &off) == -1) + off = mdb_ctf_offsetof_by_name("refcount_t", "rc_list"); + if (off == -1) return (DCMD_ERR); - rc_list = addr + off/NBBY; - mdb_pwalk("list", reference_cb, (void*)B_FALSE, rc_list); + mdb_pwalk("list", reference_cb, (void*)B_FALSE, addr + off); + + if (released && rcr.rc_removed_count > 0) { + mdb_printf("released holds:\n"); - if (released) { - if (rc_removed_count > 0) - mdb_printf("released holds:\n"); - if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1) + off = mdb_ctf_offsetof_by_name("refcount_t", "rc_removed"); + if (off == -1) return (DCMD_ERR); - rc_removed = addr + off/NBBY; - mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed); + mdb_pwalk("list", reference_cb, (void*)B_FALSE, addr + off); } return (DCMD_OK); @@ -3004,7 +3004,7 @@ zfs_aces_walk_step(mdb_walk_state_t *wsp) } typedef struct mdb_zfs_rrwlock { - kthread_t *rr_writer; + uintptr_t rr_writer; boolean_t rr_writer_wanted; } mdb_zfs_rrwlock_t; @@ -3025,8 +3025,8 @@ rrwlock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 0) == -1) return (DCMD_ERR); - if (rrw.rr_writer != NULL) { - mdb_printf("write lock held by thread %p\n", rrw.rr_writer); + if (rrw.rr_writer != 0) { + mdb_printf("write lock held by thread %lx\n", rrw.rr_writer); return (DCMD_OK); } diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c index d4d32b9996..2ce719d21d 100644 --- a/usr/src/cmd/zdb/zdb.c +++ b/usr/src/cmd/zdb/zdb.c @@ -1997,6 +1997,8 @@ typedef struct zdb_blkstats { uint64_t zb_lsize; uint64_t zb_psize; uint64_t zb_count; + uint64_t zb_gangs; + uint64_t zb_ditto_samevdev; uint64_t zb_psize_histogram[PSIZE_HISTO_SIZE]; } zdb_blkstats_t; @@ -2044,6 +2046,7 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp, for (int i = 0; i < 4; i++) { int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL; int t = (i & 1) ? type : ZDB_OT_TOTAL; + int equal; zdb_blkstats_t *zb = &zcb->zcb_type[l][t]; zb->zb_asize += BP_GET_ASIZE(bp); @@ -2051,6 +2054,27 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp, zb->zb_psize += BP_GET_PSIZE(bp); zb->zb_count++; zb->zb_psize_histogram[BP_GET_PSIZE(bp) >> SPA_MINBLOCKSHIFT]++; + + zb->zb_gangs += BP_COUNT_GANG(bp); + + switch (BP_GET_NDVAS(bp)) { + case 2: + if (DVA_GET_VDEV(&bp->blk_dva[0]) == + DVA_GET_VDEV(&bp->blk_dva[1])) + zb->zb_ditto_samevdev++; + break; + case 3: + equal = (DVA_GET_VDEV(&bp->blk_dva[0]) == + DVA_GET_VDEV(&bp->blk_dva[1])) + + (DVA_GET_VDEV(&bp->blk_dva[0]) == + DVA_GET_VDEV(&bp->blk_dva[2])) + + (DVA_GET_VDEV(&bp->blk_dva[1]) == + DVA_GET_VDEV(&bp->blk_dva[2])); + if (equal != 0) + zb->zb_ditto_samevdev++; + break; + } + } if (dump_opt['L']) @@ -2439,6 +2463,8 @@ dump_block_stats(spa_t *spa) (void) printf("\n"); (void) printf("\tbp count: %10llu\n", (u_longlong_t)tzb->zb_count); + (void) printf("\tganged count: %10llu\n", + (longlong_t)tzb->zb_gangs); (void) printf("\tbp logical: %10llu avg: %6llu\n", (u_longlong_t)tzb->zb_lsize, (u_longlong_t)(tzb->zb_lsize / tzb->zb_count)); @@ -2460,6 +2486,11 @@ dump_block_stats(spa_t *spa) (void) printf("\tSPA allocated: %10llu used: %5.2f%%\n", (u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space); + if (tzb->zb_ditto_samevdev != 0) { + (void) printf("\tDittoed blocks on same vdev: %llu\n", + (longlong_t)tzb->zb_ditto_samevdev); + } + if (dump_opt['b'] >= 2) { int l, t, level; (void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE" @@ -2467,7 +2498,7 @@ dump_block_stats(spa_t *spa) for (t = 0; t <= ZDB_OT_TOTAL; t++) { char csize[32], lsize[32], psize[32], asize[32]; - char avg[32]; + char avg[32], gang[32]; char *typename; if (t < DMU_OT_NUMTYPES) @@ -2508,6 +2539,7 @@ dump_block_stats(spa_t *spa) zdb_nicenum(zb->zb_psize, psize); zdb_nicenum(zb->zb_asize, asize); zdb_nicenum(zb->zb_asize / zb->zb_count, avg); + zdb_nicenum(zb->zb_gangs, gang); (void) printf("%6s\t%5s\t%5s\t%5s\t%5s" "\t%5.2f\t%6.2f\t", @@ -2521,6 +2553,11 @@ dump_block_stats(spa_t *spa) (void) printf(" L%d %s\n", level, typename); + if (dump_opt['b'] >= 3 && zb->zb_gangs > 0) { + (void) printf("\t number of ganged " + "blocks: %s\n", gang); + } + if (dump_opt['b'] >= 4) { (void) printf("psize " "(in 512-byte sectors): " diff --git a/usr/src/uts/common/fs/zfs/sys/zap.h b/usr/src/uts/common/fs/zfs/sys/zap.h index 092669c8b3..1e975e99e0 100644 --- a/usr/src/uts/common/fs/zfs/sys/zap.h +++ b/usr/src/uts/common/fs/zfs/sys/zap.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Delphix. All rights reserved. */ #ifndef _SYS_ZAP_H @@ -368,11 +368,6 @@ void zap_cursor_advance(zap_cursor_t *zc); uint64_t zap_cursor_serialize(zap_cursor_t *zc); /* - * Advance the cursor to the attribute having the given key. - */ -int zap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt); - -/* * Initialize a zap cursor pointing to the position recorded by * zap_cursor_serialize (in the "serialized" argument). You can also * use a "serialized" argument of 0 to start at the beginning of the diff --git a/usr/src/uts/common/fs/zfs/sys/zap_impl.h b/usr/src/uts/common/fs/zfs/sys/zap_impl.h index 1dc322e02f..466aab02ba 100644 --- a/usr/src/uts/common/fs/zfs/sys/zap_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/zap_impl.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013 by Delphix. All rights reserved. */ #ifndef _SYS_ZAP_IMPL_H @@ -219,7 +220,6 @@ int fzap_add_cd(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, const void *val, uint32_t cd, dmu_tx_t *tx); void fzap_upgrade(zap_t *zap, dmu_tx_t *tx, zap_flags_t flags); -int fzap_cursor_move_to_key(zap_cursor_t *zc, zap_name_t *zn); #ifdef __cplusplus } diff --git a/usr/src/uts/common/fs/zfs/zap.c b/usr/src/uts/common/fs/zfs/zap.c index 0e637d56c9..2f4ccfb6ea 100644 --- a/usr/src/uts/common/fs/zfs/zap.c +++ b/usr/src/uts/common/fs/zfs/zap.c @@ -1242,31 +1242,6 @@ zap_stats_ptrtbl(zap_t *zap, uint64_t *tbl, int len, zap_stats_t *zs) } } -int -fzap_cursor_move_to_key(zap_cursor_t *zc, zap_name_t *zn) -{ - int err; - zap_leaf_t *l; - zap_entry_handle_t zeh; - - if (zn->zn_key_orig_numints * zn->zn_key_intlen > ZAP_MAXNAMELEN) - return (SET_ERROR(ENAMETOOLONG)); - - err = zap_deref_leaf(zc->zc_zap, zn->zn_hash, NULL, RW_READER, &l); - if (err != 0) - return (err); - - err = zap_leaf_lookup(l, zn, &zeh); - if (err != 0) - return (err); - - zc->zc_leaf = l; - zc->zc_hash = zeh.zeh_hash; - zc->zc_cd = zeh.zeh_cd; - - return (err); -} - void fzap_get_stats(zap_t *zap, zap_stats_t *zs) { diff --git a/usr/src/uts/common/fs/zfs/zap_micro.c b/usr/src/uts/common/fs/zfs/zap_micro.c index e79038017f..e2fc0118c6 100644 --- a/usr/src/uts/common/fs/zfs/zap_micro.c +++ b/usr/src/uts/common/fs/zfs/zap_micro.c @@ -1316,46 +1316,6 @@ zap_cursor_advance(zap_cursor_t *zc) } int -zap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt) -{ - int err = 0; - mzap_ent_t *mze; - zap_name_t *zn; - - if (zc->zc_zap == NULL) { - err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, - RW_READER, TRUE, FALSE, &zc->zc_zap); - if (err) - return (err); - } else { - rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); - } - - zn = zap_name_alloc(zc->zc_zap, name, mt); - if (zn == NULL) { - rw_exit(&zc->zc_zap->zap_rwlock); - return (SET_ERROR(ENOTSUP)); - } - - if (!zc->zc_zap->zap_ismicro) { - err = fzap_cursor_move_to_key(zc, zn); - } else { - mze = mze_find(zn); - if (mze == NULL) { - err = SET_ERROR(ENOENT); - goto out; - } - zc->zc_hash = mze->mze_hash; - zc->zc_cd = mze->mze_cd; - } - -out: - zap_name_free(zn); - rw_exit(&zc->zc_zap->zap_rwlock); - return (err); -} - -int zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs) { int err; |