1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * CDDL HEADER START 4 * 5 * This file and its contents are supplied under the terms of the 6 * Common Development and Distribution License ("CDDL"), version 1.0. 7 * You may only use this file in accordance with the terms of version 8 * 1.0 of the CDDL. 9 * 10 * A full copy of the text of the CDDL should have accompanied this 11 * source. A copy of the CDDL is also available via the Internet at 12 * http://www.illumos.org/license/CDDL. 13 * 14 * CDDL HEADER END 15 */ 16 17 /* 18 * Copyright (c) 2015 by Delphix. All rights reserved. 19 */ 20 21 #ifndef _SYS_VDEV_INDIRECT_MAPPING_H 22 #define _SYS_VDEV_INDIRECT_MAPPING_H 23 24 #include <sys/dmu.h> 25 #include <sys/list.h> 26 #include <sys/spa.h> 27 #include <sys/space_map.h> 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 typedef struct vdev_indirect_mapping_entry_phys { 34 /* 35 * Decode with DVA_MAPPING_* macros. 36 * Contains: 37 * the source offset (low 63 bits) 38 * the one-bit "mark", used for garbage collection (by zdb) 39 */ 40 uint64_t vimep_src; 41 42 /* 43 * Note: the DVA's asize is 24 bits, and can thus store ranges 44 * up to 8GB. 45 */ 46 dva_t vimep_dst; 47 } vdev_indirect_mapping_entry_phys_t; 48 49 #define DVA_MAPPING_GET_SRC_OFFSET(vimep) \ 50 BF64_GET_SB((vimep)->vimep_src, 0, 63, SPA_MINBLOCKSHIFT, 0) 51 #define DVA_MAPPING_SET_SRC_OFFSET(vimep, x) \ 52 BF64_SET_SB((vimep)->vimep_src, 0, 63, SPA_MINBLOCKSHIFT, 0, x) 53 54 typedef struct vdev_indirect_mapping_entry { 55 vdev_indirect_mapping_entry_phys_t vime_mapping; 56 uint32_t vime_obsolete_count; 57 list_node_t vime_node; 58 } vdev_indirect_mapping_entry_t; 59 60 /* 61 * This is stored in the bonus buffer of the mapping object, see comment of 62 * vdev_indirect_config for more details. 63 */ 64 typedef struct vdev_indirect_mapping_phys { 65 uint64_t vimp_max_offset; 66 uint64_t vimp_bytes_mapped; 67 uint64_t vimp_num_entries; /* number of v_i_m_entry_phys_t's */ 68 69 /* 70 * For each entry in the mapping object, this object contains an 71 * entry representing the number of bytes of that mapping entry 72 * that were no longer in use by the pool at the time this indirect 73 * vdev was last condensed. 74 */ 75 uint64_t vimp_counts_object; 76 } vdev_indirect_mapping_phys_t; 77 78 #define VDEV_INDIRECT_MAPPING_SIZE_V0 (3 * sizeof (uint64_t)) 79 80 typedef struct vdev_indirect_mapping { 81 uint64_t vim_object; 82 boolean_t vim_havecounts; 83 84 /* 85 * An ordered array of all mapping entries, sorted by source offset. 86 * Note that vim_entries is needed during a removal (and contains 87 * mappings that have been synced to disk so far) to handle frees 88 * from the removing device. 89 */ 90 vdev_indirect_mapping_entry_phys_t *vim_entries; 91 92 objset_t *vim_objset; 93 94 dmu_buf_t *vim_dbuf; 95 vdev_indirect_mapping_phys_t *vim_phys; 96 } vdev_indirect_mapping_t; 97 98 extern vdev_indirect_mapping_t *vdev_indirect_mapping_open(objset_t *os, 99 uint64_t object); 100 extern void vdev_indirect_mapping_close(vdev_indirect_mapping_t *vim); 101 extern uint64_t vdev_indirect_mapping_alloc(objset_t *os, dmu_tx_t *tx); 102 extern void vdev_indirect_mapping_free(objset_t *os, uint64_t obj, 103 dmu_tx_t *tx); 104 105 extern uint64_t vdev_indirect_mapping_num_entries(vdev_indirect_mapping_t *vim); 106 extern uint64_t vdev_indirect_mapping_max_offset(vdev_indirect_mapping_t *vim); 107 extern uint64_t vdev_indirect_mapping_object(vdev_indirect_mapping_t *vim); 108 extern uint64_t vdev_indirect_mapping_bytes_mapped( 109 vdev_indirect_mapping_t *vim); 110 extern uint64_t vdev_indirect_mapping_size(vdev_indirect_mapping_t *vim); 111 112 /* 113 * Writes the given list of vdev_indirect_mapping_entry_t to the mapping 114 * then updates internal state. 115 */ 116 extern void vdev_indirect_mapping_add_entries(vdev_indirect_mapping_t *vim, 117 list_t *vime_list, dmu_tx_t *tx); 118 119 extern vdev_indirect_mapping_entry_phys_t * 120 vdev_indirect_mapping_entry_for_offset(vdev_indirect_mapping_t *vim, 121 uint64_t offset); 122 123 extern vdev_indirect_mapping_entry_phys_t * 124 vdev_indirect_mapping_entry_for_offset_or_next(vdev_indirect_mapping_t *vim, 125 uint64_t offset); 126 127 extern uint32_t *vdev_indirect_mapping_load_obsolete_counts( 128 vdev_indirect_mapping_t *vim); 129 extern void vdev_indirect_mapping_load_obsolete_spacemap( 130 vdev_indirect_mapping_t *vim, 131 uint32_t *counts, space_map_t *obsolete_space_sm); 132 extern void vdev_indirect_mapping_increment_obsolete_count( 133 vdev_indirect_mapping_t *vim, 134 uint64_t offset, uint64_t asize, uint32_t *counts); 135 extern void vdev_indirect_mapping_free_obsolete_counts( 136 vdev_indirect_mapping_t *vim, uint32_t *counts); 137 138 #ifdef __cplusplus 139 } 140 #endif 141 142 #endif /* _SYS_VDEV_INDIRECT_MAPPING_H */ 143