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