dm_dev.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
31 #include <sys/types.h>
32 #include <sys/param.h>
33
34 #include <sys/disk.h>
35 #include <sys/errno.h>
36 #include <sys/ioctl.h>
37 #include <sys/ioccom.h>
38 #include <sys/kmem.h>
39 #include <sys/lkm.h>
40 #include <sys/queue.h>
41
42 #include "netbsd-dm.h"
43 #include "dm.h"
44
45 /*TAILQ_HEAD(dm_dev_head, dm_dev);*/
46
47 static struct dm_dev_head dm_dev_list =
48 TAILQ_HEAD_INITIALIZER(dm_dev_list);
49 /*static struct db_cmd_tbl_en db_base_cmd_builtins =
50 { .db_cmd = db_command_table };*/
51
52 kmutex_t dm_dev_mutex;
53
54 /*
55 * Locking architecture, for now I use mutexes later we can convert them to
56 * rw_locks. I use IPL_NONE for specifing IPL type for mutex.
57 * I will enter into mutex everytime I'm working with dm_dev_list.
58 */
59
60 /*
61 * Lookup device with its minor number.
62 */
63 struct dm_dev*
64 dm_dev_lookup_minor(int dm_dev_minor)
65 {
66 struct dm_dev *dm_dev;
67
68 mutex_enter(&dm_dev_mutex);
69
70 TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
71 if (dm_dev_minor == dm_dev->minor){
72 mutex_exit(&dm_dev_mutex);
73 return dm_dev;
74 }
75 }
76
77
78 mutex_exit(&dm_dev_mutex);
79
80 return NULL;
81 }
82
83 /*
84 * Lookup device with it's device name.
85 */
86 struct dm_dev*
87 dm_dev_lookup_name(const char *dm_dev_name)
88 {
89 struct dm_dev *dm_dev;
90 int dlen; int slen;
91
92 if (dm_dev_name == NULL)
93 return NULL;
94
95 slen = strlen(dm_dev_name);
96
97 mutex_enter(&dm_dev_mutex);
98
99 TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
100
101 dlen = strlen(dm_dev->name);
102
103 if(slen != dlen)
104 continue;
105
106 if (strncmp(dm_dev_name, dm_dev->name, slen) == 0) {
107 mutex_exit(&dm_dev_mutex);
108 return dm_dev;
109 }
110 }
111
112 mutex_exit(&dm_dev_mutex);
113
114 return NULL;
115 }
116
117 /*
118 * Lookup device with it's device uuid. Used mostly by LVM2tools.
119 */
120 struct dm_dev*
121 dm_dev_lookup_uuid(const char *dm_dev_uuid)
122 {
123 struct dm_dev *dm_dev;
124
125 if (dm_dev_uuid == NULL)
126 return NULL;
127
128 mutex_enter(&dm_dev_mutex);
129
130 TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist)
131 if (strncmp(dm_dev_uuid, dm_dev->uuid, strlen(dm_dev->uuid)) == 0){
132 mutex_exit(&dm_dev_mutex);
133 return dm_dev;
134 }
135 mutex_exit(&dm_dev_mutex);
136
137 return NULL;
138 }
139
140 /*
141 * Insert new device to the global list of devices.
142 */
143 int
144 dm_dev_insert(struct dm_dev *dev)
145 {
146 struct dm_dev *dmt;
147 int r;
148
149 dmt = NULL;
150 r = 0;
151
152 /* XXX dev->name can be NULL if uuid is used */
153 dmt = dm_dev_lookup_name(dev->name);
154
155 if (dmt == NULL) {
156 mutex_enter(&dm_dev_mutex);
157 TAILQ_INSERT_TAIL(&dm_dev_list, dev, next_devlist);
158 mutex_exit(&dm_dev_mutex);
159 } else
160 r = EEXIST;
161
162 return r;
163 }
164
165
166 /*
167 * Remove device selected with name.
168 */
169 int
170 dm_dev_rem(const char *dm_dev_name)
171 {
172 struct dm_dev *dm_dev;
173 int r;
174
175 r = ENOENT;
176
177 if(dm_dev_name == NULL)
178 goto out;
179
180 if((dm_dev = dm_dev_lookup_name(dm_dev_name)) == NULL)
181 dm_dev = dm_dev_lookup_uuid(dm_dev_name);
182
183 if (dm_dev == NULL)
184 goto out;
185
186 mutex_enter(&dm_dev_mutex);
187
188 TAILQ_REMOVE(&dm_dev_list, dm_dev, next_devlist);
189
190 mutex_exit(&dm_dev_mutex);
191
192 dm_dev_free(dm_dev);
193
194 r = 0;
195 out:
196 return r;
197 }
198
199 /*
200 * Allocate new device entry.
201 */
202 struct dm_dev*
203 dm_dev_alloc()
204 {
205 struct dm_dev *dmv;
206
207 if ((dmv = kmem_alloc(sizeof(struct dm_dev), KM_NOSLEEP)) == NULL)
208 return NULL;
209
210 if ((dmv->dm_dk = kmem_alloc(sizeof(struct disk), KM_NOSLEEP)) == NULL){
211 (void)kmem_free(dmv, sizeof(struct dm_dev));
212 return NULL;
213 }
214
215 return dmv;
216 }
217
218 /*
219 * Freed device entry.
220 */
221 int
222 dm_dev_free(struct dm_dev *dmv)
223 {
224 if (dmv != NULL){
225 (void)kmem_free(dmv->dm_dk, sizeof(struct disk));
226 (void)kmem_free(dmv, sizeof(struct dm_dev));
227 }
228
229 return 0;
230 }
231
232
233 /*
234 * Return prop_array of dm_targer_list dictionaries.
235 */
236 prop_array_t
237 dm_dev_prop_list(void)
238 {
239 struct dm_dev *dmd;
240
241 int j;
242
243 prop_array_t dev_array;
244 prop_dictionary_t dev_dict;
245
246 j =0;
247
248 dev_array = prop_array_create();
249
250 mutex_enter(&dm_dev_mutex);
251
252 TAILQ_FOREACH(dmd, &dm_dev_list,next_devlist) {
253 dev_dict = prop_dictionary_create();
254
255 prop_dictionary_set_cstring(dev_dict, DM_DEV_NAME, dmd->name);
256
257 prop_dictionary_set_uint32(dev_dict, DM_DEV_DEV, dmd->minor);
258
259 prop_array_set(dev_array, j, dev_dict);
260
261 prop_object_release(dev_dict);
262
263 j++;
264 }
265
266 mutex_exit(&dm_dev_mutex);
267
268 return dev_array;
269 }
270
271 /*
272 *Initialize global device mutex.
273 */
274 int
275 dm_dev_init()
276 {
277 mutex_init(&dm_dev_mutex, MUTEX_DEFAULT, IPL_NONE);
278
279 return 0;
280 }
281