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