/* Fill info from dm_ioctl structure. Look at DM_EXISTS_FLAG*/ int dm_task_get_info(struct dm_task *dmt, struct dm_info *info) { if (!dmt->dmi.v4) return 0; memset(info, 0, sizeof(*info)); info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0; if (!info->exists) return 1; info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0; info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0; info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0; info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ? 1 : 0; info->target_count = dmt->dmi.v4->target_count; info->open_count = dmt->dmi.v4->open_count; info->event_nr = dmt->dmi.v4->event_nr; nbsd_get_dm_major(&info->major, DM_BLOCK_MAJOR); /* get netbsd dm device major number */ info->minor = MINOR(dmt->dmi.v4->dev); return 1; }
static int _control_device_number(uint32_t *major, uint32_t *minor) { nbsd_get_dm_major(major, DM_CHAR_MAJOR); *minor = 0; return 1; }
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor) { int r; uint32_t major, dm_major; char *name; mode_t mode; dev_t dev; size_t val_len,i; struct kinfo_drivers *kd; mode = 0; nbsd_get_dm_major(&dm_major, DM_BLOCK_MAJOR); if (bufsize < 8) return 0; if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) { printf("sysctlbyname failed"); return 0; } if ((kd = malloc (val_len)) == NULL){ printf("malloc kd info error\n"); return 0; } if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) { printf("sysctlbyname failed kd"); return 0; } for (i = 0, val_len /= sizeof(*kd); i < val_len; i++){ if (kd[i].d_cmajor == dev_major) { major = kd[i].d_bmajor; break; } } dev = MKDEV(major,dev_minor); mode |= S_IFBLK; if ((name = devname(dev,mode)) == NULL) name = get_dev_name(kd[i].d_name, major, dev_minor); r = snprintf(buf, (size_t) bufsize, "/dev/%s",name); free(kd); if (r < 0 || r > bufsize - 1 || name == NULL) return 0; return 1; }
/* Check if major is device-mapper block device major number */ int dm_is_dm_major(uint32_t major) { uint32_t dm_major; nbsd_get_dm_major(&dm_major, DM_BLOCK_MAJOR); if (major == dm_major) return 1; return 0; }
struct dm_ioctl* nbsd_dm_dict_to_dmi(prop_dictionary_t dm_dict,const int cmd) { struct dm_ioctl *dmi; prop_array_t ver; size_t i; int r; char *name, *uuid; uint32_t major,minor; name = NULL; uuid = NULL; minor = 0; nbsd_get_dm_major(&major, DM_BLOCK_MAJOR); if (!(dmi = dm_malloc(DMI_SIZE))) return NULL; memset(dmi,0,DMI_SIZE); prop_dictionary_get_int32(dm_dict, DM_IOCTL_OPEN, &dmi->open_count); prop_dictionary_get_uint32(dm_dict, DM_IOCTL_EVENT, &dmi->event_nr); prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &dmi->flags); prop_dictionary_get_uint32(dm_dict, DM_IOCTL_TARGET_COUNT, &dmi->target_count); if (prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor)) dmi->dev = MKDEV(major, minor); else dmi->dev = 0; /* Copy name and uuid to dm_ioctl. */ if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, (const char **)&name)){ strlcpy(dmi->name, name, DM_NAME_LEN); } else dmi->name[0] = '\0'; if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, (const char **)&uuid)){ strlcpy(dmi->uuid, uuid, DM_UUID_LEN); } else dmi->uuid[0] = '\0'; /* dmi parsing values, size of dmi block and offset to data. */ dmi->data_size = DMI_SIZE; dmi->data_start = sizeof(struct dm_ioctl); /* Get kernel version from dm_dict. */ ver = prop_dictionary_get(dm_dict,DM_IOCTL_VERSION); for(i=0; i<3; i++) prop_array_get_uint32(ver,i,&dmi->version[i]); switch (cmd){ case DM_LIST_VERSIONS: r = dm_list_versions(dm_dict,dmi); if (r >= 0) dmi->target_count = r; break; case DM_LIST_DEVICES: r = dm_list_devices(dm_dict,dmi); if (r >= 0) dmi->target_count = r; break; case DM_TABLE_STATUS: r = dm_table_status(dm_dict,dmi); if (r >= 0) dmi->target_count = r; break; case DM_TABLE_DEPS: r = dm_dev_deps(dm_dict,dmi); if (r >= 0) dmi->target_count = r; break; } return dmi; }
/* * List all available dm devices in system. */ static int dm_list_devices(prop_dictionary_t dm_dict, struct dm_ioctl *dmi) { struct dm_name_list *dml,*odml; prop_array_t targets; prop_dictionary_t target_dict; prop_object_iterator_t iter; uint32_t minor; uint32_t major; char *name; size_t j,slen,rec_size; odml = NULL; name = NULL; minor = 0; j = 0; nbsd_get_dm_major(&major,DM_BLOCK_MAJOR); dml = (struct dm_name_list *)((uint8_t *)dmi + dmi->data_start); if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){ iter = prop_array_iterator(targets); if (!iter) err(EXIT_FAILURE,"dm_list_devices %s",__func__); while((target_dict = prop_object_iterator_next(iter)) != NULL){ prop_dictionary_get_cstring_nocopy(target_dict, DM_DEV_NAME,(const char **)&name); prop_dictionary_get_uint32(target_dict,DM_DEV_DEV,&minor); dml->dev = MKDEV(major,minor); slen = strlen(name) + 1; rec_size = sizeof(struct dm_name_list) + slen + 1; if (rec_size > dmi->data_size) return -ENOMEM; dml->next = rec_size; strlcpy(dml->name,name,slen); odml = dml; dml =(struct dm_name_list *)((uint8_t *)dml + rec_size); j++; } if (odml != NULL) odml->next = 0; } prop_object_iterator_release(iter); return j; }
/* Parse given dm task structure to proplib dictionary. */ static int _flatten(struct dm_task *dmt, prop_dictionary_t dm_dict) { prop_array_t cmd_array; prop_dictionary_t target_spec; struct target *t; size_t len; char type[DM_MAX_TYPE_NAME]; uint32_t major, flags; int count = 0; char *str = NULL; const int (*version)[3]; flags = 0; version = &_cmd_data_v4[dmt->type].version; cmd_array = prop_array_create(); for (t = dmt->head; t; t = t->next) { target_spec = prop_dictionary_create(); prop_dictionary_set_uint64(target_spec,DM_TABLE_START,t->start); prop_dictionary_set_uint64(target_spec,DM_TABLE_LENGTH,t->length); strlcpy(type,t->type,DM_MAX_TYPE_NAME); prop_dictionary_set_cstring(target_spec,DM_TABLE_TYPE,type); prop_dictionary_set_cstring(target_spec,DM_TABLE_PARAMS,t->params); prop_dictionary_get_cstring(target_spec, DM_TABLE_PARAMS, (char **) &str); prop_array_set(cmd_array,count,target_spec); prop_object_release(target_spec); count++; } if (count && (dmt->sector || dmt->message)) { log_error("targets and message are incompatible"); return -1; } if (count && dmt->newname) { log_error("targets and newname are incompatible"); return -1; } if (count && dmt->geometry) { log_error("targets and geometry are incompatible"); return -1; } if (dmt->newname && (dmt->sector || dmt->message)) { log_error("message and newname are incompatible"); return -1; } if (dmt->newname && dmt->geometry) { log_error("geometry and newname are incompatible"); return -1; } if (dmt->geometry && (dmt->sector || dmt->message)) { log_error("geometry and message are incompatible"); return -1; } if (dmt->sector && !dmt->message) { log_error("message is required with sector"); return -1; } if (dmt->newname) len += strlen(dmt->newname) + 1; if (dmt->message) len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1; if (dmt->geometry) len += strlen(dmt->geometry) + 1; nbsd_dmi_add_version((*version), dm_dict); nbsd_get_dm_major(&major, DM_BLOCK_MAJOR); /* * Only devices with major which is equal to netbsd dm major * dm devices in NetBSD can't have more majors then one assigned to dm. */ if (dmt->major != major && dmt->major != -1) return -1; if (dmt->minor >= 0) { flags |= DM_PERSISTENT_DEV_FLAG; prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmt->minor); } /* Set values to dictionary. */ if (dmt->dev_name) prop_dictionary_set_cstring(dm_dict, DM_IOCTL_NAME, dmt->dev_name); if (dmt->uuid) prop_dictionary_set_cstring(dm_dict, DM_IOCTL_UUID, dmt->uuid); if (dmt->type == DM_DEVICE_SUSPEND) flags |= DM_SUSPEND_FLAG; if (dmt->no_flush) flags |= DM_NOFLUSH_FLAG; if (dmt->read_only) flags |= DM_READONLY_FLAG; if (dmt->skip_lockfs) flags |= DM_SKIP_LOCKFS_FLAG; if (dmt->query_inactive_table) { if (_dm_version_minor < 16) log_warn("WARNING: Inactive table query unsupported " "by kernel. It will use live table."); flags |= DM_QUERY_INACTIVE_TABLE_FLAG; } prop_dictionary_set_uint32(dm_dict, DM_IOCTL_FLAGS, flags); prop_dictionary_set_uint32(dm_dict, DM_IOCTL_EVENT, dmt->event_nr); if (dmt->newname) prop_array_set_cstring(cmd_array, 0, dmt->newname); /* Add array for all COMMAND specific data. */ prop_dictionary_set(dm_dict, DM_IOCTL_CMD_DATA, cmd_array); prop_object_release(cmd_array); return 0; }
/* Parse given dm task structure to proplib dictionary. */ static int _flatten(struct dm_task *dmt, libdm_task_t task) { libdm_cmd_t cmd; libdm_table_t table; struct target *t; size_t len; char type[DM_MAX_TYPE_NAME]; uint32_t major, flags; int count = 0; flags = 0; cmd = libdm_cmd_create(); for (t = dmt->head; t; t = t->next) { strlcpy(type,t->type,DM_MAX_TYPE_NAME); table = libdm_table_create(); libdm_table_set_start(t->start, table); libdm_table_set_length(t->length, table); libdm_table_set_target(type, table); libdm_table_set_params(t->params, table); libdm_cmd_set_table(table, cmd); libdm_table_destroy(table); count++; } if (count && (dmt->sector || dmt->message)) { log_error("targets and message are incompatible"); return -1; } if (count && dmt->newname) { log_error("targets and newname are incompatible"); return -1; } if (count && dmt->geometry) { log_error("targets and geometry are incompatible"); return -1; } if (dmt->newname && (dmt->sector || dmt->message)) { log_error("message and newname are incompatible"); return -1; } if (dmt->newname && dmt->geometry) { log_error("geometry and newname are incompatible"); return -1; } if (dmt->geometry && (dmt->sector || dmt->message)) { log_error("geometry and message are incompatible"); return -1; } if (dmt->sector && !dmt->message) { log_error("message is required with sector"); return -1; } if (dmt->newname) len += strlen(dmt->newname) + 1; if (dmt->message) len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1; if (dmt->geometry) len += strlen(dmt->geometry) + 1; nbsd_get_dm_major(&major, DM_BLOCK_MAJOR); /* * Only devices with major which is equal to netbsd dm major * dm devices in NetBSD can't have more majors then one assigned to dm. */ if (dmt->major != major && dmt->major != -1) return -1; if (dmt->minor >= 0) { flags |= DM_PERSISTENT_DEV_FLAG; libdm_task_set_minor(dmt->minor, task); } /* Set values to dictionary. */ if (dmt->dev_name) libdm_task_set_name(dmt->dev_name, task); if (dmt->uuid) libdm_task_set_uuid(dmt->uuid, task); if (dmt->type == DM_DEVICE_SUSPEND) flags |= DM_SUSPEND_FLAG; if (dmt->no_flush) flags |= DM_NOFLUSH_FLAG; if (dmt->read_only) flags |= DM_READONLY_FLAG; if (dmt->skip_lockfs) flags |= DM_SKIP_LOCKFS_FLAG; if (dmt->query_inactive_table) { if (_dm_version_minor < 16) log_warn("WARNING: Inactive table query unsupported " "by kernel. It will use live table."); flags |= DM_QUERY_INACTIVE_TABLE_FLAG; } libdm_task_set_flags(task, flags); // prop_dictionary_set_uint32(dm_dict, DM_IOCTL_EVENT, dmt->event_nr); if (dmt->newname) libdm_dev_set_newname(dmt->newname, cmd); /* Add array for all COMMAND specific data. */ libdm_task_set_cmd(cmd, task); libdm_cmd_destroy(cmd); return 0; }