Print this page
4101 metaslab_debug should allow for fine-grained control
4102 space_maps should store more information about themselves
4103 space map object blocksize should be increased
4104 ::spa_space no longer works
4105 removing a mirrored log device results in a leaked object
4106 asynchronously load metaslab
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Sebastien Roy <seb@delphix.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/zfs/sys/space_map.h
+++ new/usr/src/uts/common/fs/zfs/sys/space_map.h
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 - * Copyright (c) 2012 by Delphix. All rights reserved.
27 + * Copyright (c) 2013 by Delphix. All rights reserved.
28 28 */
29 29
30 30 #ifndef _SYS_SPACE_MAP_H
31 31 #define _SYS_SPACE_MAP_H
32 32
33 33 #include <sys/avl.h>
34 +#include <sys/range_tree.h>
34 35 #include <sys/dmu.h>
35 36
36 37 #ifdef __cplusplus
37 38 extern "C" {
38 39 #endif
39 40
40 -typedef struct space_map_ops space_map_ops_t;
41 +/*
42 + * The size of the space map object has increased to include a histogram.
43 + * The SPACE_MAP_SIZE_V0 designates the original size and is used to
44 + * maintain backward compatibility.
45 + */
46 +#define SPACE_MAP_SIZE_V0 (3 * sizeof (uint64_t))
47 +#define SPACE_MAP_HISTOGRAM_SIZE(sm) \
48 + (sizeof ((sm)->sm_phys->smp_histogram) / \
49 + sizeof ((sm)->sm_phys->smp_histogram[0]))
41 50
51 +/*
52 + * The space_map_phys is the on-disk representation of the space map.
53 + * Consumers of space maps should never reference any of the members of this
54 + * structure directly. These members may only be updated in syncing context.
55 + *
56 + * Note the smp_object is no longer used but remains in the structure
57 + * for backward compatibility.
58 + */
59 +typedef struct space_map_phys {
60 + uint64_t smp_object; /* on-disk space map object */
61 + uint64_t smp_objsize; /* size of the object */
62 + uint64_t smp_alloc; /* space allocated from the map */
63 + uint64_t smp_pad[5]; /* reserved */
64 +
65 + /*
66 + * The smp_histogram maintains a histogram of free regions. Each
67 + * bucket, smp_histogram[i], contains the number of free regions
68 + * whose size is:
69 + * 2^(i+sm_shift) <= size of free region in bytes < 2^(i+sm_shift+1)
70 + */
71 + uint64_t smp_histogram[32]; /* histogram of free space */
72 +} space_map_phys_t;
73 +
74 +/*
75 + * The space map object defines a region of space, its size, how much is
76 + * allocated, and the on-disk object that stores this information.
77 + * Consumers of space maps may only access the members of this structure.
78 + */
42 79 typedef struct space_map {
43 - avl_tree_t sm_root; /* offset-ordered segment AVL tree */
44 - uint64_t sm_space; /* sum of all segments in the map */
45 80 uint64_t sm_start; /* start of map */
46 81 uint64_t sm_size; /* size of map */
47 82 uint8_t sm_shift; /* unit shift */
48 - uint8_t sm_loaded; /* map loaded? */
49 - uint8_t sm_loading; /* map loading? */
50 - uint8_t sm_condensing; /* map condensing? */
51 - kcondvar_t sm_load_cv; /* map load completion */
52 - space_map_ops_t *sm_ops; /* space map block picker ops vector */
53 - avl_tree_t *sm_pp_root; /* size-ordered, picker-private tree */
54 - void *sm_ppd; /* picker-private data */
83 + uint64_t sm_length; /* synced length */
84 + uint64_t sm_alloc; /* synced space allocated */
85 + objset_t *sm_os; /* objset for this map */
86 + uint64_t sm_object; /* object id for this map */
87 + uint32_t sm_blksz; /* block size for space map */
88 + dmu_buf_t *sm_dbuf; /* space_map_phys_t dbuf */
89 + space_map_phys_t *sm_phys; /* on-disk space map */
55 90 kmutex_t *sm_lock; /* pointer to lock that protects map */
56 91 } space_map_t;
57 92
58 -typedef struct space_seg {
59 - avl_node_t ss_node; /* AVL node */
60 - avl_node_t ss_pp_node; /* AVL picker-private node */
61 - uint64_t ss_start; /* starting offset of this segment */
62 - uint64_t ss_end; /* ending offset (non-inclusive) */
63 -} space_seg_t;
64 -
65 -typedef struct space_ref {
66 - avl_node_t sr_node; /* AVL node */
67 - uint64_t sr_offset; /* offset (start or end) */
68 - int64_t sr_refcnt; /* associated reference count */
69 -} space_ref_t;
70 -
71 -typedef struct space_map_obj {
72 - uint64_t smo_object; /* on-disk space map object */
73 - uint64_t smo_objsize; /* size of the object */
74 - uint64_t smo_alloc; /* space allocated from the map */
75 -} space_map_obj_t;
76 -
77 -struct space_map_ops {
78 - void (*smop_load)(space_map_t *sm);
79 - void (*smop_unload)(space_map_t *sm);
80 - uint64_t (*smop_alloc)(space_map_t *sm, uint64_t size);
81 - void (*smop_claim)(space_map_t *sm, uint64_t start, uint64_t size);
82 - void (*smop_free)(space_map_t *sm, uint64_t start, uint64_t size);
83 - uint64_t (*smop_max)(space_map_t *sm);
84 - boolean_t (*smop_fragmented)(space_map_t *sm);
85 -};
86 -
87 93 /*
88 94 * debug entry
89 95 *
90 96 * 1 3 10 50
91 97 * ,---+--------+------------+---------------------------------.
92 98 * | 1 | action | syncpass | txg (lower bits) |
93 99 * `---+--------+------------+---------------------------------'
94 100 * 63 62 60 59 50 49 0
95 101 *
96 102 *
97 103 * non-debug entry
98 104 *
99 105 * 1 47 1 15
100 106 * ,-----------------------------------------------------------.
101 107 * | 0 | offset (sm_shift units) | type | run |
102 108 * `-----------------------------------------------------------'
103 109 * 63 62 17 16 15 0
104 110 */
105 111
106 112 /* All this stuff takes and returns bytes */
107 113 #define SM_RUN_DECODE(x) (BF64_DECODE(x, 0, 15) + 1)
108 114 #define SM_RUN_ENCODE(x) BF64_ENCODE((x) - 1, 0, 15)
109 115 #define SM_TYPE_DECODE(x) BF64_DECODE(x, 15, 1)
110 116 #define SM_TYPE_ENCODE(x) BF64_ENCODE(x, 15, 1)
111 117 #define SM_OFFSET_DECODE(x) BF64_DECODE(x, 16, 47)
112 118 #define SM_OFFSET_ENCODE(x) BF64_ENCODE(x, 16, 47)
113 119 #define SM_DEBUG_DECODE(x) BF64_DECODE(x, 63, 1)
114 120 #define SM_DEBUG_ENCODE(x) BF64_ENCODE(x, 63, 1)
115 121
116 122 #define SM_DEBUG_ACTION_DECODE(x) BF64_DECODE(x, 60, 3)
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
117 123 #define SM_DEBUG_ACTION_ENCODE(x) BF64_ENCODE(x, 60, 3)
118 124
119 125 #define SM_DEBUG_SYNCPASS_DECODE(x) BF64_DECODE(x, 50, 10)
120 126 #define SM_DEBUG_SYNCPASS_ENCODE(x) BF64_ENCODE(x, 50, 10)
121 127
122 128 #define SM_DEBUG_TXG_DECODE(x) BF64_DECODE(x, 0, 50)
123 129 #define SM_DEBUG_TXG_ENCODE(x) BF64_ENCODE(x, 0, 50)
124 130
125 131 #define SM_RUN_MAX SM_RUN_DECODE(~0ULL)
126 132
127 -#define SM_ALLOC 0x0
128 -#define SM_FREE 0x1
133 +typedef enum {
134 + SM_ALLOC,
135 + SM_FREE
136 +} maptype_t;
129 137
130 138 /*
131 139 * The data for a given space map can be kept on blocks of any size.
132 140 * Larger blocks entail fewer i/o operations, but they also cause the
133 141 * DMU to keep more data in-core, and also to waste more i/o bandwidth
134 142 * when only a few blocks have changed since the last transaction group.
135 - * This could use a lot more research, but for now, set the freelist
136 - * block size to 4k (2^12).
143 + * Rather than having a fixed block size for all space maps the block size
144 + * can adjust as needed (see space_map_max_blksz). Set the initial block
145 + * size for the space map to 4k.
137 146 */
138 -#define SPACE_MAP_BLOCKSHIFT 12
147 +#define SPACE_MAP_INITIAL_BLOCKSIZE (1ULL << 12)
139 148
140 -typedef void space_map_func_t(space_map_t *sm, uint64_t start, uint64_t size);
149 +int space_map_load(space_map_t *sm, range_tree_t *rt, maptype_t maptype);
141 150
142 -extern void space_map_init(void);
143 -extern void space_map_fini(void);
144 -extern void space_map_create(space_map_t *sm, uint64_t start, uint64_t size,
145 - uint8_t shift, kmutex_t *lp);
146 -extern void space_map_destroy(space_map_t *sm);
147 -extern void space_map_add(space_map_t *sm, uint64_t start, uint64_t size);
148 -extern void space_map_remove(space_map_t *sm, uint64_t start, uint64_t size);
149 -extern boolean_t space_map_contains(space_map_t *sm,
150 - uint64_t start, uint64_t size);
151 -extern space_seg_t *space_map_find(space_map_t *sm, uint64_t start,
152 - uint64_t size, avl_index_t *wherep);
153 -extern void space_map_swap(space_map_t **msrc, space_map_t **mdest);
154 -extern void space_map_vacate(space_map_t *sm,
155 - space_map_func_t *func, space_map_t *mdest);
156 -extern void space_map_walk(space_map_t *sm,
157 - space_map_func_t *func, space_map_t *mdest);
151 +void space_map_histogram_clear(space_map_t *sm);
152 +void space_map_histogram_add(space_map_t *sm, range_tree_t *rt,
153 + dmu_tx_t *tx);
158 154
159 -extern void space_map_load_wait(space_map_t *sm);
160 -extern int space_map_load(space_map_t *sm, space_map_ops_t *ops,
161 - uint8_t maptype, space_map_obj_t *smo, objset_t *os);
162 -extern void space_map_unload(space_map_t *sm);
155 +void space_map_update(space_map_t *sm);
163 156
164 -extern uint64_t space_map_alloc(space_map_t *sm, uint64_t size);
165 -extern void space_map_claim(space_map_t *sm, uint64_t start, uint64_t size);
166 -extern void space_map_free(space_map_t *sm, uint64_t start, uint64_t size);
167 -extern uint64_t space_map_maxsize(space_map_t *sm);
157 +uint64_t space_map_object(space_map_t *sm);
158 +uint64_t space_map_allocated(space_map_t *sm);
159 +uint64_t space_map_length(space_map_t *sm);
168 160
169 -extern void space_map_sync(space_map_t *sm, uint8_t maptype,
170 - space_map_obj_t *smo, objset_t *os, dmu_tx_t *tx);
171 -extern void space_map_truncate(space_map_obj_t *smo,
172 - objset_t *os, dmu_tx_t *tx);
161 +void space_map_write(space_map_t *sm, range_tree_t *rt, maptype_t maptype,
162 + dmu_tx_t *tx);
163 +void space_map_truncate(space_map_t *sm, dmu_tx_t *tx);
164 +uint64_t space_map_alloc(objset_t *os, dmu_tx_t *tx);
165 +void space_map_free(space_map_t *sm, dmu_tx_t *tx);
173 166
174 -extern void space_map_ref_create(avl_tree_t *t);
175 -extern void space_map_ref_destroy(avl_tree_t *t);
176 -extern void space_map_ref_add_seg(avl_tree_t *t,
177 - uint64_t start, uint64_t end, int64_t refcnt);
178 -extern void space_map_ref_add_map(avl_tree_t *t,
179 - space_map_t *sm, int64_t refcnt);
180 -extern void space_map_ref_generate_map(avl_tree_t *t,
181 - space_map_t *sm, int64_t minref);
167 +int space_map_open(space_map_t **smp, objset_t *os, uint64_t object,
168 + uint64_t start, uint64_t size, uint8_t shift, kmutex_t *lp);
169 +void space_map_close(space_map_t *sm);
182 170
171 +int64_t space_map_alloc_delta(space_map_t *sm);
172 +
183 173 #ifdef __cplusplus
184 174 }
185 175 #endif
186 176
187 177 #endif /* _SYS_SPACE_MAP_H */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX