dm_dev.c revision 1.1.2.10 1 /* $NetBSD: dm_dev.c,v 1.1.2.10 2008/09/26 22:57:13 haad Exp $ */
2
3 /*
4 * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Adam Hamsik.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
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
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35
36 #include <sys/disklabel.h>
37 #include <sys/errno.h>
38 #include <sys/ioctl.h>
39 #include <sys/ioccom.h>
40 #include <sys/kmem.h>
41 #include <sys/lkm.h>
42 #include <sys/queue.h>
43
44 #include "netbsd-dm.h"
45 #include "dm.h"
46
47 static struct dm_dev* dm_dev_lookup_name(const char *);
48 static struct dm_dev* dm_dev_lookup_uuid(const char *);
49 static struct dm_dev* dm_dev_lookup_minor(int);
50
51 static struct dm_dev_head dm_dev_list =
52 TAILQ_HEAD_INITIALIZER(dm_dev_list);
53
54 kmutex_t dm_dev_mutex;
55
56 /*
57 * Locking architecture, for now I use mutexes later we can convert them to
58 * rw_locks. I use IPL_NONE for specifing IPL type for mutex.
59 * I will enter into mutex everytime I'm working with dm_dev_list.
60 */
61
62 /*
63 * Generic function used to lookup struct dm_dev. Calling with dm_dev_name
64 * and dm_dev_uuid NULL is allowed.
65 */
66 struct dm_dev*
67 dm_dev_lookup(const char *dm_dev_name, const char *dm_dev_uuid,
68 int dm_dev_minor)
69 {
70 struct dm_dev *dmv;
71
72 dmv = NULL;
73
74 if (dm_dev_minor > 0)
75 if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL)
76 return dmv;
77
78 if (dm_dev_name != NULL)
79 if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL)
80 return dmv;
81
82 if (dm_dev_uuid != NULL)
83 if ((dmv = dm_dev_lookup_name(dm_dev_uuid)) != NULL)
84 return dmv;
85
86 return NULL;
87 }
88
89
90 /*
91 * Lookup device with its minor number.
92 */
93 static struct dm_dev*
94 dm_dev_lookup_minor(int dm_dev_minor)
95 {
96 struct dm_dev *dm_dev;
97
98 mutex_enter(&dm_dev_mutex);
99
100 TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
101 if (dm_dev_minor == dm_dev->minor){
102 mutex_exit(&dm_dev_mutex);
103 return dm_dev;
104 }
105 }
106
107 mutex_exit(&dm_dev_mutex);
108
109 return NULL;
110 }
111
112 /*
113 * Lookup device with it's device name.
114 */
115 static struct dm_dev*
116 dm_dev_lookup_name(const char *dm_dev_name)
117 {
118 struct dm_dev *dm_dev;
119 int dlen; int slen;
120
121 slen = strlen(dm_dev_name);
122
123 if (slen == 0)
124 return NULL;
125
126 mutex_enter(&dm_dev_mutex);
127
128 TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
129
130 dlen = strlen(dm_dev->name);
131
132 if(slen != dlen)
133 continue;
134
135 if (strncmp(dm_dev_name, dm_dev->name, slen) == 0) {
136 mutex_exit(&dm_dev_mutex);
137 return dm_dev;
138 }
139 }
140
141 mutex_exit(&dm_dev_mutex);
142
143 return NULL;
144 }
145
146 /*
147 * Lookup device with it's device uuid. Used mostly by LVM2tools.
148 */
149 static struct dm_dev*
150 dm_dev_lookup_uuid(const char *dm_dev_uuid)
151 {
152 struct dm_dev *dm_dev;
153 size_t len;
154
155 len = 0;
156
157 len = strlen(dm_dev_uuid);
158
159 if (len == 0)
160 return NULL;
161
162 mutex_enter(&dm_dev_mutex);
163
164 TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
165
166 if (strlen(dm_dev->uuid) != len)
167 continue;
168
169 if (strncmp(dm_dev_uuid, dm_dev->uuid, strlen(dm_dev->uuid)) == 0){
170 mutex_exit(&dm_dev_mutex);
171 return dm_dev;
172 }
173 }
174 mutex_exit(&dm_dev_mutex);
175
176 return NULL;
177 }
178
179 /*
180 * Insert new device to the global list of devices.
181 */
182 int
183 dm_dev_insert(struct dm_dev *dev)
184 {
185 struct dm_dev *dmt;
186 int r;
187
188 dmt = NULL;
189 r = 0;
190
191 if (((dmt = dm_dev_lookup_uuid(dev->uuid)) == NULL) &&
192 ((dmt = dm_dev_lookup_name(dev->name)) == NULL) &&
193 ((dmt = dm_dev_lookup_minor(dev->minor)) == NULL)){
194
195 mutex_enter(&dm_dev_mutex);
196 TAILQ_INSERT_TAIL(&dm_dev_list, dev, next_devlist);
197 mutex_exit(&dm_dev_mutex);
198 } else
199 r = EEXIST;
200
201 return r;
202 }
203
204
205 /*
206 * Remove device selected with dm_dev from global list of devices.
207 */
208 int
209 dm_dev_rem(struct dm_dev *dm_dev)
210 {
211 mutex_enter(&dm_dev_mutex);
212
213 TAILQ_REMOVE(&dm_dev_list, dm_dev, next_devlist);
214
215 mutex_exit(&dm_dev_mutex);
216
217 return 0;
218 }
219
220 /*
221 * Destroy all devices created in device-mapper. Remove all tables
222 * free all allocated memmory.
223 */
224
225 int
226 dm_dev_destroy(void)
227 {
228 struct dm_dev *dm_dev;
229
230 /* XXX should I get rw_lock here ? */
231 mutex_enter(&dm_dev_mutex);
232
233 while (TAILQ_FIRST(&dm_dev_list) != NULL){
234
235 dm_dev = TAILQ_FIRST(&dm_dev_list);
236
237 TAILQ_REMOVE(&dm_dev_list, TAILQ_FIRST(&dm_dev_list),
238 next_devlist);
239
240 rw_enter(&dm_dev->dev_rwlock, RW_WRITER);
241
242 /* Destroy active table first. */
243 if (!SLIST_EMPTY(&dm_dev->tables[dm_dev->cur_active_table]))
244 dm_table_destroy(&dm_dev->tables[dm_dev->cur_active_table]);
245
246 /* Destroy unactive table if exits, too. */
247 if (!SLIST_EMPTY(&dm_dev->tables[1 - dm_dev->cur_active_table]))
248 dm_table_destroy(&dm_dev->tables[1 - dm_dev->cur_active_table]);
249
250 rw_exit(&dm_dev->dev_rwlock);
251
252 rw_destroy(&dm_dev->dev_rwlock);
253
254 (void)kmem_free(dm_dev, sizeof(struct dm_dev));
255 }
256
257 mutex_exit(&dm_dev_mutex);
258
259 mutex_destroy(&dm_dev_mutex);
260
261 return 0;
262 }
263
264 /*
265 * Allocate new device entry.
266 */
267 struct dm_dev*
268 dm_dev_alloc()
269 {
270 struct dm_dev *dmv;
271
272 dmv = kmem_zalloc(sizeof(struct dm_dev), KM_NOSLEEP);
273 dmv->dk_label = kmem_zalloc(sizeof(struct disklabel), KM_NOSLEEP);
274
275 return dmv;
276 }
277
278 /*
279 * Freed device entry.
280 */
281 int
282 dm_dev_free(struct dm_dev *dmv)
283 {
284 if (dmv->dk_label != NULL)
285 (void)kmem_free(dmv, sizeof(struct disklabel));
286
287 if (dmv != NULL)
288 (void)kmem_free(dmv, sizeof(struct dm_dev));
289
290 return 0;
291 }
292
293
294 /*
295 * Return prop_array of dm_targer_list dictionaries.
296 */
297 prop_array_t
298 dm_dev_prop_list(void)
299 {
300 struct dm_dev *dmd;
301
302 int j;
303
304 prop_array_t dev_array;
305 prop_dictionary_t dev_dict;
306
307 j =0;
308
309 dev_array = prop_array_create();
310
311 mutex_enter(&dm_dev_mutex);
312
313 TAILQ_FOREACH(dmd, &dm_dev_list,next_devlist) {
314 dev_dict = prop_dictionary_create();
315
316 prop_dictionary_set_cstring(dev_dict, DM_DEV_NAME, dmd->name);
317
318 prop_dictionary_set_uint32(dev_dict, DM_DEV_DEV, dmd->minor);
319
320 prop_array_set(dev_array, j, dev_dict);
321
322 prop_object_release(dev_dict);
323
324 j++;
325 }
326
327 mutex_exit(&dm_dev_mutex);
328
329 return dev_array;
330 }
331
332 /*
333 * Initialize global device mutex.
334 */
335 int
336 dm_dev_init()
337 {
338 TAILQ_INIT(&dm_dev_list); /* initialize global dev list */
339
340 mutex_init(&dm_dev_mutex, MUTEX_DEFAULT, IPL_NONE);
341
342 return 0;
343 }
344