dm_target.c revision 1.1.2.8 1 /* $NetBSD: dm_target.c,v 1.1.2.8 2008/08/19 13:30:36 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 * Allocate new target entry.
147 */
148 struct dm_target*
149 dm_target_alloc(const char *name)
150 {
151 struct dm_target *dmt;
152
153 if ((dmt = kmem_alloc(sizeof(struct dm_target)+strlen(name)+1,
154 KM_NOSLEEP)) == NULL)
155 return NULL;
156
157 return dmt;
158 }
159
160 /*
161 * Return prop_array of dm_target dictionaries.
162 */
163 prop_array_t
164 dm_target_prop_list(void)
165 {
166 prop_array_t target_array,ver;
167 prop_dictionary_t target_dict;
168 struct dm_target *dm_target;
169
170 size_t i,j;
171
172 j = 0;
173
174 target_array = prop_array_create();
175
176 mutex_enter(&dm_target_mutex);
177
178 TAILQ_FOREACH (dm_target, &dm_target_list, dm_target_next){
179
180 target_dict = prop_dictionary_create();
181 ver = prop_array_create();
182
183 prop_dictionary_set_cstring(target_dict, DM_TARGETS_NAME,
184 dm_target->name);
185
186 for (i=0;i<3;i++)
187 prop_array_set_uint32(ver, i, dm_target->version[i]);
188
189 prop_dictionary_set(target_dict, DM_TARGETS_VERSION, ver);
190
191 prop_array_set(target_array, j, target_dict);
192
193 prop_object_release(target_dict);
194
195 j++;
196 }
197
198 mutex_exit(&dm_target_mutex);
199
200 return target_array;
201 }
202
203 /* Initialize dm_target subsystem. */
204 int
205 dm_target_init(void)
206 {
207 struct dm_target *dmt,*dmt1,*dmt2,*dmt3,*dmt4,*dmt5,*dmt6;
208 int r;
209
210 r = 0;
211
212 mutex_init(&dm_target_mutex, MUTEX_DEFAULT, IPL_NONE);
213
214 dmt = dm_target_alloc("linear");
215 dmt1 = dm_target_alloc("zero");
216 dmt2 = dm_target_alloc("error");
217 dmt3 = dm_target_alloc("striped");
218 dmt4 = dm_target_alloc("mirror");
219 dmt5 = dm_target_alloc("snapshot");
220 dmt6 = dm_target_alloc("snapshot-origin");
221
222 dmt->version[0] = 1;
223 dmt->version[1] = 0;
224 dmt->version[2] = 2;
225 strncpy(dmt->name, "linear", DM_MAX_TYPE_NAME);
226 dmt->init = &dm_target_linear_init;
227 dmt->status = &dm_target_linear_status;
228 dmt->strategy = &dm_target_linear_strategy;
229 dmt->destroy = &dm_target_linear_destroy;
230 dmt->upcall = &dm_target_linear_upcall;
231
232 r = dm_target_insert(dmt);
233
234
235 dmt1->version[0] = 1;
236 dmt1->version[1] = 0;
237 dmt1->version[2] = 0;
238 strncpy(dmt1->name, "zero", DM_MAX_TYPE_NAME);
239 dmt1->init = &dm_target_zero_init;
240 dmt1->status = &dm_target_zero_status;
241 dmt1->strategy = &dm_target_zero_strategy;
242 dmt1->destroy = &dm_target_zero_destroy;
243 dmt1->upcall = &dm_target_zero_upcall;
244
245 r = dm_target_insert(dmt1);
246
247 dmt2->version[0] = 1;
248 dmt2->version[1] = 0;
249 dmt2->version[2] = 0;
250 strncpy(dmt2->name, "error", DM_MAX_TYPE_NAME);
251 dmt2->init = &dm_target_error_init;
252 dmt2->status = &dm_target_error_status;
253 dmt2->strategy = &dm_target_error_strategy;
254 dmt2->destroy = &dm_target_error_destroy;
255 dmt2->upcall = &dm_target_error_upcall;
256
257 r = dm_target_insert(dmt2);
258
259 dmt3->version[0] = 1;
260 dmt3->version[1] = 0;
261 dmt3->version[2] = 3;
262 strncpy(dmt3->name, "striped", DM_MAX_TYPE_NAME);
263 dmt3->init = &dm_target_linear_init;
264 dmt3->status = NULL;
265 dmt3->strategy = &dm_target_linear_strategy;
266 dmt3->destroy = &dm_target_linear_destroy;
267 dmt3->destroy = NULL;
268 dmt3->upcall = NULL;
269
270 r = dm_target_insert(dmt3);
271
272 dmt4->version[0] = 1;
273 dmt4->version[1] = 0;
274 dmt4->version[2] = 3;
275 strncpy(dmt4->name, "mirror", DM_MAX_TYPE_NAME);
276 dmt4->init = NULL;
277 dmt4->status = NULL;
278 dmt4->strategy = NULL;
279 dmt4->destroy = NULL;
280 dmt4->upcall = NULL;
281
282 r = dm_target_insert(dmt4);
283
284 dmt5->version[0] = 1;
285 dmt5->version[1] = 0;
286 dmt5->version[2] = 5;
287 strncpy(dmt5->name, "snapshot", DM_MAX_TYPE_NAME);
288 dmt5->init = &dm_target_snapshot_init;
289 dmt5->status = &dm_target_snapshot_status;
290 dmt5->strategy = &dm_target_snapshot_strategy;
291 dmt5->destroy = &dm_target_snapshot_destroy;
292 dmt5->upcall = &dm_target_snapshot_upcall;
293
294 r = dm_target_insert(dmt5);
295
296 dmt6->version[0] = 1;
297 dmt6->version[1] = 0;
298 dmt6->version[2] = 5;
299 strncpy(dmt6->name, "snapshot-origin", DM_MAX_TYPE_NAME);
300 dmt6->init = &dm_target_snapshot_init;
301 dmt6->status = &dm_target_snapshot_status;
302 dmt6->strategy = &dm_target_snapshot_strategy;
303 dmt6->destroy = &dm_target_snapshot_destroy;
304 dmt6->upcall = &dm_target_snapshot_upcall;
305
306 r = dm_target_insert(dmt6);
307
308 return r;
309 }
310