Print this page
4171 clean up spa_feature_*() interfaces
4172 implement extensible_dataset feature for use by other zpool features
Reviewed by: Max Grossman <max.grossman@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>


 546         int refcount = 0;
 547 
 548         if (vd->vdev_top == vd) {
 549                 for (int m = 0; m < vd->vdev_ms_count; m++) {
 550                         space_map_t *sm = vd->vdev_ms[m]->ms_sm;
 551 
 552                         if (sm != NULL &&
 553                             sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
 554                                 refcount++;
 555                 }
 556         }
 557         for (int c = 0; c < vd->vdev_children; c++)
 558                 refcount += get_metaslab_refcount(vd->vdev_child[c]);
 559 
 560         return (refcount);
 561 }
 562 
 563 static int
 564 verify_spacemap_refcounts(spa_t *spa)
 565 {
 566         int expected_refcount, actual_refcount;

 567 
 568         expected_refcount = spa_feature_get_refcount(spa,
 569             &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM]);

 570         actual_refcount = get_dtl_refcount(spa->spa_root_vdev);
 571         actual_refcount += get_metaslab_refcount(spa->spa_root_vdev);
 572 
 573         if (expected_refcount != actual_refcount) {
 574                 (void) printf("space map refcount mismatch: expected %d != "
 575                     "actual %d\n", expected_refcount, actual_refcount);


 576                 return (2);
 577         }
 578         return (0);
 579 }
 580 
 581 static void
 582 dump_spacemap(objset_t *os, space_map_t *sm)
 583 {
 584         uint64_t alloc, offset, entry;
 585         char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
 586                             "INVALID", "INVALID", "INVALID", "INVALID" };
 587 
 588         if (sm == NULL)
 589                 return;
 590 
 591         /*
 592          * Print out the freelist entries in both encoded and decoded form.
 593          */
 594         alloc = 0;
 595         for (offset = 0; offset < space_map_length(sm);


 657         zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
 658 
 659         (void) printf(
 660             "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
 661             (u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
 662             (u_longlong_t)space_map_object(sm), freebuf);
 663 
 664         if (dump_opt['m'] > 2 && !dump_opt['L']) {
 665                 mutex_enter(&msp->ms_lock);
 666                 metaslab_load_wait(msp);
 667                 if (!msp->ms_loaded) {
 668                         VERIFY0(metaslab_load(msp));
 669                         range_tree_stat_verify(msp->ms_tree);
 670                 }
 671                 dump_metaslab_stats(msp);
 672                 metaslab_unload(msp);
 673                 mutex_exit(&msp->ms_lock);
 674         }
 675 
 676         if (dump_opt['m'] > 1 && sm != NULL &&
 677             spa_feature_is_active(spa,
 678             &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM])) {
 679                 /*
 680                  * The space map histogram represents free space in chunks
 681                  * of sm_shift (i.e. bucket 0 refers to 2^sm_shift).
 682                  */
 683                 (void) printf("\tOn-disk histogram:\n");
 684                 dump_histogram(sm->sm_phys->smp_histogram,
 685                     SPACE_MAP_HISTOGRAM_SIZE(sm), sm->sm_shift);
 686         }
 687 
 688         if (dump_opt['d'] > 5 || dump_opt['m'] > 3) {
 689                 ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift));
 690 
 691                 mutex_enter(&msp->ms_lock);
 692                 dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
 693                 mutex_exit(&msp->ms_lock);
 694         }
 695 }
 696 
 697 static void
 698 print_vdev_metaslab_header(vdev_t *vd)


2449 
2450         /*
2451          * Load all space maps as SM_ALLOC maps, then traverse the pool
2452          * claiming each block we discover.  If the pool is perfectly
2453          * consistent, the space maps will be empty when we're done.
2454          * Anything left over is a leak; any block we can't claim (because
2455          * it's not part of any space map) is a double allocation,
2456          * reference to a freed block, or an unclaimed log block.
2457          */
2458         zdb_leak_init(spa, &zcb);
2459 
2460         /*
2461          * If there's a deferred-free bplist, process that first.
2462          */
2463         (void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
2464             count_block_cb, &zcb, NULL);
2465         if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
2466                 (void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
2467                     count_block_cb, &zcb, NULL);
2468         }
2469         if (spa_feature_is_active(spa,
2470             &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
2471                 VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
2472                     spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
2473                     &zcb, NULL));
2474         }
2475 
2476         if (dump_opt['c'] > 1)
2477                 flags |= TRAVERSE_PREFETCH_DATA;
2478 
2479         zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
2480         zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
2481         zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
2482 
2483         /*
2484          * If we've traversed the data blocks then we need to wait for those
2485          * I/Os to complete. We leverage "The Godfather" zio to wait on
2486          * all async I/Os to complete.
2487          */
2488         if (dump_opt['c']) {
2489                 (void) zio_wait(spa->spa_async_zio_root);
2490                 spa->spa_async_zio_root = zio_root(spa, NULL, NULL,


2776         if (dump_opt['u'])
2777                 dump_uberblock(&spa->spa_uberblock, "\nUberblock:\n", "\n");
2778 
2779         if (dump_opt['D'])
2780                 dump_all_ddts(spa);
2781 
2782         if (dump_opt['d'] > 2 || dump_opt['m'])
2783                 dump_metaslabs(spa);
2784 
2785         if (dump_opt['d'] || dump_opt['i']) {
2786                 dump_dir(dp->dp_meta_objset);
2787                 if (dump_opt['d'] >= 3) {
2788                         dump_bpobj(&spa->spa_deferred_bpobj,
2789                             "Deferred frees", 0);
2790                         if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
2791                                 dump_bpobj(&spa->spa_dsl_pool->dp_free_bpobj,
2792                                     "Pool snapshot frees", 0);
2793                         }
2794 
2795                         if (spa_feature_is_active(spa,
2796                             &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
2797                                 dump_bptree(spa->spa_meta_objset,
2798                                     spa->spa_dsl_pool->dp_bptree_obj,
2799                                     "Pool dataset frees");
2800                         }
2801                         dump_dtl(spa->spa_root_vdev, 0);
2802                 }
2803                 (void) dmu_objset_find(spa_name(spa), dump_one_dir,
2804                     NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
2805         }
2806         if (dump_opt['b'] || dump_opt['c'])
2807                 rc = dump_block_stats(spa);
2808 
2809         if (rc == 0)
2810                 rc = verify_spacemap_refcounts(spa);
2811 
2812         if (dump_opt['s'])
2813                 show_pool_stats(spa);
2814 
2815         if (dump_opt['h'])
2816                 dump_history(spa);




 546         int refcount = 0;
 547 
 548         if (vd->vdev_top == vd) {
 549                 for (int m = 0; m < vd->vdev_ms_count; m++) {
 550                         space_map_t *sm = vd->vdev_ms[m]->ms_sm;
 551 
 552                         if (sm != NULL &&
 553                             sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
 554                                 refcount++;
 555                 }
 556         }
 557         for (int c = 0; c < vd->vdev_children; c++)
 558                 refcount += get_metaslab_refcount(vd->vdev_child[c]);
 559 
 560         return (refcount);
 561 }
 562 
 563 static int
 564 verify_spacemap_refcounts(spa_t *spa)
 565 {
 566         uint64_t expected_refcount = 0;
 567         uint64_t actual_refcount;
 568 
 569         (void) feature_get_refcount(spa,
 570             &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM],
 571             &expected_refcount);
 572         actual_refcount = get_dtl_refcount(spa->spa_root_vdev);
 573         actual_refcount += get_metaslab_refcount(spa->spa_root_vdev);
 574 
 575         if (expected_refcount != actual_refcount) {
 576                 (void) printf("space map refcount mismatch: expected %lld != "
 577                     "actual %lld\n",
 578                     (longlong_t)expected_refcount,
 579                     (longlong_t)actual_refcount);
 580                 return (2);
 581         }
 582         return (0);
 583 }
 584 
 585 static void
 586 dump_spacemap(objset_t *os, space_map_t *sm)
 587 {
 588         uint64_t alloc, offset, entry;
 589         char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
 590                             "INVALID", "INVALID", "INVALID", "INVALID" };
 591 
 592         if (sm == NULL)
 593                 return;
 594 
 595         /*
 596          * Print out the freelist entries in both encoded and decoded form.
 597          */
 598         alloc = 0;
 599         for (offset = 0; offset < space_map_length(sm);


 661         zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
 662 
 663         (void) printf(
 664             "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
 665             (u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
 666             (u_longlong_t)space_map_object(sm), freebuf);
 667 
 668         if (dump_opt['m'] > 2 && !dump_opt['L']) {
 669                 mutex_enter(&msp->ms_lock);
 670                 metaslab_load_wait(msp);
 671                 if (!msp->ms_loaded) {
 672                         VERIFY0(metaslab_load(msp));
 673                         range_tree_stat_verify(msp->ms_tree);
 674                 }
 675                 dump_metaslab_stats(msp);
 676                 metaslab_unload(msp);
 677                 mutex_exit(&msp->ms_lock);
 678         }
 679 
 680         if (dump_opt['m'] > 1 && sm != NULL &&
 681             spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {

 682                 /*
 683                  * The space map histogram represents free space in chunks
 684                  * of sm_shift (i.e. bucket 0 refers to 2^sm_shift).
 685                  */
 686                 (void) printf("\tOn-disk histogram:\n");
 687                 dump_histogram(sm->sm_phys->smp_histogram,
 688                     SPACE_MAP_HISTOGRAM_SIZE(sm), sm->sm_shift);
 689         }
 690 
 691         if (dump_opt['d'] > 5 || dump_opt['m'] > 3) {
 692                 ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift));
 693 
 694                 mutex_enter(&msp->ms_lock);
 695                 dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
 696                 mutex_exit(&msp->ms_lock);
 697         }
 698 }
 699 
 700 static void
 701 print_vdev_metaslab_header(vdev_t *vd)


2452 
2453         /*
2454          * Load all space maps as SM_ALLOC maps, then traverse the pool
2455          * claiming each block we discover.  If the pool is perfectly
2456          * consistent, the space maps will be empty when we're done.
2457          * Anything left over is a leak; any block we can't claim (because
2458          * it's not part of any space map) is a double allocation,
2459          * reference to a freed block, or an unclaimed log block.
2460          */
2461         zdb_leak_init(spa, &zcb);
2462 
2463         /*
2464          * If there's a deferred-free bplist, process that first.
2465          */
2466         (void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
2467             count_block_cb, &zcb, NULL);
2468         if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
2469                 (void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
2470                     count_block_cb, &zcb, NULL);
2471         }
2472         if (spa_feature_is_active(spa, SPA_FEATURE_ASYNC_DESTROY)) {

2473                 VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
2474                     spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
2475                     &zcb, NULL));
2476         }
2477 
2478         if (dump_opt['c'] > 1)
2479                 flags |= TRAVERSE_PREFETCH_DATA;
2480 
2481         zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
2482         zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
2483         zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
2484 
2485         /*
2486          * If we've traversed the data blocks then we need to wait for those
2487          * I/Os to complete. We leverage "The Godfather" zio to wait on
2488          * all async I/Os to complete.
2489          */
2490         if (dump_opt['c']) {
2491                 (void) zio_wait(spa->spa_async_zio_root);
2492                 spa->spa_async_zio_root = zio_root(spa, NULL, NULL,


2778         if (dump_opt['u'])
2779                 dump_uberblock(&spa->spa_uberblock, "\nUberblock:\n", "\n");
2780 
2781         if (dump_opt['D'])
2782                 dump_all_ddts(spa);
2783 
2784         if (dump_opt['d'] > 2 || dump_opt['m'])
2785                 dump_metaslabs(spa);
2786 
2787         if (dump_opt['d'] || dump_opt['i']) {
2788                 dump_dir(dp->dp_meta_objset);
2789                 if (dump_opt['d'] >= 3) {
2790                         dump_bpobj(&spa->spa_deferred_bpobj,
2791                             "Deferred frees", 0);
2792                         if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
2793                                 dump_bpobj(&spa->spa_dsl_pool->dp_free_bpobj,
2794                                     "Pool snapshot frees", 0);
2795                         }
2796 
2797                         if (spa_feature_is_active(spa,
2798                             SPA_FEATURE_ASYNC_DESTROY)) {
2799                                 dump_bptree(spa->spa_meta_objset,
2800                                     spa->spa_dsl_pool->dp_bptree_obj,
2801                                     "Pool dataset frees");
2802                         }
2803                         dump_dtl(spa->spa_root_vdev, 0);
2804                 }
2805                 (void) dmu_objset_find(spa_name(spa), dump_one_dir,
2806                     NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
2807         }
2808         if (dump_opt['b'] || dump_opt['c'])
2809                 rc = dump_block_stats(spa);
2810 
2811         if (rc == 0)
2812                 rc = verify_spacemap_refcounts(spa);
2813 
2814         if (dump_opt['s'])
2815                 show_pool_stats(spa);
2816 
2817         if (dump_opt['h'])
2818                 dump_history(spa);