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