extern int dm_get_status(char * name, char * outstatus) { int r = 1; struct dm_task *dmt; uint64_t start, length; char *target_type; char *status; if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) return 1; if (!dm_task_set_name(dmt, name)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; /* Fetch 1st target */ dm_get_next_target(dmt, NULL, &start, &length, &target_type, &status); if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE) r = 0; out: if (r) condlog(0, "%s: error getting map status string", name); dm_task_destroy(dmt); return r; }
/* * returns: * 1 : match * 0 : no match * -1 : empty map */ extern int dm_type(const char * name, char * type) { int r = 0; struct dm_task *dmt; uint64_t start, length; char *target_type = NULL; char *params; if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) return 0; if (!dm_task_set_name(dmt, name)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; /* Fetch 1st target */ dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms); if (!target_type) r = -1; else if (!strcmp(target_type, type)) r = 1; out: dm_task_destroy(dmt); return r; }
static gboolean map_is_multipath (const gchar *map_name, GError **error) { struct dm_task *task = NULL; struct dm_info info; guint64 start = 0; guint64 length = 0; gchar *type = NULL; gchar *params = NULL; gboolean ret = FALSE; if (geteuid () != 0) { g_set_error (error, BD_MPATH_ERROR, BD_MPATH_ERROR_NOT_ROOT, "Not running as root, cannot query DM maps"); return FALSE; } task = dm_task_create (DM_DEVICE_STATUS); if (!task) { g_warning ("Failed to create DM task"); g_set_error (error, BD_MPATH_ERROR, BD_MPATH_ERROR_DM_ERROR, "Failed to create DM task"); return FALSE; } if (dm_task_set_name (task, map_name) == 0) { g_set_error (error, BD_MPATH_ERROR, BD_MPATH_ERROR_DM_ERROR, "Failed to create DM task"); dm_task_destroy (task); return FALSE; } if (dm_task_run (task) == 0) { g_set_error (error, BD_MPATH_ERROR, BD_MPATH_ERROR_DM_ERROR, "Failed to run DM task"); dm_task_destroy (task); return FALSE; } if (dm_task_get_info (task, &info) == 0) { g_set_error (error, BD_MPATH_ERROR, BD_MPATH_ERROR_DM_ERROR, "Failed to get task info"); dm_task_destroy (task); return FALSE; } dm_get_next_target(task, NULL, &start, &length, &type, ¶ms); if (g_strcmp0 (type, "multipath") == 0) ret = TRUE; else ret = FALSE; dm_task_destroy (task); return ret; }
int main(int argc, char** argv) { /* * Dump a devices table. First arg should be the device name. * */ char* name; if (argc < 2) { printf("usage: dump_table <device name>\n"); return 1; } else { name = argv[1]; } struct dm_task *dmt; struct dm_info info; struct dm_names *names; uint64_t start, length; char* params, * target_type; void* next = NULL; if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) { printf("could not create dm task\n"); return 1; } if (!_set_task_device(dmt, name, 0)) { printf("device %s may not exist -?\n", name); } if (!dm_task_run(dmt)) { printf("error running task\n"); dm_task_destroy(dmt); return 1; } if (!dm_task_get_info(dmt, &info) || !info.exists) { printf("could not get info for %s\n", name); return 1; } /* not sure about this bit */ do { next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); printf("%" PRIu64 " %" PRIu64 " %s %s\n", start, length, target_type, params); } while(next); dm_task_destroy(dmt); return 0; }
/* FIXME Interface must cope with multiple targets */ static int _status_run(const char *name, const char *uuid, unsigned long long *s, unsigned long long *l, char **t, uint32_t t_size, char **p, uint32_t p_size) { int r = 0; struct dm_task *dmt; struct dm_info info; void *next = NULL; uint64_t start, length; char *type = NULL; char *params = NULL; if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS, 0, 0))) return_0; if (!dm_task_no_open_count(dmt)) log_error("Failed to disable open_count"); if (!dm_task_run(dmt)) goto_out; if (!dm_task_get_info(dmt, &info) || !info.exists) goto_out; do { next = dm_get_next_target(dmt, next, &start, &length, &type, ¶ms); if (type) { *s = start; *l = length; /* Make sure things are null terminated */ strncpy(*t, type, t_size); (*t)[t_size - 1] = '\0'; strncpy(*p, params, p_size); (*p)[p_size - 1] = '\0'; r = 1; /* FIXME Cope with multiple targets! */ break; } } while (next); out: dm_task_destroy(dmt); return r; }
static int virStorageBackendIsMultipath(const char *devname) { int ret = 0; struct dm_task *dmt = NULL; void *next = NULL; uint64_t start, length; char *target_type = NULL; char *params = NULL; dmt = dm_task_create(DM_DEVICE_TABLE); if (dmt == NULL) { ret = -1; goto out; } if (dm_task_set_name(dmt, devname) == 0) { ret = -1; goto out; } dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) { ret = -1; goto out; } dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); if (target_type == NULL) { ret = -1; goto out; } if (STREQ(target_type, "multipath")) { ret = 1; } out: if (dmt != NULL) { dm_task_destroy(dmt); } return ret; }
int dm_status_device(const char *name) { struct dm_task *dmt; struct dm_info dmi; uint64_t start, length; char *target_type, *params; void *next = NULL; int r = -EINVAL; if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) return -EINVAL; if (!dm_task_set_name(dmt, name)) { r = -EINVAL; goto out; } if (!dm_task_run(dmt)) { r = -EINVAL; goto out; } if (!dm_task_get_info(dmt, &dmi)) { r = -EINVAL; goto out; } if (!dmi.exists) { r = -ENODEV; goto out; } next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 || start != 0 || next) r = -EINVAL; else r = (dmi.open_count > 0); out: if (dmt) dm_task_destroy(dmt); return r; }
int lv_has_target_type(struct dm_pool *mem, struct logical_volume *lv, const char *layer, const char *target_type) { int r = 0; char *dlid; struct dm_task *dmt; struct dm_info info; void *next = NULL; uint64_t start, length; char *type = NULL; char *params = NULL; if (!(dlid = build_dm_uuid(mem, lv->lvid.s, layer))) return_0; if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0))) return_0; if (!dm_task_no_open_count(dmt)) log_error("Failed to disable open_count"); if (!dm_task_run(dmt)) goto_out; if (!dm_task_get_info(dmt, &info) || !info.exists) goto_out; do { next = dm_get_next_target(dmt, next, &start, &length, &type, ¶ms); if (type && strncmp(type, target_type, strlen(target_type)) == 0) { if (info.live_table) r = 1; break; } } while (next); out: dm_task_destroy(dmt); return r; }
extern int dm_is_mpath(const char * name) { int r = 0; struct dm_task *dmt; struct dm_info info; uint64_t start, length; char *target_type = NULL; char *params; const char *uuid; if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) return 0; if (!dm_task_set_name(dmt, name)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &info) || !info.exists) goto out; uuid = dm_task_get_uuid(dmt); if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0) goto out; /* Fetch 1st target */ dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms); if (!target_type || strcmp(target_type, TGT_MPATH) != 0) goto out; r = 1; out: dm_task_destroy(dmt); return r; }
extern int dm_get_map(const char * name, unsigned long long * size, char * outparams) { int r = 1; struct dm_task *dmt; uint64_t start, length; char *target_type = NULL; char *params = NULL; if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) return 1; if (!dm_task_set_name(dmt, name)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; /* Fetch 1st target */ dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms); if (size) *size = length; if (!outparams) { r = 0; goto out; } if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE) r = 0; out: dm_task_destroy(dmt); return r; }
static int _percent_run(struct dev_manager *dm, const char *name, const char *dlid, const char *target_type, int wait, const struct logical_volume *lv, float *percent, percent_range_t *overall_percent_range, uint32_t *event_nr, int fail_if_percent_unsupported) { int r = 0; struct dm_task *dmt; struct dm_info info; void *next = NULL; uint64_t start, length; char *type = NULL; char *params = NULL; const struct dm_list *segh = &lv->segments; struct lv_segment *seg = NULL; struct segment_type *segtype; percent_range_t percent_range = 0, combined_percent_range = 0; int first_time = 1; uint64_t total_numerator = 0, total_denominator = 0; *percent = -1; *overall_percent_range = PERCENT_INVALID; if (!(dmt = _setup_task(name, dlid, event_nr, wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0))) return_0; if (!dm_task_no_open_count(dmt)) log_error("Failed to disable open_count"); if (!dm_task_run(dmt)) goto_out; if (!dm_task_get_info(dmt, &info) || !info.exists) goto_out; if (event_nr) *event_nr = info.event_nr; do { next = dm_get_next_target(dmt, next, &start, &length, &type, ¶ms); if (lv) { if (!(segh = dm_list_next(&lv->segments, segh))) { log_error("Number of segments in active LV %s " "does not match metadata", lv->name); goto out; } seg = dm_list_item(segh, struct lv_segment); } if (!type || !params) continue; if (!(segtype = get_segtype_from_string(dm->cmd, target_type))) continue; if (strcmp(type, target_type)) { /* If kernel's type isn't an exact match is it compatible? */ if (!segtype->ops->target_status_compatible || !segtype->ops->target_status_compatible(type)) continue; } if (segtype->ops->target_percent && !segtype->ops->target_percent(&dm->target_state, &percent_range, dm->mem, dm->cmd, seg, params, &total_numerator, &total_denominator)) goto_out; if (first_time) { combined_percent_range = percent_range; first_time = 0; } else combined_percent_range = _combine_percent_ranges(combined_percent_range, percent_range); } while (next); if (lv && (segh = dm_list_next(&lv->segments, segh))) { log_error("Number of segments in active LV %s does not " "match metadata", lv->name); goto out; } if (total_denominator) { *percent = (float) total_numerator *100 / total_denominator; *overall_percent_range = combined_percent_range; } else { *percent = 100; if (first_time) { /* above ->target_percent() was not executed! */ /* FIXME why return PERCENT_100 et. al. in this case? */ *overall_percent_range = PERCENT_100; if (fail_if_percent_unsupported) goto_out; } else *overall_percent_range = combined_percent_range; } log_debug("LV percent: %f", *percent); r = 1; out: dm_task_destroy(dmt); return r; }
int device_is_usable(struct device *dev) { struct dm_task *dmt; struct dm_info info; const char *name, *uuid; uint64_t start, length; char *target_type = NULL; char *params, *vgname = NULL, *lvname, *layer; void *next = NULL; int r = 0; if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) { log_error("Failed to allocate dm_task struct to check dev status"); return 0; } if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1)) goto_out; if (!dm_task_run(dmt)) { log_error("Failed to get state of mapped device"); goto out; } if (!dm_task_get_info(dmt, &info)) goto_out; if (!info.exists || info.suspended) goto out; name = dm_task_get_name(dmt); uuid = dm_task_get_uuid(dmt); /* FIXME Also check for mirror block_on_error and mpath no paths */ /* For now, we exclude all mirrors */ do { next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); /* Skip if target type doesn't match */ if (target_type && !strcmp(target_type, "mirror")) { log_debug("%s: Mirror device not usable.", dev_name(dev)); goto out; } } while (next); /* FIXME Also check dependencies? */ /* Check internal lvm devices */ if (uuid && !strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) { if (!(vgname = dm_strdup(name)) || !dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer)) goto_out; if (lvname && (is_reserved_lvname(lvname) || *layer)) { log_debug("%s: Reserved internal LV device %s/%s%s%s not usable.", dev_name(dev), vgname, lvname, *layer ? "-" : "", layer); goto out; } } r = 1; out: dm_free(vgname); dm_task_destroy(dmt); return r; }
static int _first_status(int task, const char *name, const char *uuid, uint64_t *start, uint64_t *length, size_t target_size, char *target_ptr, size_t params_size, char *params_ptr) { uint64_t a, b; struct dm_task *dmt; struct dm_info dmi; char *tgt, *prm; int rc = -1; if (!(dmt = dm_task_create(task))) return -1; if (name && !dm_task_set_name(dmt, name)) goto out; if (uuid && !dm_task_set_uuid(dmt, uuid)) goto out; if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &dmi)) goto out; if (!dmi.exists) { error(0, "target %s does not exists", name ? name : (uuid ? uuid : "<NULL>")); goto out; } (void)dm_get_next_target(dmt, NULL, &a, &b, &tgt, &prm); if (start) *start = a; if (length) *length = b; if (target_size > 0 && target_ptr) { if (strlen(tgt) >= target_size) { error(0, "too long target name"); goto out; } strcpy(target_ptr, tgt); } if (params_size > 0 && params_ptr) { if (strlen(prm) >= params_size) { error(0, "too long target params"); goto out; } strcpy(params_ptr, prm); } rc = 0; out: dm_task_destroy(dmt); return rc; }
int dm_query_device(const char *name, char **device, uint64_t *size, uint64_t *skip, uint64_t *offset, char **cipher, int *key_size, char **key, int *read_only, int *suspended, char **uuid) { struct dm_task *dmt; struct dm_info dmi; uint64_t start, length, val64; char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3], *tmp_uuid; void *next = NULL; int i, r = -EINVAL; if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) goto out; if (!dm_task_set_name(dmt, name)) goto out; r = -ENODEV; if (!dm_task_run(dmt)) goto out; r = -EINVAL; if (!dm_task_get_info(dmt, &dmi)) goto out; if (!dmi.exists) { r = -ENODEV; goto out; } next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 || start != 0 || next) goto out; if (size) *size = length; rcipher = strsep(¶ms, " "); /* cipher */ if (cipher) *cipher = strdup(rcipher); /* skip */ key_ = strsep(¶ms, " "); if (!params) goto out; val64 = strtoull(params, ¶ms, 10); if (*params != ' ') goto out; params++; if (skip) *skip = val64; /* device */ rdevice = strsep(¶ms, " "); if (device) *device = lookup_dev(rdevice); /*offset */ if (!params) goto out; val64 = strtoull(params, ¶ms, 10); if (*params) goto out; if (offset) *offset = val64; /* key_size */ if (key_size) *key_size = strlen(key_) / 2; /* key */ if (key_size && key) { *key = safe_alloc(*key_size); if (!*key) { r = -ENOMEM; goto out; } buffer[2] = '\0'; for(i = 0; i < *key_size; i++) { memcpy(buffer, &key_[i * 2], 2); (*key)[i] = strtoul(buffer, &endp, 16); if (endp != &buffer[2]) { safe_free(key); *key = NULL; goto out; } } } memset(key_, 0, strlen(key_)); if (read_only) *read_only = dmi.read_only; if (suspended) *suspended = dmi.suspended; if (uuid && (tmp_uuid = (char*)dm_task_get_uuid(dmt)) && !strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN)) *uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN); r = (dmi.open_count > 0); out: if (dmt) dm_task_destroy(dmt); return r; }