1 /* $NetBSD: libdm_netbsd.c,v 1.4 2009/12/01 23:11:17 haad Exp $ */
4 * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35 #include <sys/sysctl.h>
44 #include <dev/dm/netbsd-dm.h>
49 #include "libdm-netbsd.h"
51 #define DMI_SIZE 16 * 1024
53 static int dm_list_versions(prop_dictionary_t
, struct dm_ioctl
*);
54 static int dm_list_devices(prop_dictionary_t
, struct dm_ioctl
*);
55 static int dm_dev_deps(prop_dictionary_t
, struct dm_ioctl
*);
56 static int dm_table_status(prop_dictionary_t
, struct dm_ioctl
*);
59 nbsd_get_dm_major(uint32_t *major
, int type
)
62 struct kinfo_drivers
*kd
;
64 if (sysctlbyname("kern.drivers",NULL
,&val_len
,NULL
,0) < 0) {
65 printf("sysctlbyname failed");
69 if ((kd
= malloc (val_len
)) == NULL
){
70 printf("malloc kd info error\n");
74 if (sysctlbyname("kern.drivers", kd
, &val_len
, NULL
, 0) < 0) {
75 printf("sysctlbyname failed kd");
79 for (i
= 0, val_len
/= sizeof(*kd
); i
< val_len
; i
++) {
81 if (strncmp(kd
[i
].d_name
,DM_NAME
,strlen(kd
[i
].d_name
)) == 0){
83 if (type
== DM_CHAR_MAJOR
)
84 /* Set major to dm-driver char major number. */
85 *major
= kd
[i
].d_cmajor
;
87 if (type
== DM_BLOCK_MAJOR
)
88 *major
= kd
[i
].d_bmajor
;
102 nbsd_dmi_add_version(const int *version
, prop_dictionary_t dm_dict
)
107 if ((ver
= prop_array_create()) == NULL
)
111 prop_array_set_uint32(ver
,i
,version
[i
]);
113 if ((prop_dictionary_set(dm_dict
,"version",ver
)) == false)
116 prop_object_release(ver
);
122 nbsd_dm_dict_to_dmi(prop_dictionary_t dm_dict
,const int cmd
)
124 struct dm_ioctl
*dmi
;
130 uint32_t major
,minor
;
136 nbsd_get_dm_major(&major
, DM_BLOCK_MAJOR
);
138 if (!(dmi
= dm_malloc(DMI_SIZE
)))
141 memset(dmi
,0,DMI_SIZE
);
143 prop_dictionary_get_int32(dm_dict
, DM_IOCTL_OPEN
, &dmi
->open_count
);
144 prop_dictionary_get_uint32(dm_dict
, DM_IOCTL_EVENT
, &dmi
->event_nr
);
145 prop_dictionary_get_uint32(dm_dict
, DM_IOCTL_FLAGS
, &dmi
->flags
);
146 prop_dictionary_get_uint32(dm_dict
, DM_IOCTL_TARGET_COUNT
,
149 if (prop_dictionary_get_uint32(dm_dict
, DM_IOCTL_MINOR
, &minor
))
150 dmi
->dev
= MKDEV(major
, minor
);
154 /* Copy name and uuid to dm_ioctl. */
155 if (prop_dictionary_get_cstring_nocopy(dm_dict
, DM_IOCTL_NAME
,
156 (const char **)&name
)){
157 strlcpy(dmi
->name
, name
, DM_NAME_LEN
);
161 if (prop_dictionary_get_cstring_nocopy(dm_dict
, DM_IOCTL_UUID
,
162 (const char **)&uuid
)){
163 strlcpy(dmi
->uuid
, uuid
, DM_UUID_LEN
);
167 /* dmi parsing values, size of dmi block and offset to data. */
168 dmi
->data_size
= DMI_SIZE
;
169 dmi
->data_start
= sizeof(struct dm_ioctl
);
171 /* Get kernel version from dm_dict. */
172 ver
= prop_dictionary_get(dm_dict
,DM_IOCTL_VERSION
);
175 prop_array_get_uint32(ver
,i
,&dmi
->version
[i
]);
179 case DM_LIST_VERSIONS
:
180 r
= dm_list_versions(dm_dict
,dmi
);
182 dmi
->target_count
= r
;
185 case DM_LIST_DEVICES
:
186 r
= dm_list_devices(dm_dict
,dmi
);
188 dmi
->target_count
= r
;
191 case DM_TABLE_STATUS
:
192 r
= dm_table_status(dm_dict
,dmi
);
194 dmi
->target_count
= r
;
198 r
= dm_dev_deps(dm_dict
,dmi
);
200 dmi
->target_count
= r
;
208 * Parse dm_dict when targets command was called and fill dm_ioctl buffer with it.
210 * Return number of targets or if failed <0 error.
214 dm_list_versions(prop_dictionary_t dm_dict
, struct dm_ioctl
*dmi
)
216 struct dm_target_versions
*dmtv
,*odmtv
;
218 prop_array_t targets
,ver
;
219 prop_dictionary_t target_dict
;
220 prop_object_iterator_t iter
;
223 size_t j
,i
,slen
,rec_size
;
229 dmtv
= (struct dm_target_versions
*)((uint8_t *)dmi
+ dmi
->data_start
);
231 /* printf("dmi: vers: %d.%d.%d data_size: %d data_start: %d name: %s t_count: %d\n",
232 dmi->version[0],dmi->version[1],dmi->version[2],dmi->data_size,dmi->data_start,
233 dmi->name,dmi->target_count);
235 printf("dmi: size: %d -- %p --- %p \n",sizeof(struct dm_ioctl),dmi,dmi+dmi->data_start);
236 printf("dmtv: size: %p --- %p\n",dmtv,(struct dm_target_versions *)(dmi+312));*/
238 /* get prop_array of target_version dictionaries */
239 if ((targets
= prop_dictionary_get(dm_dict
,DM_IOCTL_CMD_DATA
))){
241 iter
= prop_array_iterator(targets
);
243 err(EXIT_FAILURE
,"dm_list_versions %s",__func__
);
245 while((target_dict
= prop_object_iterator_next(iter
)) != NULL
){
248 prop_dictionary_get_cstring_nocopy(target_dict
,
249 DM_TARGETS_NAME
,(const char **)&name
);
251 slen
= strlen(name
) + 1;
252 rec_size
= sizeof(struct dm_target_versions
) + slen
+ 1;
254 if (rec_size
> dmi
->data_size
)
257 ver
= prop_dictionary_get(target_dict
,DM_TARGETS_VERSION
);
260 prop_array_get_uint32(ver
,i
,&dmtv
->version
[i
]);
262 dmtv
->next
= rec_size
;
264 strlcpy(dmtv
->name
,name
,slen
);
268 dmtv
=(struct dm_target_versions
*)((uint8_t *)dmtv
+ rec_size
);
275 prop_object_iterator_release(iter
);
280 * List all available dm devices in system.
283 dm_list_devices(prop_dictionary_t dm_dict
, struct dm_ioctl
*dmi
)
285 struct dm_name_list
*dml
,*odml
;
287 prop_array_t targets
;
288 prop_dictionary_t target_dict
;
289 prop_object_iterator_t iter
;
295 size_t j
,slen
,rec_size
;
302 nbsd_get_dm_major(&major
,DM_BLOCK_MAJOR
);
304 dml
= (struct dm_name_list
*)((uint8_t *)dmi
+ dmi
->data_start
);
306 if ((targets
= prop_dictionary_get(dm_dict
,DM_IOCTL_CMD_DATA
))){
308 iter
= prop_array_iterator(targets
);
310 err(EXIT_FAILURE
,"dm_list_devices %s",__func__
);
312 while((target_dict
= prop_object_iterator_next(iter
)) != NULL
){
314 prop_dictionary_get_cstring_nocopy(target_dict
,
315 DM_DEV_NAME
,(const char **)&name
);
317 prop_dictionary_get_uint32(target_dict
,DM_DEV_DEV
,&minor
);
319 dml
->dev
= MKDEV(major
,minor
);
321 slen
= strlen(name
) + 1;
322 rec_size
= sizeof(struct dm_name_list
) + slen
+ 1;
324 if (rec_size
> dmi
->data_size
)
327 dml
->next
= rec_size
;
329 strlcpy(dml
->name
,name
,slen
);
333 dml
=(struct dm_name_list
*)((uint8_t *)dml
+ rec_size
);
341 prop_object_iterator_release(iter
);
346 * Print status of each table, target arguments, start sector,
347 * size and target name.
350 dm_table_status(prop_dictionary_t dm_dict
,struct dm_ioctl
*dmi
)
352 struct dm_target_spec
*dmts
, *odmts
;
354 prop_array_t targets
;
355 prop_dictionary_t target_dict
;
356 prop_object_iterator_t iter
;
358 char *type
,*params
,*params_start
;
361 size_t j
,plen
,rec_size
,next
;
371 dmts
= (struct dm_target_spec
*)((uint8_t *)dmi
+ dmi
->data_start
);
373 if ((targets
= prop_dictionary_get(dm_dict
,DM_IOCTL_CMD_DATA
))){
375 iter
= prop_array_iterator(targets
);
377 err(EXIT_FAILURE
,"dm_table_status %s",__func__
);
379 while((target_dict
= prop_object_iterator_next(iter
)) != NULL
){
381 prop_dictionary_get_cstring_nocopy(target_dict
,
382 DM_TABLE_TYPE
,(const char **)&type
);
384 prm
= prop_dictionary_get_cstring_nocopy(target_dict
,
385 DM_TABLE_PARAMS
,(const char **)¶ms
);
387 prop_dictionary_get_uint64(target_dict
,DM_TABLE_START
,&dmts
->sector_start
);
388 prop_dictionary_get_uint64(target_dict
,DM_TABLE_LENGTH
,&dmts
->length
);
389 prop_dictionary_get_int32(target_dict
,DM_TABLE_STAT
,&dmts
->status
);
392 plen
= strlen(params
) + 1;
394 rec_size
= sizeof(struct dm_target_spec
) + plen
;
397 * In linux when copying table status from kernel next is
398 * number of bytes from the start of the first dm_target_spec
399 * structure. I don't know why but, it has to be done this way.
403 if (rec_size
> dmi
->data_size
)
408 strlcpy(dmts
->target_type
, type
, DM_MAX_TYPE_NAME
);
410 params_start
= (char *)dmts
+ sizeof(struct dm_target_spec
);
413 strlcpy(params_start
, params
, plen
);
420 dmts
= (struct dm_target_spec
*)((uint8_t *)dmts
+ rec_size
);
429 prop_object_iterator_release(iter
);
435 * Print dm device dependiences, get minor/major number for
436 * devices. From kernel I will receive major:minor number of
437 * block device used with target. I have to translate it to
438 * raw device numbers and use them, because all other parts of lvm2
439 * uses raw devices internaly.
442 dm_dev_deps(prop_dictionary_t dm_dict
, struct dm_ioctl
*dmi
)
444 struct dm_target_deps
*dmtd
;
445 struct kinfo_drivers
*kd
;
447 prop_array_t targets
;
448 prop_object_iterator_t iter
;
452 size_t val_len
, i
, j
;
460 if (sysctlbyname("kern.drivers",NULL
,&val_len
,NULL
,0) < 0) {
461 printf("sysctlbyname failed");
465 if ((kd
= malloc (val_len
)) == NULL
){
466 printf("malloc kd info error\n");
470 if (sysctlbyname("kern.drivers", kd
, &val_len
, NULL
, 0) < 0) {
471 printf("sysctlbyname failed kd");
475 dmtd
= (struct dm_target_deps
*)((uint8_t *)dmi
+ dmi
->data_start
);
477 if ((targets
= prop_dictionary_get(dm_dict
, DM_IOCTL_CMD_DATA
))){
479 iter
= prop_array_iterator(targets
);
481 err(EXIT_FAILURE
,"dm_target_deps %s", __func__
);
483 while((prop_object_iterator_next(iter
)) != NULL
){
485 prop_array_get_uint64(targets
, j
, &dev_tmp
);
487 for (i
= 0, val_len
/= sizeof(*kd
); i
< val_len
; i
++){
488 if (kd
[i
].d_bmajor
== MAJOR(dev_tmp
)) {
489 major
= kd
[i
].d_cmajor
;
494 dmtd
->dev
[j
] = MKDEV(major
,MINOR(dev_tmp
));
502 prop_object_iterator_release(iter
);