dm_target.c revision 1.1.2.7 1 /*
2 * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Adam Hamsik.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32
33 #include <sys/errno.h>
34 #include <sys/ioctl.h>
35 #include <sys/ioccom.h>
36 #include <sys/kmem.h>
37 #include <sys/queue.h>
38
39
40 #include "netbsd-dm.h"
41 #include "dm.h"
42
43 static struct dm_target* dm_target_alloc(const char *);
44
45 TAILQ_HEAD(dm_target_head, dm_target);
46
47 static struct dm_target_head dm_target_list =
48 TAILQ_HEAD_INITIALIZER(dm_target_list);
49
50 kmutex_t dm_target_mutex;
51
52 /*
53 * Search for name in TAIL and return apropriate pointer.
54 */
55 struct dm_target*
56 dm_target_lookup_name(const char *dm_target_name)
57 {
58 struct dm_target *dm_target;
59 int dlen; int slen;
60
61 slen = strlen(dm_target_name)+1;
62
63 mutex_enter(&dm_target_mutex);
64
65 TAILQ_FOREACH (dm_target, &dm_target_list, dm_target_next) {
66 dlen = strlen(dm_target->name)+1;
67
68 if (dlen != slen)
69 continue;
70
71 if (strncmp(dm_target_name, dm_target->name, slen) == 0){
72 mutex_exit(&dm_target_mutex);
73 return dm_target;
74 }
75 }
76
77 mutex_exit(&dm_target_mutex);
78
79 return NULL;
80 }
81
82 /*
83 * Insert new target struct into the TAIL.
84 * dm_target
85 * contains name, version, function pointer to specifif target functions.
86 */
87 int
88 dm_target_insert(struct dm_target *dm_target)
89 {
90 struct dm_target *dmt;
91 int r;
92
93 r = 0;
94
95 dmt = dm_target_lookup_name(dm_target->name);
96
97 if (dmt != NULL) {
98 if (dmt->version[0] >= dm_target->version[0] &&
99 dmt->version[1] >= dm_target->version[1] &&
100 dmt->version[2] >= dm_target->version[2]) {
101 r = EEXIST;
102 goto out;
103 }
104 }
105
106 mutex_enter(&dm_target_mutex);
107
108 TAILQ_INSERT_TAIL(&dm_target_list, dm_target, dm_target_next);
109
110 mutex_exit(&dm_target_mutex);
111 out:
112 return r;
113 }
114
115
116 /*
117 * Remove target from TAIL, target is selected with it's name.
118 */
119 int
120 dm_target_rem(char *dm_target_name)
121 {
122 struct dm_target *dm_target;
123
124 if (dm_target_name == NULL)
125 return ENOENT;
126
127 dm_target = dm_target_lookup_name(dm_target_name);
128 if (dm_target == NULL)
129 return ENOENT;
130
131 mutex_enter(&dm_target_mutex);
132
133 TAILQ_REMOVE(&dm_target_list,
134 dm_target, dm_target_next);
135
136 mutex_exit(&dm_target_mutex);
137
138 (void)kmem_free(dm_target, sizeof(struct dm_target));
139
140 return 0;
141 }
142
143 /*
144 * Allocate new target entry.
145 */
146 struct dm_target*
147 dm_target_alloc(const char *name)
148 {
149 struct dm_target *dmt;
150
151 if ((dmt = kmem_alloc(sizeof(struct dm_target)+strlen(name)+1,
152 KM_NOSLEEP)) == NULL)
153 return NULL;
154
155 return dmt;
156 }
157
158 /*
159 * Return prop_array of dm_target dictionaries.
160 */
161 prop_array_t
162 dm_target_prop_list(void)
163 {
164 prop_array_t target_array,ver;
165 prop_dictionary_t target_dict;
166 struct dm_target *dm_target;
167
168 size_t i,j;
169
170 j = 0;
171
172 target_array = prop_array_create();
173
174 mutex_enter(&dm_target_mutex);
175
176 TAILQ_FOREACH (dm_target, &dm_target_list, dm_target_next){
177
178 target_dict = prop_dictionary_create();
179 ver = prop_array_create();
180
181 prop_dictionary_set_cstring(target_dict, DM_TARGETS_NAME,
182 dm_target->name);
183
184 for (i=0;i<3;i++)
185 prop_array_set_uint32(ver, i, dm_target->version[i]);
186
187 prop_dictionary_set(target_dict, DM_TARGETS_VERSION, ver);
188
189 prop_array_set(target_array, j, target_dict);
190
191 prop_object_release(target_dict);
192
193 j++;
194 }
195
196 mutex_exit(&dm_target_mutex);
197
198 return target_array;
199 }
200
201 /* Initialize dm_target subsystem. */
202 int
203 dm_target_init(void)
204 {
205 struct dm_target *dmt,*dmt1,*dmt2,*dmt3,*dmt4,*dmt5,*dmt6;
206 int r;
207
208 r = 0;
209
210 mutex_init(&dm_target_mutex, MUTEX_DEFAULT, IPL_NONE);
211
212 dmt = dm_target_alloc("linear");
213 dmt1 = dm_target_alloc("zero");
214 dmt2 = dm_target_alloc("error");
215 dmt3 = dm_target_alloc("striped");
216 dmt4 = dm_target_alloc("mirror");
217 dmt5 = dm_target_alloc("snapshot");
218 dmt6 = dm_target_alloc("snapshot-origin");
219
220 dmt->version[0] = 1;
221 dmt->version[1] = 0;
222 dmt->version[2] = 2;
223 strncpy(dmt->name, "linear", DM_MAX_TYPE_NAME);
224 dmt->init = &dm_target_linear_init;
225 dmt->status = &dm_target_linear_status;
226 dmt->strategy = &dm_target_linear_strategy;
227 dmt->destroy = &dm_target_linear_destroy;
228 dmt->upcall = &dm_target_linear_upcall;
229
230 r = dm_target_insert(dmt);
231
232
233 dmt1->version[0] = 1;
234 dmt1->version[1] = 0;
235 dmt1->version[2] = 0;
236 strncpy(dmt1->name, "zero", DM_MAX_TYPE_NAME);
237 dmt1->init = &dm_target_zero_init;
238 dmt1->status = &dm_target_zero_status;
239 dmt1->strategy = &dm_target_zero_strategy;
240 dmt1->destroy = &dm_target_zero_destroy;
241 dmt1->upcall = &dm_target_zero_upcall;
242
243 r = dm_target_insert(dmt1);
244
245 dmt2->version[0] = 1;
246 dmt2->version[1] = 0;
247 dmt2->version[2] = 0;
248 strncpy(dmt2->name, "error", DM_MAX_TYPE_NAME);
249 dmt2->init = &dm_target_error_init;
250 dmt2->status = &dm_target_error_status;
251 dmt2->strategy = &dm_target_error_strategy;
252 dmt2->destroy = &dm_target_error_destroy;
253 dmt2->upcall = &dm_target_error_upcall;
254
255 r = dm_target_insert(dmt2);
256
257 dmt3->version[0] = 1;
258 dmt3->version[1] = 0;
259 dmt3->version[2] = 3;
260 strncpy(dmt3->name, "striped", DM_MAX_TYPE_NAME);
261 dmt3->init = &dm_target_linear_init;
262 dmt3->status = NULL;
263 dmt3->strategy = &dm_target_linear_strategy;
264 dmt3->destroy = &dm_target_linear_destroy;
265 dmt3->destroy = NULL;
266 dmt3->upcall = NULL;
267
268 r = dm_target_insert(dmt3);
269
270 dmt4->version[0] = 1;
271 dmt4->version[1] = 0;
272 dmt4->version[2] = 3;
273 strncpy(dmt4->name, "mirror", DM_MAX_TYPE_NAME);
274 dmt4->init = NULL;
275 dmt4->status = NULL;
276 dmt4->strategy = NULL;
277 dmt4->destroy = NULL;
278 dmt4->upcall = NULL;
279
280 r = dm_target_insert(dmt4);
281
282 dmt5->version[0] = 1;
283 dmt5->version[1] = 0;
284 dmt5->version[2] = 5;
285 strncpy(dmt5->name, "snapshot", DM_MAX_TYPE_NAME);
286 dmt5->init = &dm_target_snapshot_init;
287 dmt5->status = &dm_target_snapshot_status;
288 dmt5->strategy = &dm_target_snapshot_strategy;
289 dmt5->destroy = &dm_target_snapshot_destroy;
290 dmt5->upcall = &dm_target_snapshot_upcall;
291
292 r = dm_target_insert(dmt5);
293
294 dmt6->version[0] = 1;
295 dmt6->version[1] = 0;
296 dmt6->version[2] = 5;
297 strncpy(dmt6->name, "snapshot-origin", DM_MAX_TYPE_NAME);
298 dmt6->init = &dm_target_snapshot_init;
299 dmt6->status = &dm_target_snapshot_status;
300 dmt6->strategy = &dm_target_snapshot_strategy;
301 dmt6->destroy = &dm_target_snapshot_destroy;
302 dmt6->upcall = &dm_target_snapshot_upcall;
303
304 r = dm_target_insert(dmt6);
305
306 return r;
307 }
308