dm: Remove unnecessary inlining These two don't really need to be inlined.diff -r1.16 -r1.17 src/sys/dev/dm/dm_dev.c
(tkusumi)
--- src/sys/dev/dm/dm_dev.c 2019/12/15 14:39:42 1.16
+++ src/sys/dev/dm/dm_dev.c 2019/12/31 10:30:30 1.17
@@ -1,405 +1,405 @@ | @@ -1,405 +1,405 @@ | |||
1 | /* $NetBSD: dm_dev.c,v 1.16 2019/12/15 14:39:42 tkusumi Exp $ */ | 1 | /* $NetBSD: dm_dev.c,v 1.17 2019/12/31 10:30:30 tkusumi Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Hamsik. | 8 | * by Adam Hamsik. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | __KERNEL_RCSID(0, "$NetBSD: dm_dev.c,v 1.16 2019/12/15 14:39:42 tkusumi Exp $"); | 32 | __KERNEL_RCSID(0, "$NetBSD: dm_dev.c,v 1.17 2019/12/31 10:30:30 tkusumi Exp $"); | |
33 | 33 | |||
34 | #include <sys/types.h> | 34 | #include <sys/types.h> | |
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/disk.h> | 36 | #include <sys/disk.h> | |
37 | #include <sys/disklabel.h> | 37 | #include <sys/disklabel.h> | |
38 | #include <sys/ioctl.h> | 38 | #include <sys/ioctl.h> | |
39 | #include <sys/ioccom.h> | 39 | #include <sys/ioccom.h> | |
40 | #include <sys/kmem.h> | 40 | #include <sys/kmem.h> | |
41 | 41 | |||
42 | #include "netbsd-dm.h" | 42 | #include "netbsd-dm.h" | |
43 | #include "dm.h" | 43 | #include "dm.h" | |
44 | 44 | |||
45 | static dm_dev_t *dm_dev_lookup_name(const char *); | 45 | static dm_dev_t *dm_dev_lookup_name(const char *); | |
46 | static dm_dev_t *dm_dev_lookup_uuid(const char *); | 46 | static dm_dev_t *dm_dev_lookup_uuid(const char *); | |
47 | static dm_dev_t *dm_dev_lookup_minor(int); | 47 | static dm_dev_t *dm_dev_lookup_minor(int); | |
48 | 48 | |||
49 | static struct dm_dev_head dm_dev_list = TAILQ_HEAD_INITIALIZER(dm_dev_list); | 49 | static struct dm_dev_head dm_dev_list = TAILQ_HEAD_INITIALIZER(dm_dev_list); | |
50 | 50 | |||
51 | static kmutex_t dm_dev_mutex; | 51 | static kmutex_t dm_dev_mutex; | |
52 | 52 | |||
53 | /* dm_dev_mutex must be holdby caller before using disable_dev. */ | 53 | /* dm_dev_mutex must be holdby caller before using disable_dev. */ | |
54 | __inline static void | 54 | static void | |
55 | disable_dev(dm_dev_t *dmv) | 55 | disable_dev(dm_dev_t *dmv) | |
56 | { | 56 | { | |
57 | 57 | |||
58 | TAILQ_REMOVE(&dm_dev_list, dmv, next_devlist); | 58 | TAILQ_REMOVE(&dm_dev_list, dmv, next_devlist); | |
59 | mutex_enter(&dmv->dev_mtx); | 59 | mutex_enter(&dmv->dev_mtx); | |
60 | mutex_exit(&dm_dev_mutex); | 60 | mutex_exit(&dm_dev_mutex); | |
61 | while (dmv->ref_cnt != 0) | 61 | while (dmv->ref_cnt != 0) | |
62 | cv_wait(&dmv->dev_cv, &dmv->dev_mtx); | 62 | cv_wait(&dmv->dev_cv, &dmv->dev_mtx); | |
63 | mutex_exit(&dmv->dev_mtx); | 63 | mutex_exit(&dmv->dev_mtx); | |
64 | } | 64 | } | |
65 | 65 | |||
66 | /* | 66 | /* | |
67 | * Generic function used to lookup dm_dev_t. Calling with dm_dev_name | 67 | * Generic function used to lookup dm_dev_t. Calling with dm_dev_name | |
68 | * and dm_dev_uuid NULL is allowed. | 68 | * and dm_dev_uuid NULL is allowed. | |
69 | */ | 69 | */ | |
70 | dm_dev_t * | 70 | dm_dev_t * | |
71 | dm_dev_lookup(const char *dm_dev_name, const char *dm_dev_uuid, | 71 | dm_dev_lookup(const char *dm_dev_name, const char *dm_dev_uuid, | |
72 | int dm_dev_minor) | 72 | int dm_dev_minor) | |
73 | { | 73 | { | |
74 | dm_dev_t *dmv; | 74 | dm_dev_t *dmv; | |
75 | 75 | |||
76 | mutex_enter(&dm_dev_mutex); | 76 | mutex_enter(&dm_dev_mutex); | |
77 | /* KASSERT(dm_dev_name != NULL && dm_dev_uuid != NULL && dm_dev_minor | 77 | /* KASSERT(dm_dev_name != NULL && dm_dev_uuid != NULL && dm_dev_minor | |
78 | * > 0); */ | 78 | * > 0); */ | |
79 | if (dm_dev_minor > 0) | 79 | if (dm_dev_minor > 0) | |
80 | if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL) { | 80 | if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL) { | |
81 | dm_dev_busy(dmv); | 81 | dm_dev_busy(dmv); | |
82 | mutex_exit(&dm_dev_mutex); | 82 | mutex_exit(&dm_dev_mutex); | |
83 | return dmv; | 83 | return dmv; | |
84 | } | 84 | } | |
85 | if (dm_dev_name != NULL) | 85 | if (dm_dev_name != NULL) | |
86 | if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL) { | 86 | if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL) { | |
87 | dm_dev_busy(dmv); | 87 | dm_dev_busy(dmv); | |
88 | mutex_exit(&dm_dev_mutex); | 88 | mutex_exit(&dm_dev_mutex); | |
89 | return dmv; | 89 | return dmv; | |
90 | } | 90 | } | |
91 | if (dm_dev_uuid != NULL) | 91 | if (dm_dev_uuid != NULL) | |
92 | if ((dmv = dm_dev_lookup_uuid(dm_dev_uuid)) != NULL) { | 92 | if ((dmv = dm_dev_lookup_uuid(dm_dev_uuid)) != NULL) { | |
93 | dm_dev_busy(dmv); | 93 | dm_dev_busy(dmv); | |
94 | mutex_exit(&dm_dev_mutex); | 94 | mutex_exit(&dm_dev_mutex); | |
95 | return dmv; | 95 | return dmv; | |
96 | } | 96 | } | |
97 | mutex_exit(&dm_dev_mutex); | 97 | mutex_exit(&dm_dev_mutex); | |
98 | 98 | |||
99 | return NULL; | 99 | return NULL; | |
100 | } | 100 | } | |
101 | 101 | |||
102 | /* | 102 | /* | |
103 | * Lookup device with its minor number. | 103 | * Lookup device with its minor number. | |
104 | */ | 104 | */ | |
105 | static dm_dev_t * | 105 | static dm_dev_t * | |
106 | dm_dev_lookup_minor(int dm_dev_minor) | 106 | dm_dev_lookup_minor(int dm_dev_minor) | |
107 | { | 107 | { | |
108 | dm_dev_t *dmv; | 108 | dm_dev_t *dmv; | |
109 | 109 | |||
110 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) | 110 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) | |
111 | if (dm_dev_minor == dmv->minor) | 111 | if (dm_dev_minor == dmv->minor) | |
112 | return dmv; | 112 | return dmv; | |
113 | 113 | |||
114 | return NULL; | 114 | return NULL; | |
115 | } | 115 | } | |
116 | 116 | |||
117 | /* | 117 | /* | |
118 | * Lookup device with its device name. | 118 | * Lookup device with its device name. | |
119 | */ | 119 | */ | |
120 | static dm_dev_t * | 120 | static dm_dev_t * | |
121 | dm_dev_lookup_name(const char *dm_dev_name) | 121 | dm_dev_lookup_name(const char *dm_dev_name) | |
122 | { | 122 | { | |
123 | dm_dev_t *dmv; | 123 | dm_dev_t *dmv; | |
124 | size_t dlen; | 124 | size_t dlen; | |
125 | size_t slen; | 125 | size_t slen; | |
126 | 126 | |||
127 | slen = strlen(dm_dev_name); | 127 | slen = strlen(dm_dev_name); | |
128 | 128 | |||
129 | if (slen == 0) | 129 | if (slen == 0) | |
130 | return NULL; | 130 | return NULL; | |
131 | 131 | |||
132 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | 132 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | |
133 | dlen = strlen(dmv->name); | 133 | dlen = strlen(dmv->name); | |
134 | 134 | |||
135 | if (slen != dlen) | 135 | if (slen != dlen) | |
136 | continue; | 136 | continue; | |
137 | 137 | |||
138 | if (strncmp(dm_dev_name, dmv->name, slen) == 0) | 138 | if (strncmp(dm_dev_name, dmv->name, slen) == 0) | |
139 | return dmv; | 139 | return dmv; | |
140 | } | 140 | } | |
141 | 141 | |||
142 | return NULL; | 142 | return NULL; | |
143 | } | 143 | } | |
144 | 144 | |||
145 | /* | 145 | /* | |
146 | * Lookup device with its device uuid. Used mostly by LVM2tools. | 146 | * Lookup device with its device uuid. Used mostly by LVM2tools. | |
147 | */ | 147 | */ | |
148 | static dm_dev_t * | 148 | static dm_dev_t * | |
149 | dm_dev_lookup_uuid(const char *dm_dev_uuid) | 149 | dm_dev_lookup_uuid(const char *dm_dev_uuid) | |
150 | { | 150 | { | |
151 | dm_dev_t *dmv; | 151 | dm_dev_t *dmv; | |
152 | size_t len; | 152 | size_t len; | |
153 | 153 | |||
154 | len = 0; | 154 | len = 0; | |
155 | len = strlen(dm_dev_uuid); | 155 | len = strlen(dm_dev_uuid); | |
156 | 156 | |||
157 | if (len == 0) | 157 | if (len == 0) | |
158 | return NULL; | 158 | return NULL; | |
159 | 159 | |||
160 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | 160 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | |
161 | if (strlen(dmv->uuid) != len) | 161 | if (strlen(dmv->uuid) != len) | |
162 | continue; | 162 | continue; | |
163 | 163 | |||
164 | if (strncmp(dm_dev_uuid, dmv->uuid, strlen(dmv->uuid)) == 0) | 164 | if (strncmp(dm_dev_uuid, dmv->uuid, strlen(dmv->uuid)) == 0) | |
165 | return dmv; | 165 | return dmv; | |
166 | } | 166 | } | |
167 | 167 | |||
168 | return NULL; | 168 | return NULL; | |
169 | } | 169 | } | |
170 | 170 | |||
171 | /* | 171 | /* | |
172 | * Insert new device to the global list of devices. | 172 | * Insert new device to the global list of devices. | |
173 | */ | 173 | */ | |
174 | int | 174 | int | |
175 | dm_dev_insert(dm_dev_t *dev) | 175 | dm_dev_insert(dm_dev_t *dev) | |
176 | { | 176 | { | |
177 | dm_dev_t *dmv; | 177 | dm_dev_t *dmv; | |
178 | int r; | 178 | int r; | |
179 | 179 | |||
180 | dmv = NULL; | 180 | dmv = NULL; | |
181 | r = 0; | 181 | r = 0; | |
182 | 182 | |||
183 | KASSERT(dev != NULL); | 183 | KASSERT(dev != NULL); | |
184 | mutex_enter(&dm_dev_mutex); | 184 | mutex_enter(&dm_dev_mutex); | |
185 | if (((dmv = dm_dev_lookup_uuid(dev->uuid)) == NULL) && | 185 | if (((dmv = dm_dev_lookup_uuid(dev->uuid)) == NULL) && | |
186 | ((dmv = dm_dev_lookup_name(dev->name)) == NULL) && | 186 | ((dmv = dm_dev_lookup_name(dev->name)) == NULL) && | |
187 | ((dmv = dm_dev_lookup_minor(dev->minor)) == NULL)) { | 187 | ((dmv = dm_dev_lookup_minor(dev->minor)) == NULL)) { | |
188 | TAILQ_INSERT_TAIL(&dm_dev_list, dev, next_devlist); | 188 | TAILQ_INSERT_TAIL(&dm_dev_list, dev, next_devlist); | |
189 | } else | 189 | } else | |
190 | r = EEXIST; | 190 | r = EEXIST; | |
191 | mutex_exit(&dm_dev_mutex); | 191 | mutex_exit(&dm_dev_mutex); | |
192 | 192 | |||
193 | return r; | 193 | return r; | |
194 | } | 194 | } | |
195 | 195 | |||
196 | #ifdef notyet | 196 | #ifdef notyet | |
197 | /* | 197 | /* | |
198 | * Lookup device with its minor number. | 198 | * Lookup device with its minor number. | |
199 | */ | 199 | */ | |
200 | int | 200 | int | |
201 | dm_dev_test_minor(int dm_dev_minor) | 201 | dm_dev_test_minor(int dm_dev_minor) | |
202 | { | 202 | { | |
203 | dm_dev_t *dmv; | 203 | dm_dev_t *dmv; | |
204 | 204 | |||
205 | mutex_enter(&dm_dev_mutex); | 205 | mutex_enter(&dm_dev_mutex); | |
206 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | 206 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | |
207 | if (dm_dev_minor == dmv->minor) { | 207 | if (dm_dev_minor == dmv->minor) { | |
208 | mutex_exit(&dm_dev_mutex); | 208 | mutex_exit(&dm_dev_mutex); | |
209 | return 1; | 209 | return 1; | |
210 | } | 210 | } | |
211 | } | 211 | } | |
212 | mutex_exit(&dm_dev_mutex); | 212 | mutex_exit(&dm_dev_mutex); | |
213 | 213 | |||
214 | return 0; | 214 | return 0; | |
215 | } | 215 | } | |
216 | #endif | 216 | #endif | |
217 | 217 | |||
218 | /* | 218 | /* | |
219 | * dm_dev_lookup_devt look for selected device_t. We keep this routine | 219 | * dm_dev_lookup_devt look for selected device_t. We keep this routine | |
220 | * outside of dm_dev_lookup because it is a temporally solution. | 220 | * outside of dm_dev_lookup because it is a temporally solution. | |
221 | * | 221 | * | |
222 | * TODO: This is a hack autoconf should be more flexible. | 222 | * TODO: This is a hack autoconf should be more flexible. | |
223 | */ | 223 | */ | |
224 | dm_dev_t * | 224 | dm_dev_t * | |
225 | dm_dev_detach(device_t devt) | 225 | dm_dev_detach(device_t devt) | |
226 | { | 226 | { | |
227 | dm_dev_t *dmv; | 227 | dm_dev_t *dmv; | |
228 | 228 | |||
229 | mutex_enter(&dm_dev_mutex); | 229 | mutex_enter(&dm_dev_mutex); | |
230 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | 230 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | |
231 | if (devt == dmv->devt) { | 231 | if (devt == dmv->devt) { | |
232 | disable_dev(dmv); | 232 | disable_dev(dmv); | |
233 | return dmv; | 233 | return dmv; | |
234 | } | 234 | } | |
235 | } | 235 | } | |
236 | mutex_exit(&dm_dev_mutex); | 236 | mutex_exit(&dm_dev_mutex); | |
237 | 237 | |||
238 | return NULL; | 238 | return NULL; | |
239 | } | 239 | } | |
240 | 240 | |||
241 | /* | 241 | /* | |
242 | * Remove device selected with dm_dev from global list of devices. | 242 | * Remove device selected with dm_dev from global list of devices. | |
243 | */ | 243 | */ | |
244 | dm_dev_t * | 244 | dm_dev_t * | |
245 | dm_dev_rem(const char *dm_dev_name, const char *dm_dev_uuid, | 245 | dm_dev_rem(const char *dm_dev_name, const char *dm_dev_uuid, | |
246 | int dm_dev_minor) | 246 | int dm_dev_minor) | |
247 | { | 247 | { | |
248 | dm_dev_t *dmv; | 248 | dm_dev_t *dmv; | |
249 | 249 | |||
250 | mutex_enter(&dm_dev_mutex); | 250 | mutex_enter(&dm_dev_mutex); | |
251 | if (dm_dev_minor > 0) | 251 | if (dm_dev_minor > 0) | |
252 | if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL) { | 252 | if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL) { | |
253 | disable_dev(dmv); | 253 | disable_dev(dmv); | |
254 | return dmv; | 254 | return dmv; | |
255 | } | 255 | } | |
256 | if (dm_dev_name != NULL) | 256 | if (dm_dev_name != NULL) | |
257 | if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL) { | 257 | if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL) { | |
258 | disable_dev(dmv); | 258 | disable_dev(dmv); | |
259 | return dmv; | 259 | return dmv; | |
260 | } | 260 | } | |
261 | if (dm_dev_uuid != NULL) | 261 | if (dm_dev_uuid != NULL) | |
262 | if ((dmv = dm_dev_lookup_name(dm_dev_uuid)) != NULL) { | 262 | if ((dmv = dm_dev_lookup_name(dm_dev_uuid)) != NULL) { | |
263 | disable_dev(dmv); | 263 | disable_dev(dmv); | |
264 | return dmv; | 264 | return dmv; | |
265 | } | 265 | } | |
266 | mutex_exit(&dm_dev_mutex); | 266 | mutex_exit(&dm_dev_mutex); | |
267 | 267 | |||
268 | return NULL; | 268 | return NULL; | |
269 | } | 269 | } | |
270 | 270 | |||
271 | /* | 271 | /* | |
272 | * Destroy all devices created in device-mapper. Remove all tables | 272 | * Destroy all devices created in device-mapper. Remove all tables | |
273 | * free all allocated memmory. | 273 | * free all allocated memmory. | |
274 | */ | 274 | */ | |
275 | int | 275 | int | |
276 | dm_dev_destroy(void) | 276 | dm_dev_destroy(void) | |
277 | { | 277 | { | |
278 | dm_dev_t *dmv; | 278 | dm_dev_t *dmv; | |
279 | 279 | |||
280 | mutex_enter(&dm_dev_mutex); | 280 | mutex_enter(&dm_dev_mutex); | |
281 | while (TAILQ_FIRST(&dm_dev_list) != NULL) { | 281 | while (TAILQ_FIRST(&dm_dev_list) != NULL) { | |
282 | dmv = TAILQ_FIRST(&dm_dev_list); | 282 | dmv = TAILQ_FIRST(&dm_dev_list); | |
283 | 283 | |||
284 | TAILQ_REMOVE(&dm_dev_list, TAILQ_FIRST(&dm_dev_list), | 284 | TAILQ_REMOVE(&dm_dev_list, TAILQ_FIRST(&dm_dev_list), | |
285 | next_devlist); | 285 | next_devlist); | |
286 | 286 | |||
287 | mutex_enter(&dmv->dev_mtx); | 287 | mutex_enter(&dmv->dev_mtx); | |
288 | 288 | |||
289 | while (dmv->ref_cnt != 0) | 289 | while (dmv->ref_cnt != 0) | |
290 | cv_wait(&dmv->dev_cv, &dmv->dev_mtx); | 290 | cv_wait(&dmv->dev_cv, &dmv->dev_mtx); | |
291 | 291 | |||
292 | /* Destroy active table first. */ | 292 | /* Destroy active table first. */ | |
293 | dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE); | 293 | dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE); | |
294 | 294 | |||
295 | /* Destroy inactive table if exits, too. */ | 295 | /* Destroy inactive table if exits, too. */ | |
296 | dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE); | 296 | dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE); | |
297 | 297 | |||
298 | dm_table_head_destroy(&dmv->table_head); | 298 | dm_table_head_destroy(&dmv->table_head); | |
299 | 299 | |||
300 | mutex_exit(&dmv->dev_mtx); | 300 | mutex_exit(&dmv->dev_mtx); | |
301 | mutex_destroy(&dmv->dev_mtx); | 301 | mutex_destroy(&dmv->dev_mtx); | |
302 | cv_destroy(&dmv->dev_cv); | 302 | cv_destroy(&dmv->dev_cv); | |
303 | 303 | |||
304 | kmem_free(dmv, sizeof(dm_dev_t)); | 304 | kmem_free(dmv, sizeof(dm_dev_t)); | |
305 | } | 305 | } | |
306 | mutex_exit(&dm_dev_mutex); | 306 | mutex_exit(&dm_dev_mutex); | |
307 | 307 | |||
308 | mutex_destroy(&dm_dev_mutex); | 308 | mutex_destroy(&dm_dev_mutex); | |
309 | return 0; | 309 | return 0; | |
310 | } | 310 | } | |
311 | 311 | |||
312 | /* | 312 | /* | |
313 | * Allocate new device entry. | 313 | * Allocate new device entry. | |
314 | */ | 314 | */ | |
315 | dm_dev_t * | 315 | dm_dev_t * | |
316 | dm_dev_alloc(void) | 316 | dm_dev_alloc(void) | |
317 | { | 317 | { | |
318 | dm_dev_t *dmv; | 318 | dm_dev_t *dmv; | |
319 | 319 | |||
320 | dmv = kmem_zalloc(sizeof(dm_dev_t), KM_SLEEP); | 320 | dmv = kmem_zalloc(sizeof(dm_dev_t), KM_SLEEP); | |
321 | dmv->diskp = kmem_zalloc(sizeof(struct disk), KM_SLEEP); | 321 | dmv->diskp = kmem_zalloc(sizeof(struct disk), KM_SLEEP); | |
322 | return dmv; | 322 | return dmv; | |
323 | } | 323 | } | |
324 | 324 | |||
325 | /* | 325 | /* | |
326 | * Freed device entry. | 326 | * Freed device entry. | |
327 | */ | 327 | */ | |
328 | int | 328 | int | |
329 | dm_dev_free(dm_dev_t *dmv) | 329 | dm_dev_free(dm_dev_t *dmv) | |
330 | { | 330 | { | |
331 | 331 | |||
332 | KASSERT(dmv != NULL); | 332 | KASSERT(dmv != NULL); | |
333 | 333 | |||
334 | mutex_destroy(&dmv->dev_mtx); | 334 | mutex_destroy(&dmv->dev_mtx); | |
335 | mutex_destroy(&dmv->diskp_mtx); | 335 | mutex_destroy(&dmv->diskp_mtx); | |
336 | cv_destroy(&dmv->dev_cv); | 336 | cv_destroy(&dmv->dev_cv); | |
337 | 337 | |||
338 | if (dmv->diskp != NULL) | 338 | if (dmv->diskp != NULL) | |
339 | kmem_free(dmv->diskp, sizeof(struct disk)); | 339 | kmem_free(dmv->diskp, sizeof(struct disk)); | |
340 | 340 | |||
341 | kmem_free(dmv, sizeof(dm_dev_t)); | 341 | kmem_free(dmv, sizeof(dm_dev_t)); | |
342 | 342 | |||
343 | return 0; | 343 | return 0; | |
344 | } | 344 | } | |
345 | 345 | |||
346 | void | 346 | void | |
347 | dm_dev_busy(dm_dev_t *dmv) | 347 | dm_dev_busy(dm_dev_t *dmv) | |
348 | { | 348 | { | |
349 | 349 | |||
350 | mutex_enter(&dmv->dev_mtx); | 350 | mutex_enter(&dmv->dev_mtx); | |
351 | dmv->ref_cnt++; | 351 | dmv->ref_cnt++; | |
352 | mutex_exit(&dmv->dev_mtx); | 352 | mutex_exit(&dmv->dev_mtx); | |
353 | } | 353 | } | |
354 | 354 | |||
355 | void | 355 | void | |
356 | dm_dev_unbusy(dm_dev_t *dmv) | 356 | dm_dev_unbusy(dm_dev_t *dmv) | |
357 | { | 357 | { | |
358 | 358 | |||
359 | KASSERT(dmv->ref_cnt != 0); | 359 | KASSERT(dmv->ref_cnt != 0); | |
360 | 360 | |||
361 | mutex_enter(&dmv->dev_mtx); | 361 | mutex_enter(&dmv->dev_mtx); | |
362 | if (--dmv->ref_cnt == 0) | 362 | if (--dmv->ref_cnt == 0) | |
363 | cv_broadcast(&dmv->dev_cv); | 363 | cv_broadcast(&dmv->dev_cv); | |
364 | mutex_exit(&dmv->dev_mtx); | 364 | mutex_exit(&dmv->dev_mtx); | |
365 | } | 365 | } | |
366 | 366 | |||
367 | /* | 367 | /* | |
368 | * Return prop_array of dm_targer_list dictionaries. | 368 | * Return prop_array of dm_targer_list dictionaries. | |
369 | */ | 369 | */ | |
370 | prop_array_t | 370 | prop_array_t | |
371 | dm_dev_prop_list(void) | 371 | dm_dev_prop_list(void) | |
372 | { | 372 | { | |
373 | dm_dev_t *dmv; | 373 | dm_dev_t *dmv; | |
374 | prop_array_t dev_array; | 374 | prop_array_t dev_array; | |
375 | prop_dictionary_t dev_dict; | 375 | prop_dictionary_t dev_dict; | |
376 | 376 | |||
377 | dev_array = prop_array_create(); | 377 | dev_array = prop_array_create(); | |
378 | 378 | |||
379 | mutex_enter(&dm_dev_mutex); | 379 | mutex_enter(&dm_dev_mutex); | |
380 | 380 | |||
381 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | 381 | TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist) { | |
382 | dev_dict = prop_dictionary_create(); | 382 | dev_dict = prop_dictionary_create(); | |
383 | 383 | |||
384 | prop_dictionary_set_cstring(dev_dict, DM_DEV_NAME, dmv->name); | 384 | prop_dictionary_set_cstring(dev_dict, DM_DEV_NAME, dmv->name); | |
385 | prop_dictionary_set_uint32(dev_dict, DM_DEV_DEV, dmv->minor); | 385 | prop_dictionary_set_uint32(dev_dict, DM_DEV_DEV, dmv->minor); | |
386 | 386 | |||
387 | prop_array_add(dev_array, dev_dict); | 387 | prop_array_add(dev_array, dev_dict); | |
388 | prop_object_release(dev_dict); | 388 | prop_object_release(dev_dict); | |
389 | } | 389 | } | |
390 | 390 | |||
391 | mutex_exit(&dm_dev_mutex); | 391 | mutex_exit(&dm_dev_mutex); | |
392 | return dev_array; | 392 | return dev_array; | |
393 | } | 393 | } | |
394 | 394 | |||
395 | /* | 395 | /* | |
396 | * Initialize global device mutex. | 396 | * Initialize global device mutex. | |
397 | */ | 397 | */ | |
398 | int | 398 | int | |
399 | dm_dev_init(void) | 399 | dm_dev_init(void) | |
400 | { | 400 | { | |
401 | 401 | |||
402 | TAILQ_INIT(&dm_dev_list); /* initialize global dev list */ | 402 | TAILQ_INIT(&dm_dev_list); /* initialize global dev list */ | |
403 | mutex_init(&dm_dev_mutex, MUTEX_DEFAULT, IPL_NONE); | 403 | mutex_init(&dm_dev_mutex, MUTEX_DEFAULT, IPL_NONE); | |
404 | return 0; | 404 | return 0; | |
405 | } | 405 | } |
--- src/sys/dev/dm/dm_table.c 2019/12/22 13:16:09 1.18
+++ src/sys/dev/dm/dm_table.c 2019/12/31 10:30:30 1.19
@@ -1,379 +1,379 @@ | @@ -1,379 +1,379 @@ | |||
1 | /* $NetBSD: dm_table.c,v 1.18 2019/12/22 13:16:09 tkusumi Exp $ */ | 1 | /* $NetBSD: dm_table.c,v 1.19 2019/12/31 10:30:30 tkusumi Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Hamsik. | 8 | * by Adam Hamsik. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | __KERNEL_RCSID(0, "$NetBSD: dm_table.c,v 1.18 2019/12/22 13:16:09 tkusumi Exp $"); | 32 | __KERNEL_RCSID(0, "$NetBSD: dm_table.c,v 1.19 2019/12/31 10:30:30 tkusumi Exp $"); | |
33 | 33 | |||
34 | #include <sys/types.h> | 34 | #include <sys/types.h> | |
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/kmem.h> | 36 | #include <sys/kmem.h> | |
37 | 37 | |||
38 | #include "dm.h" | 38 | #include "dm.h" | |
39 | 39 | |||
40 | /* | 40 | /* | |
41 | * There are two types of users of this interface: | 41 | * There are two types of users of this interface: | |
42 | * | 42 | * | |
43 | * a) Readers such as | 43 | * a) Readers such as | |
44 | * dmstrategy, dmgetdisklabel, dmsize, dm_dev_status_ioctl, | 44 | * dmstrategy, dmgetdisklabel, dmsize, dm_dev_status_ioctl, | |
45 | * dm_table_deps_ioctl, dm_table_status_ioctl, dm_table_reload_ioctl | 45 | * dm_table_deps_ioctl, dm_table_status_ioctl, dm_table_reload_ioctl | |
46 | * | 46 | * | |
47 | * b) Writers such as | 47 | * b) Writers such as | |
48 | * dm_dev_remove_ioctl, dm_dev_resume_ioctl, dm_table_clear_ioctl | 48 | * dm_dev_remove_ioctl, dm_dev_resume_ioctl, dm_table_clear_ioctl | |
49 | * | 49 | * | |
50 | * Writers can work with table_head only when there are no readers. I | 50 | * Writers can work with table_head only when there are no readers. I | |
51 | * use reference counting on io_cnt. | 51 | * use reference counting on io_cnt. | |
52 | * | 52 | * | |
53 | */ | 53 | */ | |
54 | 54 | |||
55 | static int dm_table_busy(dm_table_head_t *, uint8_t); | 55 | static int dm_table_busy(dm_table_head_t *, uint8_t); | |
56 | static void dm_table_unbusy(dm_table_head_t *); | 56 | static void dm_table_unbusy(dm_table_head_t *); | |
57 | static void dm_table_free_deps(dm_table_entry_t *); | 57 | static void dm_table_free_deps(dm_table_entry_t *); | |
58 | 58 | |||
59 | 59 | |||
60 | /* | 60 | /* | |
61 | * Function to increment table user reference counter. Return id | 61 | * Function to increment table user reference counter. Return id | |
62 | * of table_id table. | 62 | * of table_id table. | |
63 | * DM_TABLE_ACTIVE will return active table id. | 63 | * DM_TABLE_ACTIVE will return active table id. | |
64 | * DM_TABLE_INACTIVE will return inactive table id. | 64 | * DM_TABLE_INACTIVE will return inactive table id. | |
65 | */ | 65 | */ | |
66 | static int | 66 | static int | |
67 | dm_table_busy(dm_table_head_t *head, uint8_t table_id) | 67 | dm_table_busy(dm_table_head_t *head, uint8_t table_id) | |
68 | { | 68 | { | |
69 | uint8_t id; | 69 | uint8_t id; | |
70 | 70 | |||
71 | mutex_enter(&head->table_mtx); | 71 | mutex_enter(&head->table_mtx); | |
72 | 72 | |||
73 | if (table_id == DM_TABLE_ACTIVE) | 73 | if (table_id == DM_TABLE_ACTIVE) | |
74 | id = head->cur_active_table; | 74 | id = head->cur_active_table; | |
75 | else | 75 | else | |
76 | id = 1 - head->cur_active_table; | 76 | id = 1 - head->cur_active_table; | |
77 | 77 | |||
78 | head->io_cnt++; | 78 | head->io_cnt++; | |
79 | 79 | |||
80 | mutex_exit(&head->table_mtx); | 80 | mutex_exit(&head->table_mtx); | |
81 | return id; | 81 | return id; | |
82 | } | 82 | } | |
83 | 83 | |||
84 | /* | 84 | /* | |
85 | * Function release table lock and eventually wakeup all waiters. | 85 | * Function release table lock and eventually wakeup all waiters. | |
86 | */ | 86 | */ | |
87 | static void | 87 | static void | |
88 | dm_table_unbusy(dm_table_head_t *head) | 88 | dm_table_unbusy(dm_table_head_t *head) | |
89 | { | 89 | { | |
90 | 90 | |||
91 | KASSERT(head->io_cnt != 0); | 91 | KASSERT(head->io_cnt != 0); | |
92 | 92 | |||
93 | mutex_enter(&head->table_mtx); | 93 | mutex_enter(&head->table_mtx); | |
94 | 94 | |||
95 | if (--head->io_cnt == 0) | 95 | if (--head->io_cnt == 0) | |
96 | cv_broadcast(&head->table_cv); | 96 | cv_broadcast(&head->table_cv); | |
97 | 97 | |||
98 | mutex_exit(&head->table_mtx); | 98 | mutex_exit(&head->table_mtx); | |
99 | } | 99 | } | |
100 | 100 | |||
101 | /* | 101 | /* | |
102 | * Return current active table to caller, increment io_cnt reference counter. | 102 | * Return current active table to caller, increment io_cnt reference counter. | |
103 | */ | 103 | */ | |
104 | dm_table_t * | 104 | dm_table_t * | |
105 | dm_table_get_entry(dm_table_head_t *head, uint8_t table_id) | 105 | dm_table_get_entry(dm_table_head_t *head, uint8_t table_id) | |
106 | { | 106 | { | |
107 | uint8_t id; | 107 | uint8_t id; | |
108 | 108 | |||
109 | id = dm_table_busy(head, table_id); | 109 | id = dm_table_busy(head, table_id); | |
110 | 110 | |||
111 | return &head->tables[id]; | 111 | return &head->tables[id]; | |
112 | } | 112 | } | |
113 | /* | 113 | /* | |
114 | * Decrement io reference counter and wake up all callers, with table_head cv. | 114 | * Decrement io reference counter and wake up all callers, with table_head cv. | |
115 | */ | 115 | */ | |
116 | void | 116 | void | |
117 | dm_table_release(dm_table_head_t *head, uint8_t table_id) | 117 | dm_table_release(dm_table_head_t *head, uint8_t table_id) | |
118 | { | 118 | { | |
119 | 119 | |||
120 | dm_table_unbusy(head); | 120 | dm_table_unbusy(head); | |
121 | } | 121 | } | |
122 | 122 | |||
123 | /* | 123 | /* | |
124 | * Switch table from inactive to active mode. Have to wait until io_cnt is 0. | 124 | * Switch table from inactive to active mode. Have to wait until io_cnt is 0. | |
125 | */ | 125 | */ | |
126 | void | 126 | void | |
127 | dm_table_switch_tables(dm_table_head_t *head) | 127 | dm_table_switch_tables(dm_table_head_t *head) | |
128 | { | 128 | { | |
129 | 129 | |||
130 | mutex_enter(&head->table_mtx); | 130 | mutex_enter(&head->table_mtx); | |
131 | 131 | |||
132 | while (head->io_cnt != 0) | 132 | while (head->io_cnt != 0) | |
133 | cv_wait(&head->table_cv, &head->table_mtx); | 133 | cv_wait(&head->table_cv, &head->table_mtx); | |
134 | 134 | |||
135 | head->cur_active_table = 1 - head->cur_active_table; | 135 | head->cur_active_table = 1 - head->cur_active_table; | |
136 | 136 | |||
137 | mutex_exit(&head->table_mtx); | 137 | mutex_exit(&head->table_mtx); | |
138 | } | 138 | } | |
139 | 139 | |||
140 | /* | 140 | /* | |
141 | * Destroy all table data. This function can run when there are no | 141 | * Destroy all table data. This function can run when there are no | |
142 | * readers on table lists. | 142 | * readers on table lists. | |
143 | * | 143 | * | |
144 | * XXX Is it ok to call kmem_free and potentialy VOP_CLOSE with held mutex ?xs | 144 | * XXX Is it ok to call kmem_free and potentialy VOP_CLOSE with held mutex ?xs | |
145 | */ | 145 | */ | |
146 | int | 146 | int | |
147 | dm_table_destroy(dm_table_head_t *head, uint8_t table_id) | 147 | dm_table_destroy(dm_table_head_t *head, uint8_t table_id) | |
148 | { | 148 | { | |
149 | dm_table_t *tbl; | 149 | dm_table_t *tbl; | |
150 | dm_table_entry_t *table_en; | 150 | dm_table_entry_t *table_en; | |
151 | uint8_t id; | 151 | uint8_t id; | |
152 | 152 | |||
153 | mutex_enter(&head->table_mtx); | 153 | mutex_enter(&head->table_mtx); | |
154 | 154 | |||
155 | aprint_debug("dm_Table_destroy called with %d--%d\n", table_id, head->io_cnt); | 155 | aprint_debug("dm_Table_destroy called with %d--%d\n", table_id, head->io_cnt); | |
156 | 156 | |||
157 | while (head->io_cnt != 0) | 157 | while (head->io_cnt != 0) | |
158 | cv_wait(&head->table_cv, &head->table_mtx); | 158 | cv_wait(&head->table_cv, &head->table_mtx); | |
159 | 159 | |||
160 | if (table_id == DM_TABLE_ACTIVE) | 160 | if (table_id == DM_TABLE_ACTIVE) | |
161 | id = head->cur_active_table; | 161 | id = head->cur_active_table; | |
162 | else | 162 | else | |
163 | id = 1 - head->cur_active_table; | 163 | id = 1 - head->cur_active_table; | |
164 | 164 | |||
165 | tbl = &head->tables[id]; | 165 | tbl = &head->tables[id]; | |
166 | 166 | |||
167 | while ((table_en = SLIST_FIRST(tbl)) != NULL) { | 167 | while ((table_en = SLIST_FIRST(tbl)) != NULL) { | |
168 | SLIST_REMOVE(tbl, table_en, dm_table_entry, next); | 168 | SLIST_REMOVE(tbl, table_en, dm_table_entry, next); | |
169 | if (table_en->target->destroy(table_en) == 0) | 169 | if (table_en->target->destroy(table_en) == 0) | |
170 | table_en->target_config = NULL; | 170 | table_en->target_config = NULL; | |
171 | dm_table_free_deps(table_en); | 171 | dm_table_free_deps(table_en); | |
172 | kmem_free(table_en, sizeof(*table_en)); | 172 | kmem_free(table_en, sizeof(*table_en)); | |
173 | } | 173 | } | |
174 | KASSERT(SLIST_EMPTY(tbl)); | 174 | KASSERT(SLIST_EMPTY(tbl)); | |
175 | 175 | |||
176 | mutex_exit(&head->table_mtx); | 176 | mutex_exit(&head->table_mtx); | |
177 | 177 | |||
178 | return 0; | 178 | return 0; | |
179 | } | 179 | } | |
180 | 180 | |||
181 | /* | 181 | /* | |
182 | * Return length of active table in device. | 182 | * Return length of active table in device. | |
183 | */ | 183 | */ | |
184 | static inline uint64_t | 184 | static uint64_t | |
185 | dm_table_size_impl(dm_table_head_t *head, int table) | 185 | dm_table_size_impl(dm_table_head_t *head, int table) | |
186 | { | 186 | { | |
187 | dm_table_t *tbl; | 187 | dm_table_t *tbl; | |
188 | dm_table_entry_t *table_en; | 188 | dm_table_entry_t *table_en; | |
189 | uint64_t length; | 189 | uint64_t length; | |
190 | uint8_t id; | 190 | uint8_t id; | |
191 | 191 | |||
192 | length = 0; | 192 | length = 0; | |
193 | 193 | |||
194 | id = dm_table_busy(head, table); | 194 | id = dm_table_busy(head, table); | |
195 | 195 | |||
196 | /* Select active table */ | 196 | /* Select active table */ | |
197 | tbl = &head->tables[id]; | 197 | tbl = &head->tables[id]; | |
198 | 198 | |||
199 | /* | 199 | /* | |
200 | * Find out what tables I want to select. | 200 | * Find out what tables I want to select. | |
201 | * if length => rawblkno then we should used that table. | 201 | * if length => rawblkno then we should used that table. | |
202 | */ | 202 | */ | |
203 | SLIST_FOREACH(table_en, tbl, next) | 203 | SLIST_FOREACH(table_en, tbl, next) | |
204 | length += table_en->length; | 204 | length += table_en->length; | |
205 | 205 | |||
206 | dm_table_unbusy(head); | 206 | dm_table_unbusy(head); | |
207 | 207 | |||
208 | return length; | 208 | return length; | |
209 | } | 209 | } | |
210 | 210 | |||
211 | /* | 211 | /* | |
212 | * Return length of active table in device. | 212 | * Return length of active table in device. | |
213 | */ | 213 | */ | |
214 | uint64_t | 214 | uint64_t | |
215 | dm_table_size(dm_table_head_t *head) | 215 | dm_table_size(dm_table_head_t *head) | |
216 | { | 216 | { | |
217 | 217 | |||
218 | return dm_table_size_impl(head, DM_TABLE_ACTIVE); | 218 | return dm_table_size_impl(head, DM_TABLE_ACTIVE); | |
219 | } | 219 | } | |
220 | 220 | |||
221 | /* | 221 | /* | |
222 | * Return length of active table in device. | 222 | * Return length of active table in device. | |
223 | */ | 223 | */ | |
224 | uint64_t | 224 | uint64_t | |
225 | dm_inactive_table_size(dm_table_head_t *head) | 225 | dm_inactive_table_size(dm_table_head_t *head) | |
226 | { | 226 | { | |
227 | 227 | |||
228 | return dm_table_size_impl(head, DM_TABLE_INACTIVE); | 228 | return dm_table_size_impl(head, DM_TABLE_INACTIVE); | |
229 | } | 229 | } | |
230 | 230 | |||
231 | /* | 231 | /* | |
232 | * Return combined disk geometry | 232 | * Return combined disk geometry | |
233 | */ | 233 | */ | |
234 | void | 234 | void | |
235 | dm_table_disksize(dm_table_head_t *head, uint64_t *numsecp, | 235 | dm_table_disksize(dm_table_head_t *head, uint64_t *numsecp, | |
236 | unsigned int *secsizep) | 236 | unsigned int *secsizep) | |
237 | { | 237 | { | |
238 | dm_table_t *tbl; | 238 | dm_table_t *tbl; | |
239 | dm_table_entry_t *table_en; | 239 | dm_table_entry_t *table_en; | |
240 | uint64_t length; | 240 | uint64_t length; | |
241 | unsigned int secsize, tsecsize; | 241 | unsigned int secsize, tsecsize; | |
242 | uint8_t id; | 242 | uint8_t id; | |
243 | 243 | |||
244 | length = 0; | 244 | length = 0; | |
245 | 245 | |||
246 | id = dm_table_busy(head, DM_TABLE_ACTIVE); | 246 | id = dm_table_busy(head, DM_TABLE_ACTIVE); | |
247 | 247 | |||
248 | /* Select active table */ | 248 | /* Select active table */ | |
249 | tbl = &head->tables[id]; | 249 | tbl = &head->tables[id]; | |
250 | 250 | |||
251 | /* | 251 | /* | |
252 | * Find out what tables I want to select. | 252 | * Find out what tables I want to select. | |
253 | * if length => rawblkno then we should used that table. | 253 | * if length => rawblkno then we should used that table. | |
254 | */ | 254 | */ | |
255 | secsize = 0; | 255 | secsize = 0; | |
256 | SLIST_FOREACH(table_en, tbl, next) { | 256 | SLIST_FOREACH(table_en, tbl, next) { | |
257 | length += table_en->length; | 257 | length += table_en->length; | |
258 | if (table_en->target->secsize) | 258 | if (table_en->target->secsize) | |
259 | table_en->target->secsize(table_en, &tsecsize); | 259 | table_en->target->secsize(table_en, &tsecsize); | |
260 | else | 260 | else | |
261 | tsecsize = 0; | 261 | tsecsize = 0; | |
262 | if (secsize < tsecsize) | 262 | if (secsize < tsecsize) | |
263 | secsize = tsecsize; | 263 | secsize = tsecsize; | |
264 | } | 264 | } | |
265 | 265 | |||
266 | if (numsecp) | 266 | if (numsecp) | |
267 | *numsecp = secsize > 0 ? dbtob(length) / secsize : 0; | 267 | *numsecp = secsize > 0 ? dbtob(length) / secsize : 0; | |
268 | if (secsizep) | 268 | if (secsizep) | |
269 | *secsizep = secsize; | 269 | *secsizep = secsize; | |
270 | 270 | |||
271 | dm_table_unbusy(head); | 271 | dm_table_unbusy(head); | |
272 | } | 272 | } | |
273 | 273 | |||
274 | /* | 274 | /* | |
275 | * Return > 0 if table is at least one table entry (returns number of entries) | 275 | * Return > 0 if table is at least one table entry (returns number of entries) | |
276 | * and return 0 if there is not. Target count returned from this function | 276 | * and return 0 if there is not. Target count returned from this function | |
277 | * doesn't need to be true when userspace user receive it (after return | 277 | * doesn't need to be true when userspace user receive it (after return | |
278 | * there can be dm_dev_resume_ioctl), therfore this isonly informative. | 278 | * there can be dm_dev_resume_ioctl), therfore this isonly informative. | |
279 | */ | 279 | */ | |
280 | int | 280 | int | |
281 | dm_table_get_target_count(dm_table_head_t *head, uint8_t table_id) | 281 | dm_table_get_target_count(dm_table_head_t *head, uint8_t table_id) | |
282 | { | 282 | { | |
283 | dm_table_entry_t *table_en; | 283 | dm_table_entry_t *table_en; | |
284 | dm_table_t *tbl; | 284 | dm_table_t *tbl; | |
285 | uint32_t target_count; | 285 | uint32_t target_count; | |
286 | uint8_t id; | 286 | uint8_t id; | |
287 | 287 | |||
288 | target_count = 0; | 288 | target_count = 0; | |
289 | 289 | |||
290 | id = dm_table_busy(head, table_id); | 290 | id = dm_table_busy(head, table_id); | |
291 | tbl = &head->tables[id]; | 291 | tbl = &head->tables[id]; | |
292 | 292 | |||
293 | SLIST_FOREACH(table_en, tbl, next) | 293 | SLIST_FOREACH(table_en, tbl, next) | |
294 | target_count++; | 294 | target_count++; | |
295 | 295 | |||
296 | dm_table_unbusy(head); | 296 | dm_table_unbusy(head); | |
297 | 297 | |||
298 | return target_count; | 298 | return target_count; | |
299 | } | 299 | } | |
300 | 300 | |||
301 | /* | 301 | /* | |
302 | * Initialize table_head structures, I'm trying to keep this structure as | 302 | * Initialize table_head structures, I'm trying to keep this structure as | |
303 | * opaque as possible. | 303 | * opaque as possible. | |
304 | */ | 304 | */ | |
305 | void | 305 | void | |
306 | dm_table_head_init(dm_table_head_t *head) | 306 | dm_table_head_init(dm_table_head_t *head) | |
307 | { | 307 | { | |
308 | 308 | |||
309 | head->cur_active_table = 0; | 309 | head->cur_active_table = 0; | |
310 | head->io_cnt = 0; | 310 | head->io_cnt = 0; | |
311 | 311 | |||
312 | /* Initialize tables. */ | 312 | /* Initialize tables. */ | |
313 | SLIST_INIT(&head->tables[0]); | 313 | SLIST_INIT(&head->tables[0]); | |
314 | SLIST_INIT(&head->tables[1]); | 314 | SLIST_INIT(&head->tables[1]); | |
315 | 315 | |||
316 | mutex_init(&head->table_mtx, MUTEX_DEFAULT, IPL_NONE); | 316 | mutex_init(&head->table_mtx, MUTEX_DEFAULT, IPL_NONE); | |
317 | cv_init(&head->table_cv, "dm_io"); | 317 | cv_init(&head->table_cv, "dm_io"); | |
318 | } | 318 | } | |
319 | 319 | |||
320 | /* | 320 | /* | |
321 | * Destroy all variables in table_head | 321 | * Destroy all variables in table_head | |
322 | */ | 322 | */ | |
323 | void | 323 | void | |
324 | dm_table_head_destroy(dm_table_head_t *head) | 324 | dm_table_head_destroy(dm_table_head_t *head) | |
325 | { | 325 | { | |
326 | 326 | |||
327 | KASSERT(!mutex_owned(&head->table_mtx)); | 327 | KASSERT(!mutex_owned(&head->table_mtx)); | |
328 | KASSERT(!cv_has_waiters(&head->table_cv)); | 328 | KASSERT(!cv_has_waiters(&head->table_cv)); | |
329 | /* tables doens't exists when I call this routine, therefore it | 329 | /* tables doens't exists when I call this routine, therefore it | |
330 | * doesn't make sense to have io_cnt != 0 */ | 330 | * doesn't make sense to have io_cnt != 0 */ | |
331 | KASSERT(head->io_cnt == 0); | 331 | KASSERT(head->io_cnt == 0); | |
332 | 332 | |||
333 | cv_destroy(&head->table_cv); | 333 | cv_destroy(&head->table_cv); | |
334 | mutex_destroy(&head->table_mtx); | 334 | mutex_destroy(&head->table_mtx); | |
335 | } | 335 | } | |
336 | 336 | |||
337 | int | 337 | int | |
338 | dm_table_add_deps(dm_table_entry_t *table_en, dm_pdev_t *pdev) | 338 | dm_table_add_deps(dm_table_entry_t *table_en, dm_pdev_t *pdev) | |
339 | { | 339 | { | |
340 | dm_table_head_t *head; | 340 | dm_table_head_t *head; | |
341 | dm_mapping_t *map; | 341 | dm_mapping_t *map; | |
342 | 342 | |||
343 | if (!pdev) | 343 | if (!pdev) | |
344 | return -1; | 344 | return -1; | |
345 | 345 | |||
346 | head = &table_en->dm_dev->table_head; | 346 | head = &table_en->dm_dev->table_head; | |
347 | mutex_enter(&head->table_mtx); | 347 | mutex_enter(&head->table_mtx); | |
348 | 348 | |||
349 | TAILQ_FOREACH(map, &table_en->pdev_maps, next) { | 349 | TAILQ_FOREACH(map, &table_en->pdev_maps, next) { | |
350 | if (map->data.pdev->pdev_vnode->v_rdev == | 350 | if (map->data.pdev->pdev_vnode->v_rdev == | |
351 | pdev->pdev_vnode->v_rdev) { | 351 | pdev->pdev_vnode->v_rdev) { | |
352 | mutex_exit(&head->table_mtx); | 352 | mutex_exit(&head->table_mtx); | |
353 | return -1; | 353 | return -1; | |
354 | } | 354 | } | |
355 | } | 355 | } | |
356 | 356 | |||
357 | map = kmem_alloc(sizeof(*map), KM_SLEEP); | 357 | map = kmem_alloc(sizeof(*map), KM_SLEEP); | |
358 | map->data.pdev = pdev; | 358 | map->data.pdev = pdev; | |
359 | aprint_debug("%s: %s\n", __func__, pdev->name); | 359 | aprint_debug("%s: %s\n", __func__, pdev->name); | |
360 | TAILQ_INSERT_TAIL(&table_en->pdev_maps, map, next); | 360 | TAILQ_INSERT_TAIL(&table_en->pdev_maps, map, next); | |
361 | 361 | |||
362 | mutex_exit(&head->table_mtx); | 362 | mutex_exit(&head->table_mtx); | |
363 | 363 | |||
364 | return 0; | 364 | return 0; | |
365 | } | 365 | } | |
366 | 366 | |||
367 | /* caller must hold ->table_mtx */ | 367 | /* caller must hold ->table_mtx */ | |
368 | static void | 368 | static void | |
369 | dm_table_free_deps(dm_table_entry_t *table_en) | 369 | dm_table_free_deps(dm_table_entry_t *table_en) | |
370 | { | 370 | { | |
371 | dm_mapping_t *map; | 371 | dm_mapping_t *map; | |
372 | 372 | |||
373 | while ((map = TAILQ_FIRST(&table_en->pdev_maps)) != NULL) { | 373 | while ((map = TAILQ_FIRST(&table_en->pdev_maps)) != NULL) { | |
374 | TAILQ_REMOVE(&table_en->pdev_maps, map, next); | 374 | TAILQ_REMOVE(&table_en->pdev_maps, map, next); | |
375 | aprint_debug("%s: %s\n", __func__, map->data.pdev->name); | 375 | aprint_debug("%s: %s\n", __func__, map->data.pdev->name); | |
376 | kmem_free(map, sizeof(*map)); | 376 | kmem_free(map, sizeof(*map)); | |
377 | } | 377 | } | |
378 | KASSERT(TAILQ_EMPTY(&table_en->pdev_maps)); | 378 | KASSERT(TAILQ_EMPTY(&table_en->pdev_maps)); | |
379 | } | 379 | } |