* Note: The space map's dbuf must be dirty for the changes in sm_phys to * take effect. */
| 666 | * take effect. |
| 667 | */ |
| 668 | static void |
| 669 | space_map_write_impl(space_map_t *sm, range_tree_t *rt, maptype_t maptype, |
| 670 | uint64_t vdev_id, dmu_tx_t *tx) |
| 671 | { |
| 672 | spa_t *spa = tx->tx_pool->dp_spa; |
| 673 | dmu_buf_t *db; |
| 674 | |
| 675 | space_map_write_intro_debug(sm, maptype, tx); |
| 676 | |
| 677 | #ifdef ZFS_DEBUG |
| 678 | /* |
| 679 | * We do this right after we write the intro debug entry |
| 680 | * because the estimate does not take it into account. |
| 681 | */ |
| 682 | uint64_t initial_objsize = sm->sm_phys->smp_length; |
| 683 | uint64_t estimated_growth = |
| 684 | space_map_estimate_optimal_size(sm, rt, SM_NO_VDEVID); |
| 685 | uint64_t estimated_final_objsize = initial_objsize + estimated_growth; |
| 686 | #endif |
| 687 | |
| 688 | /* |
| 689 | * Find the offset right after the last word in the space map |
| 690 | * and use that to get a hold of the last block, so we can |
| 691 | * start appending to it. |
| 692 | */ |
| 693 | uint64_t next_word_offset = sm->sm_phys->smp_length; |
| 694 | VERIFY0(dmu_buf_hold(sm->sm_os, space_map_object(sm), |
| 695 | next_word_offset, FTAG, &db, DMU_READ_PREFETCH)); |
| 696 | ASSERT3U(db->db_size, ==, sm->sm_blksz); |
| 697 | |
| 698 | dmu_buf_will_dirty(db, tx); |
| 699 | |
| 700 | zfs_btree_t *t = &rt->rt_root; |
| 701 | zfs_btree_index_t where; |
| 702 | for (range_seg_t *rs = zfs_btree_first(t, &where); rs != NULL; |
| 703 | rs = zfs_btree_next(t, &where, &where)) { |
| 704 | uint64_t offset = (rs_get_start(rs, rt) - sm->sm_start) >> |
| 705 | sm->sm_shift; |
| 706 | uint64_t length = (rs_get_end(rs, rt) - rs_get_start(rs, rt)) >> |
| 707 | sm->sm_shift; |
| 708 | uint8_t words = 1; |
| 709 | |
| 710 | /* |
| 711 | * We only write two-word entries when both of the following |
| 712 | * are true: |
| 713 | * |
| 714 | * [1] The feature is enabled. |
| 715 | * [2] The offset or run is too big for a single-word entry, |
| 716 | * or the vdev_id is set (meaning not equal to |
| 717 | * SM_NO_VDEVID). |
| 718 | * |
| 719 | * Note that for purposes of testing we've added the case that |
| 720 | * we write two-word entries occasionally when the feature is |
| 721 | * enabled and zfs_force_some_double_word_sm_entries has been |
| 722 | * set. |
| 723 | */ |
| 724 | if (spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_V2) && |
| 725 | (offset >= (1ULL << SM_OFFSET_BITS) || |
no test coverage detected