dm_target.c revision 1.1.2.2 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 int r;
124
125 r = ENOENT;
126
127 if (dm_target_name == NULL)
128 goto out;
129
130 dm_target = dm_target_lookup_name(dm_target_name);
131 if (dm_target == NULL)
132 goto out;
133
134 mutex_enter(&dm_target_mutex);
135
136 TAILQ_REMOVE(&dm_target_list,
137 dm_target, dm_target_next);
138
139 mutex_exit(&dm_target_mutex);
140
141 (void)kmem_free(dm_target, sizeof(struct dm_target));
142
143 r = 0;
144 out:
145 return r;
146 }
147
148 /*
149 * Allocate new target entry.
150 */
151 struct dm_target*
152 dm_target_alloc(const char *name)
153 {
154 struct dm_target *dmt;
155
156 if ((dmt = kmem_alloc(sizeof(struct dm_target)+strlen(name)+1,
157 KM_NOSLEEP)) == NULL)
158 return NULL;
159
160 return dmt;
161 }
162
163 /*
164 * Return prop_array of dm_target dictionaries.
165 */
166 prop_array_t
167 dm_target_prop_list(void)
168 {
169 prop_array_t target_array,ver;
170 prop_dictionary_t target_dict;
171 struct dm_target *dm_target;
172
173 size_t i,j;
174
175 j = 0;
176
177 target_array = prop_array_create();
178
179 mutex_enter(&dm_target_mutex);
180
181 TAILQ_FOREACH (dm_target, &dm_target_list, dm_target_next){
182
183 target_dict = prop_dictionary_create();
184 ver = prop_array_create();
185
186 prop_dictionary_set_cstring(target_dict, DM_TARGETS_NAME,
187 dm_target->name);
188
189 for (i=0;i<3;i++)
190 prop_array_set_uint32(ver, i, dm_target->version[i]);
191
192 prop_dictionary_set(target_dict, DM_TARGETS_VERSION, ver);
193
194 prop_array_set(target_array, j, target_dict);
195
196 prop_object_release(target_dict);
197
198 j++;
199 }
200
201 mutex_exit(&dm_target_mutex);
202
203 return target_array;
204 }
205
206 /* Initialize dm_target subsystem. */
207 int
208 dm_target_init(void)
209 {
210 struct dm_target *dmt,*dmt1,*dmt2,*dmt3,*dmt4;
211 int r;
212
213 r = 0;
214
215 mutex_init(&dm_target_mutex, MUTEX_DEFAULT, IPL_NONE);
216
217 dmt = dm_target_alloc("linear");
218 dmt3 = dm_target_alloc("striped");
219 dmt1 = dm_target_alloc("error");
220 dmt2 = dm_target_alloc("zero");
221 dmt4 = dm_target_alloc("mirror");
222
223 dmt->version[0] = 1;
224 dmt->version[1] = 0;
225 dmt->version[2] = 2;
226 strncpy(dmt->name, "linear", DM_MAX_TYPE_NAME);
227 dmt->init=&dm_target_linear_init;
228 dmt->strategy=&dm_target_linear_strategy;
229 dmt->destroy=&dm_target_linear_destroy;
230
231 r = dm_target_insert(dmt);
232
233 dmt3->version[0] = 1;
234 dmt3->version[1] = 0;
235 dmt3->version[2] = 3;
236 strncpy(dmt3->name, "striped", DM_MAX_TYPE_NAME);
237 dmt->init=&dm_target_linear_init;
238 dmt->strategy=&dm_target_linear_strategy;
239 dmt->destroy=&dm_target_linear_destroy;
240
241 r = dm_target_insert(dmt3);
242
243 dmt4->version[0] = 1;
244 dmt4->version[1] = 0;
245 dmt4->version[2] = 3;
246 strncpy(dmt4->name, "mirror", DM_MAX_TYPE_NAME);
247 dmt4->init=NULL;
248 dmt4->strategy=NULL;
249
250 r = dm_target_insert(dmt4);
251
252 dmt1->version[0] = 1;
253 dmt1->version[1] = 0;
254 dmt1->version[2] = 0;
255 strncpy(dmt1->name, "zero", DM_MAX_TYPE_NAME);
256 dmt1->init=&dm_target_zero_init;
257 dmt1->strategy=&dm_target_zero_strategy;
258
259 r = dm_target_insert(dmt1);
260
261 dmt2->version[0] = 1;
262 dmt2->version[1] = 0;
263 dmt2->version[2] = 0;
264 strncpy(dmt2->name, "error", DM_MAX_TYPE_NAME);
265 dmt2->init=&dm_target_error_init;
266 dmt2->strategy=&dm_target_error_strategy;
267
268 r = dm_target_insert(dmt2);
269
270 return r;
271 }
272