dm_target.c revision 1.1.2.10 1 /* $NetBSD: dm_target.c,v 1.1.2.10 2008/08/20 00:45:47 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 #include <sys/types.h>
33 #include <sys/param.h>
34
35 #include <sys/errno.h>
36 #include <sys/ioctl.h>
37 #include <sys/ioccom.h>
38 #include <sys/kmem.h>
39 #include <sys/queue.h>
40
41
42 #include "netbsd-dm.h"
43 #include "dm.h"
44
45 static struct dm_target* dm_target_alloc(const char *);
46
47 TAILQ_HEAD(dm_target_head, dm_target);
48
49 static struct dm_target_head dm_target_list =
50 TAILQ_HEAD_INITIALIZER(dm_target_list);
51
52 kmutex_t dm_target_mutex;
53
54 /*
55 * Search for name in TAIL and return apropriate pointer.
56 */
57 struct dm_target*
58 dm_target_lookup_name(const char *dm_target_name)
59 {
60 struct dm_target *dm_target;
61 int dlen; int slen;
62
63 slen = strlen(dm_target_name)+1;
64
65 mutex_enter(&dm_target_mutex);
66
67 TAILQ_FOREACH (dm_target, &dm_target_list, dm_target_next) {
68 dlen = strlen(dm_target->name)+1;
69
70 if (dlen != slen)
71 continue;
72
73 if (strncmp(dm_target_name, dm_target->name, slen) == 0){
74 mutex_exit(&dm_target_mutex);
75 return dm_target;
76 }
77 }
78
79 mutex_exit(&dm_target_mutex);
80
81 return NULL;
82 }
83
84 /*
85 * Insert new target struct into the TAIL.
86 * dm_target
87 * contains name, version, function pointer to specifif target functions.
88 */
89 int
90 dm_target_insert(struct dm_target *dm_target)
91 {
92 struct dm_target *dmt;
93 int r;
94
95 r = 0;
96
97 dmt = dm_target_lookup_name(dm_target->name);
98
99 if (dmt != NULL) {
100 if (dmt->version[0] >= dm_target->version[0] &&
101 dmt->version[1] >= dm_target->version[1] &&
102 dmt->version[2] >= dm_target->version[2]) {
103 r = EEXIST;
104 goto out;
105 }
106 }
107
108 mutex_enter(&dm_target_mutex);
109
110 TAILQ_INSERT_TAIL(&dm_target_list, dm_target, dm_target_next);
111
112 mutex_exit(&dm_target_mutex);
113 out:
114 return r;
115 }
116
117
118 /*
119 * Remove target from TAIL, target is selected with it's name.
120 */
121 int
122 dm_target_rem(char *dm_target_name)
123 {
124 struct dm_target *dm_target;
125
126 if (dm_target_name == NULL)
127 return ENOENT;
128
129 dm_target = dm_target_lookup_name(dm_target_name);
130 if (dm_target == NULL)
131 return ENOENT;
132
133 mutex_enter(&dm_target_mutex);
134
135 TAILQ_REMOVE(&dm_target_list,
136 dm_target, dm_target_next);
137
138 mutex_exit(&dm_target_mutex);
139
140 (void)kmem_free(dm_target, sizeof(struct dm_target));
141
142 return 0;
143 }
144
145 /*
146 * Destroy all targets and remove them from queue.
147 * This routine is called from dm_detach, before module
148 * is unloaded.
149 */
150
151 int
152 dm_target_destroy(void)
153 {
154 struct dm_target *dm_target;
155
156 mutex_enter(&dm_target_mutex);
157
158 while (TAILQ_FIRST(&dm_target_list) != NULL){
159
160 dm_target = TAILQ_FIRST(&dm_target_list);
161
162 TAILQ_REMOVE(&dm_target_list, TAILQ_FIRST(&dm_target_list),
163 dm_target_next);
164
165 (void)kmem_free(dm_target, sizeof(struct dm_target));
166 }
167
168 mutex_exit(&dm_target_mutex);
169
170 return 0;
171 }
172
173 /*
174 * Allocate new target entry.
175 */
176 struct dm_target*
177 dm_target_alloc(const char *name)
178 {
179 struct dm_target *dmt;
180
181 if ((dmt = kmem_alloc(sizeof(struct dm_target)+strlen(name)+1,
182 KM_NOSLEEP)) == NULL)
183 return NULL;
184
185 return dmt;
186 }
187
188 /*
189 * Return prop_array of dm_target dictionaries.
190 */
191 prop_array_t
192 dm_target_prop_list(void)
193 {
194 prop_array_t target_array,ver;
195 prop_dictionary_t target_dict;
196 struct dm_target *dm_target;
197
198 size_t i,j;
199
200 j = 0;
201
202 target_array = prop_array_create();
203
204 mutex_enter(&dm_target_mutex);
205
206 TAILQ_FOREACH (dm_target, &dm_target_list, dm_target_next){
207
208 target_dict = prop_dictionary_create();
209 ver = prop_array_create();
210
211 prop_dictionary_set_cstring(target_dict, DM_TARGETS_NAME,
212 dm_target->name);
213
214 for (i=0;i<3;i++)
215 prop_array_set_uint32(ver, i, dm_target->version[i]);
216
217 prop_dictionary_set(target_dict, DM_TARGETS_VERSION, ver);
218
219 prop_array_set(target_array, j, target_dict);
220
221 prop_object_release(target_dict);
222
223 j++;
224 }
225
226 mutex_exit(&dm_target_mutex);
227
228 return target_array;
229 }
230
231 /* Initialize dm_target subsystem. */
232 int
233 dm_target_init(void)
234 {
235 struct dm_target *dmt,*dmt1,*dmt2,*dmt3,*dmt4,*dmt5,*dmt6;
236 int r;
237
238 r = 0;
239
240 mutex_init(&dm_target_mutex, MUTEX_DEFAULT, IPL_NONE);
241
242 dmt = dm_target_alloc("linear");
243 dmt1 = dm_target_alloc("zero");
244 dmt2 = dm_target_alloc("error");
245 dmt3 = dm_target_alloc("striped");
246 dmt4 = dm_target_alloc("mirror");
247 dmt5 = dm_target_alloc("snapshot");
248 dmt6 = dm_target_alloc("snapshot-origin");
249
250 dmt->version[0] = 1;
251 dmt->version[1] = 0;
252 dmt->version[2] = 2;
253 strncpy(dmt->name, "linear", DM_MAX_TYPE_NAME);
254 dmt->init = &dm_target_linear_init;
255 dmt->status = &dm_target_linear_status;
256 dmt->strategy = &dm_target_linear_strategy;
257 dmt->destroy = &dm_target_linear_destroy;
258 dmt->upcall = &dm_target_linear_upcall;
259
260 r = dm_target_insert(dmt);
261
262
263 dmt1->version[0] = 1;
264 dmt1->version[1] = 0;
265 dmt1->version[2] = 0;
266 strncpy(dmt1->name, "zero", DM_MAX_TYPE_NAME);
267 dmt1->init = &dm_target_zero_init;
268 dmt1->status = &dm_target_zero_status;
269 dmt1->strategy = &dm_target_zero_strategy;
270 dmt1->destroy = &dm_target_zero_destroy;
271 dmt1->upcall = &dm_target_zero_upcall;
272
273 r = dm_target_insert(dmt1);
274
275 dmt2->version[0] = 1;
276 dmt2->version[1] = 0;
277 dmt2->version[2] = 0;
278 strncpy(dmt2->name, "error", DM_MAX_TYPE_NAME);
279 dmt2->init = &dm_target_error_init;
280 dmt2->status = &dm_target_error_status;
281 dmt2->strategy = &dm_target_error_strategy;
282 dmt2->destroy = &dm_target_error_destroy;
283 dmt2->upcall = &dm_target_error_upcall;
284
285 r = dm_target_insert(dmt2);
286
287 dmt3->version[0] = 1;
288 dmt3->version[1] = 0;
289 dmt3->version[2] = 3;
290 strncpy(dmt3->name, "striped", DM_MAX_TYPE_NAME);
291 dmt3->init = &dm_target_linear_init;
292 dmt3->status = NULL;
293 dmt3->strategy = &dm_target_linear_strategy;
294 dmt3->destroy = &dm_target_linear_destroy;
295 dmt3->destroy = NULL;
296 dmt3->upcall = NULL;
297
298 r = dm_target_insert(dmt3);
299
300 dmt4->version[0] = 1;
301 dmt4->version[1] = 0;
302 dmt4->version[2] = 3;
303 strncpy(dmt4->name, "mirror", DM_MAX_TYPE_NAME);
304 dmt4->init = NULL;
305 dmt4->status = NULL;
306 dmt4->strategy = NULL;
307 dmt4->destroy = NULL;
308 dmt4->upcall = NULL;
309
310 r = dm_target_insert(dmt4);
311
312 dmt5->version[0] = 1;
313 dmt5->version[1] = 0;
314 dmt5->version[2] = 5;
315 strncpy(dmt5->name, "snapshot", DM_MAX_TYPE_NAME);
316 dmt5->init = &dm_target_snapshot_init;
317 dmt5->status = &dm_target_snapshot_status;
318 dmt5->strategy = &dm_target_snapshot_strategy;
319 dmt5->destroy = &dm_target_snapshot_destroy;
320 dmt5->upcall = &dm_target_snapshot_upcall;
321
322 r = dm_target_insert(dmt5);
323
324 dmt6->version[0] = 1;
325 dmt6->version[1] = 0;
326 dmt6->version[2] = 5;
327 strncpy(dmt6->name, "snapshot-origin", DM_MAX_TYPE_NAME);
328 dmt6->init = &dm_target_snapshot_orig_init;
329 dmt6->status = &dm_target_snapshot_orig_status;
330 dmt6->strategy = &dm_target_snapshot_orig_strategy;
331 dmt6->destroy = &dm_target_snapshot_orig_destroy;
332 dmt6->upcall = &dm_target_snapshot_orig_upcall;
333
334 r = dm_target_insert(dmt6);
335
336 return r;
337 }
338