xref: /illumos-gate/usr/src/uts/common/fs/zfs/sys/space_map.h (revision d6e555bdd793b8bc8fe57d5f12c3d69c813d0661)
1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5ecc2d604Sbonwick  * Common Development and Distribution License (the "License").
6ecc2d604Sbonwick  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
21fa9e4066Sahrens /*
22*d6e555bdSGeorge Wilson  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fa9e4066Sahrens  * Use is subject to license terms.
24fa9e4066Sahrens  */
25fa9e4066Sahrens 
26fa9e4066Sahrens #ifndef _SYS_SPACE_MAP_H
27fa9e4066Sahrens #define	_SYS_SPACE_MAP_H
28fa9e4066Sahrens 
29fa9e4066Sahrens #include <sys/avl.h>
30fa9e4066Sahrens #include <sys/dmu.h>
31fa9e4066Sahrens 
32fa9e4066Sahrens #ifdef	__cplusplus
33fa9e4066Sahrens extern "C" {
34fa9e4066Sahrens #endif
35fa9e4066Sahrens 
36ecc2d604Sbonwick typedef struct space_map_ops space_map_ops_t;
37ecc2d604Sbonwick 
38fa9e4066Sahrens typedef struct space_map {
39ecc2d604Sbonwick 	avl_tree_t	sm_root;	/* AVL tree of map segments */
40ecc2d604Sbonwick 	uint64_t	sm_space;	/* sum of all segments in the map */
41ecc2d604Sbonwick 	uint64_t	sm_start;	/* start of map */
42ecc2d604Sbonwick 	uint64_t	sm_size;	/* size of map */
43ecc2d604Sbonwick 	uint8_t		sm_shift;	/* unit shift */
44ecc2d604Sbonwick 	uint8_t		sm_pad[3];	/* unused */
45ecc2d604Sbonwick 	uint8_t		sm_loaded;	/* map loaded? */
46ecc2d604Sbonwick 	uint8_t		sm_loading;	/* map loading? */
47ecc2d604Sbonwick 	kcondvar_t	sm_load_cv;	/* map load completion */
48ecc2d604Sbonwick 	space_map_ops_t	*sm_ops;	/* space map block picker ops vector */
49*d6e555bdSGeorge Wilson 	avl_tree_t	*sm_pp_root;	/* picker-private AVL tree */
50ecc2d604Sbonwick 	void		*sm_ppd;	/* picker-private data */
51fa9e4066Sahrens 	kmutex_t	*sm_lock;	/* pointer to lock that protects map */
52fa9e4066Sahrens } space_map_t;
53fa9e4066Sahrens 
54fa9e4066Sahrens typedef struct space_seg {
55fa9e4066Sahrens 	avl_node_t	ss_node;	/* AVL node */
56*d6e555bdSGeorge Wilson 	avl_node_t	ss_pp_node;	/* AVL picker-private node */
57fa9e4066Sahrens 	uint64_t	ss_start;	/* starting offset of this segment */
58fa9e4066Sahrens 	uint64_t	ss_end;		/* ending offset (non-inclusive) */
59fa9e4066Sahrens } space_seg_t;
60fa9e4066Sahrens 
618ad4d6ddSJeff Bonwick typedef struct space_ref {
628ad4d6ddSJeff Bonwick 	avl_node_t	sr_node;	/* AVL node */
638ad4d6ddSJeff Bonwick 	uint64_t	sr_offset;	/* offset (start or end) */
648ad4d6ddSJeff Bonwick 	int64_t		sr_refcnt;	/* associated reference count */
658ad4d6ddSJeff Bonwick } space_ref_t;
668ad4d6ddSJeff Bonwick 
67fa9e4066Sahrens typedef struct space_map_obj {
68fa9e4066Sahrens 	uint64_t	smo_object;	/* on-disk space map object */
69fa9e4066Sahrens 	uint64_t	smo_objsize;	/* size of the object */
70fa9e4066Sahrens 	uint64_t	smo_alloc;	/* space allocated from the map */
71fa9e4066Sahrens } space_map_obj_t;
72fa9e4066Sahrens 
73ecc2d604Sbonwick struct space_map_ops {
74ecc2d604Sbonwick 	void	(*smop_load)(space_map_t *sm);
75ecc2d604Sbonwick 	void	(*smop_unload)(space_map_t *sm);
76ecc2d604Sbonwick 	uint64_t (*smop_alloc)(space_map_t *sm, uint64_t size);
77ecc2d604Sbonwick 	void	(*smop_claim)(space_map_t *sm, uint64_t start, uint64_t size);
78ecc2d604Sbonwick 	void	(*smop_free)(space_map_t *sm, uint64_t start, uint64_t size);
79*d6e555bdSGeorge Wilson 	uint64_t (*smop_max)(space_map_t *sm);
80ecc2d604Sbonwick };
81ecc2d604Sbonwick 
82fa9e4066Sahrens /*
83fa9e4066Sahrens  * debug entry
84fa9e4066Sahrens  *
85fa9e4066Sahrens  *    1      3         10                     50
86fa9e4066Sahrens  *  ,---+--------+------------+---------------------------------.
87fa9e4066Sahrens  *  | 1 | action |  syncpass  |        txg (lower bits)         |
88fa9e4066Sahrens  *  `---+--------+------------+---------------------------------'
89fa9e4066Sahrens  *   63  62    60 59        50 49                               0
90fa9e4066Sahrens  *
91fa9e4066Sahrens  *
92fa9e4066Sahrens  *
93fa9e4066Sahrens  * non-debug entry
94fa9e4066Sahrens  *
95fa9e4066Sahrens  *    1               47                   1           15
96fa9e4066Sahrens  *  ,-----------------------------------------------------------.
97fa9e4066Sahrens  *  | 0 |   offset (sm_shift units)    | type |       run       |
98fa9e4066Sahrens  *  `-----------------------------------------------------------'
99fa9e4066Sahrens  *   63  62                          17   16   15               0
100fa9e4066Sahrens  */
101fa9e4066Sahrens 
102fa9e4066Sahrens /* All this stuff takes and returns bytes */
103fa9e4066Sahrens #define	SM_RUN_DECODE(x)	(BF64_DECODE(x, 0, 15) + 1)
104fa9e4066Sahrens #define	SM_RUN_ENCODE(x)	BF64_ENCODE((x) - 1, 0, 15)
105fa9e4066Sahrens #define	SM_TYPE_DECODE(x)	BF64_DECODE(x, 15, 1)
106fa9e4066Sahrens #define	SM_TYPE_ENCODE(x)	BF64_ENCODE(x, 15, 1)
107fa9e4066Sahrens #define	SM_OFFSET_DECODE(x)	BF64_DECODE(x, 16, 47)
108fa9e4066Sahrens #define	SM_OFFSET_ENCODE(x)	BF64_ENCODE(x, 16, 47)
109fa9e4066Sahrens #define	SM_DEBUG_DECODE(x)	BF64_DECODE(x, 63, 1)
110fa9e4066Sahrens #define	SM_DEBUG_ENCODE(x)	BF64_ENCODE(x, 63, 1)
111fa9e4066Sahrens 
112fa9e4066Sahrens #define	SM_DEBUG_ACTION_DECODE(x)	BF64_DECODE(x, 60, 3)
113fa9e4066Sahrens #define	SM_DEBUG_ACTION_ENCODE(x)	BF64_ENCODE(x, 60, 3)
114fa9e4066Sahrens 
115fa9e4066Sahrens #define	SM_DEBUG_SYNCPASS_DECODE(x)	BF64_DECODE(x, 50, 10)
116fa9e4066Sahrens #define	SM_DEBUG_SYNCPASS_ENCODE(x)	BF64_ENCODE(x, 50, 10)
117fa9e4066Sahrens 
118fa9e4066Sahrens #define	SM_DEBUG_TXG_DECODE(x)		BF64_DECODE(x, 0, 50)
119fa9e4066Sahrens #define	SM_DEBUG_TXG_ENCODE(x)		BF64_ENCODE(x, 0, 50)
120fa9e4066Sahrens 
121fa9e4066Sahrens #define	SM_RUN_MAX			SM_RUN_DECODE(~0ULL)
122fa9e4066Sahrens 
123fa9e4066Sahrens #define	SM_ALLOC	0x0
124fa9e4066Sahrens #define	SM_FREE		0x1
125fa9e4066Sahrens 
126fa9e4066Sahrens /*
127fa9e4066Sahrens  * The data for a given space map can be kept on blocks of any size.
128fa9e4066Sahrens  * Larger blocks entail fewer i/o operations, but they also cause the
129fa9e4066Sahrens  * DMU to keep more data in-core, and also to waste more i/o bandwidth
130fa9e4066Sahrens  * when only a few blocks have changed since the last transaction group.
131fa9e4066Sahrens  * This could use a lot more research, but for now, set the freelist
132fa9e4066Sahrens  * block size to 4k (2^12).
133fa9e4066Sahrens  */
134fa9e4066Sahrens #define	SPACE_MAP_BLOCKSHIFT	12
135fa9e4066Sahrens 
136fa9e4066Sahrens typedef void space_map_func_t(space_map_t *sm, uint64_t start, uint64_t size);
137fa9e4066Sahrens 
138fa9e4066Sahrens extern void space_map_create(space_map_t *sm, uint64_t start, uint64_t size,
139ecc2d604Sbonwick     uint8_t shift, kmutex_t *lp);
140fa9e4066Sahrens extern void space_map_destroy(space_map_t *sm);
141fa9e4066Sahrens extern void space_map_add(space_map_t *sm, uint64_t start, uint64_t size);
142fa9e4066Sahrens extern void space_map_remove(space_map_t *sm, uint64_t start, uint64_t size);
1438ad4d6ddSJeff Bonwick extern boolean_t space_map_contains(space_map_t *sm,
1448ad4d6ddSJeff Bonwick     uint64_t start, uint64_t size);
145fa9e4066Sahrens extern void space_map_vacate(space_map_t *sm,
146fa9e4066Sahrens     space_map_func_t *func, space_map_t *mdest);
147ecc2d604Sbonwick extern void space_map_walk(space_map_t *sm,
148fa9e4066Sahrens     space_map_func_t *func, space_map_t *mdest);
149fa9e4066Sahrens 
150ecc2d604Sbonwick extern void space_map_load_wait(space_map_t *sm);
151ecc2d604Sbonwick extern int space_map_load(space_map_t *sm, space_map_ops_t *ops,
152ecc2d604Sbonwick     uint8_t maptype, space_map_obj_t *smo, objset_t *os);
153ecc2d604Sbonwick extern void space_map_unload(space_map_t *sm);
154ecc2d604Sbonwick 
155ecc2d604Sbonwick extern uint64_t space_map_alloc(space_map_t *sm, uint64_t size);
156ecc2d604Sbonwick extern void space_map_claim(space_map_t *sm, uint64_t start, uint64_t size);
157ecc2d604Sbonwick extern void space_map_free(space_map_t *sm, uint64_t start, uint64_t size);
158*d6e555bdSGeorge Wilson extern uint64_t space_map_maxsize(space_map_t *sm);
159ecc2d604Sbonwick 
160ecc2d604Sbonwick extern void space_map_sync(space_map_t *sm, uint8_t maptype,
161ecc2d604Sbonwick     space_map_obj_t *smo, objset_t *os, dmu_tx_t *tx);
162ecc2d604Sbonwick extern void space_map_truncate(space_map_obj_t *smo,
163fa9e4066Sahrens     objset_t *os, dmu_tx_t *tx);
164fa9e4066Sahrens 
1658ad4d6ddSJeff Bonwick extern void space_map_ref_create(avl_tree_t *t);
1668ad4d6ddSJeff Bonwick extern void space_map_ref_destroy(avl_tree_t *t);
1678ad4d6ddSJeff Bonwick extern void space_map_ref_add_seg(avl_tree_t *t,
1688ad4d6ddSJeff Bonwick     uint64_t start, uint64_t end, int64_t refcnt);
1698ad4d6ddSJeff Bonwick extern void space_map_ref_add_map(avl_tree_t *t,
1708ad4d6ddSJeff Bonwick     space_map_t *sm, int64_t refcnt);
1718ad4d6ddSJeff Bonwick extern void space_map_ref_generate_map(avl_tree_t *t,
1728ad4d6ddSJeff Bonwick     space_map_t *sm, int64_t minref);
1738ad4d6ddSJeff Bonwick 
174fa9e4066Sahrens #ifdef	__cplusplus
175fa9e4066Sahrens }
176fa9e4066Sahrens #endif
177fa9e4066Sahrens 
178fa9e4066Sahrens #endif	/* _SYS_SPACE_MAP_H */
179