106 (void) fprintf(stderr, " -s report stats on zdb's I/O\n"); |
106 (void) fprintf(stderr, " -s report stats on zdb's I/O\n"); |
107 (void) fprintf(stderr, " -S <user|all>:<cksum_alg|all> -- " |
107 (void) fprintf(stderr, " -S <user|all>:<cksum_alg|all> -- " |
108 "dump blkptr signatures\n"); |
108 "dump blkptr signatures\n"); |
109 (void) fprintf(stderr, " -v verbose (applies to all others)\n"); |
109 (void) fprintf(stderr, " -v verbose (applies to all others)\n"); |
110 (void) fprintf(stderr, " -l dump label contents\n"); |
110 (void) fprintf(stderr, " -l dump label contents\n"); |
|
111 (void) fprintf(stderr, " -L disable leak tracking (do not " |
|
112 "load spacemaps)\n"); |
111 (void) fprintf(stderr, " -U cachefile_path -- use alternate " |
113 (void) fprintf(stderr, " -U cachefile_path -- use alternate " |
112 "cachefile\n"); |
114 "cachefile\n"); |
113 (void) fprintf(stderr, " -R read and display block from a " |
115 (void) fprintf(stderr, " -R read and display block from a " |
114 "device\n"); |
116 "device\n"); |
115 (void) fprintf(stderr, " -e Pool is exported/destroyed/" |
117 (void) fprintf(stderr, " -e Pool is exported/destroyed/" |
1479 (u_longlong_t)bp->blk_cksum.zc_word[2], |
1481 (u_longlong_t)bp->blk_cksum.zc_word[2], |
1480 (u_longlong_t)bp->blk_cksum.zc_word[3]); |
1482 (u_longlong_t)bp->blk_cksum.zc_word[3]); |
1481 } |
1483 } |
1482 } |
1484 } |
1483 |
1485 |
1484 VERIFY(zio_wait(zio_claim(NULL, spa, spa_first_txg(spa), bp, |
1486 if (!dump_opt['L']) |
1485 NULL, NULL, ZIO_FLAG_MUSTSUCCEED)) == 0); |
1487 VERIFY(zio_wait(zio_claim(NULL, spa, spa_first_txg(spa), bp, |
|
1488 NULL, NULL, ZIO_FLAG_MUSTSUCCEED)) == 0); |
1486 } |
1489 } |
1487 |
1490 |
1488 static int |
1491 static int |
1489 zdb_blkptr_cb(spa_t *spa, blkptr_t *bp, const zbookmark_t *zb, |
1492 zdb_blkptr_cb(spa_t *spa, blkptr_t *bp, const zbookmark_t *zb, |
1490 const dnode_phys_t *dnp, void *arg) |
1493 const dnode_phys_t *dnp, void *arg) |
1555 vdev_t *rvd = spa->spa_root_vdev; |
1558 vdev_t *rvd = spa->spa_root_vdev; |
1556 int leaks = 0; |
1559 int leaks = 0; |
1557 int c, e; |
1560 int c, e; |
1558 |
1561 |
1559 if (!dump_opt['S']) { |
1562 if (!dump_opt['S']) { |
1560 (void) printf("\nTraversing all blocks to %sverify" |
1563 (void) printf("\nTraversing all blocks %s%s%s%s...\n", |
1561 " nothing leaked ...\n", |
1564 (dump_opt['c'] || !dump_opt['L']) ? "to verify " : "", |
1562 dump_opt['c'] ? "verify checksums and " : ""); |
1565 dump_opt['c'] ? "checksums " : "", |
|
1566 (dump_opt['c'] && !dump_opt['L']) ? "and verify " : "", |
|
1567 !dump_opt['L'] ? "nothing leaked " : ""); |
1563 } |
1568 } |
1564 |
1569 |
1565 /* |
1570 /* |
1566 * Load all space maps as SM_ALLOC maps, then traverse the pool |
1571 * Load all space maps as SM_ALLOC maps, then traverse the pool |
1567 * claiming each block we discover. If the pool is perfectly |
1572 * claiming each block we discover. If the pool is perfectly |
1568 * consistent, the space maps will be empty when we're done. |
1573 * consistent, the space maps will be empty when we're done. |
1569 * Anything left over is a leak; any block we can't claim (because |
1574 * Anything left over is a leak; any block we can't claim (because |
1570 * it's not part of any space map) is a double allocation, |
1575 * it's not part of any space map) is a double allocation, |
1571 * reference to a freed block, or an unclaimed log block. |
1576 * reference to a freed block, or an unclaimed log block. |
1572 */ |
1577 */ |
1573 zdb_leak_init(spa); |
1578 if (!dump_opt['L']) |
|
1579 zdb_leak_init(spa); |
1574 |
1580 |
1575 /* |
1581 /* |
1576 * If there's a deferred-free bplist, process that first. |
1582 * If there's a deferred-free bplist, process that first. |
1577 */ |
1583 */ |
1578 if (spa->spa_sync_bplist_obj != 0) { |
1584 if (spa->spa_sync_bplist_obj != 0) { |
1636 logalloc += rvd->vdev_child[c]->vdev_stat.vs_alloc; |
1643 logalloc += rvd->vdev_child[c]->vdev_stat.vs_alloc; |
1637 |
1644 |
1638 tzb = &zcb.zcb_type[ZB_TOTAL][DMU_OT_TOTAL]; |
1645 tzb = &zcb.zcb_type[ZB_TOTAL][DMU_OT_TOTAL]; |
1639 |
1646 |
1640 if (tzb->zb_asize == alloc + logalloc) { |
1647 if (tzb->zb_asize == alloc + logalloc) { |
1641 (void) printf("\n\tNo leaks (block sum matches space" |
1648 if (!dump_opt['L']) |
1642 " maps exactly)\n"); |
1649 (void) printf("\n\tNo leaks (block sum matches space" |
|
1650 " maps exactly)\n"); |
1643 } else { |
1651 } else { |
1644 (void) printf("block traversal size %llu != alloc %llu " |
1652 (void) printf("block traversal size %llu != alloc %llu " |
1645 "(leaked %lld)\n", |
1653 "(%s %lld)\n", |
1646 (u_longlong_t)tzb->zb_asize, |
1654 (u_longlong_t)tzb->zb_asize, |
1647 (u_longlong_t)alloc + logalloc, |
1655 (u_longlong_t)alloc + logalloc, |
1648 (u_longlong_t)(alloc + logalloc - tzb->zb_asize)); |
1656 (dump_opt['L']) ? "unreachable" : "leaked", |
|
1657 (longlong_t)(alloc + logalloc - tzb->zb_asize)); |
1649 leaks = 1; |
1658 leaks = 1; |
1650 } |
1659 } |
1651 |
1660 |
1652 if (tzb->zb_count == 0) |
1661 if (tzb->zb_count == 0) |
1653 return (2); |
1662 return (2); |
2233 (void) setrlimit(RLIMIT_NOFILE, &rl); |
2242 (void) setrlimit(RLIMIT_NOFILE, &rl); |
2234 (void) enable_extended_FILE_stdio(-1, -1); |
2243 (void) enable_extended_FILE_stdio(-1, -1); |
2235 |
2244 |
2236 dprintf_setup(&argc, argv); |
2245 dprintf_setup(&argc, argv); |
2237 |
2246 |
2238 while ((c = getopt(argc, argv, "udibcsvCS:U:lRep:")) != -1) { |
2247 while ((c = getopt(argc, argv, "udibcsvCLS:U:lRep:")) != -1) { |
2239 switch (c) { |
2248 switch (c) { |
2240 case 'u': |
2249 case 'u': |
2241 case 'd': |
2250 case 'd': |
2242 case 'i': |
2251 case 'i': |
2243 case 'b': |
2252 case 'b': |