xref: /freebsd/sys/contrib/openzfs/include/sys/vdev_indirect_mapping.h (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
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