/* * 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 int _error_device(const char *name, size_t size) { struct dm_task *dmt; int r = 0; if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) return 0; if (!dm_task_set_name(dmt, name)) goto error; if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", "")) goto error; if (!dm_task_set_ro(dmt)) goto error; if (!dm_task_no_open_count(dmt)) goto error; if (!dm_task_run(dmt)) goto error; if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) { _dm_simple(DM_DEVICE_CLEAR, name, 0); goto error; } r = 1; error: dm_task_destroy(dmt); return r; }
extern int dm_flush_maps (void) { int r = 0; struct dm_task *dmt; struct dm_names *names; unsigned next = 0; if (!(dmt = dm_task_create (DM_DEVICE_LIST))) return 0; dm_task_no_open_count(dmt); if (!dm_task_run (dmt)) goto out; if (!(names = dm_task_get_names (dmt))) goto out; if (!names->dev) goto out; do { r |= dm_suspend_and_flush_map(names->name); next = names->next; names = (void *) names + next; } while (next); out: dm_task_destroy (dmt); return r; }
int dm_message(const char * mapname, char * message) { int r = 1; struct dm_task *dmt; if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG))) return 1; if (!dm_task_set_name(dmt, mapname)) goto out; if (!dm_task_set_sector(dmt, 0)) goto out; if (!dm_task_set_message(dmt, message)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; r = 0; out: if (r) condlog(0, "DM message failed [%s]", message); dm_task_destroy(dmt); return r; }
static int _info_run(const char *name, const char *dlid, struct dm_info *info, uint32_t *read_ahead, int mknodes, int with_open_count, int with_read_ahead, uint32_t major, uint32_t minor) { int r = 0; struct dm_task *dmt; int dmtask; dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO; if (!(dmt = _setup_task(mknodes ? name : NULL, dlid, 0, dmtask, major, minor))) return_0; if (!with_open_count) 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)) goto_out; if (with_read_ahead && info->exists) { if (!dm_task_get_read_ahead(dmt, read_ahead)) goto_out; } else if (read_ahead) *read_ahead = DM_READ_AHEAD_NONE; r = 1; out: dm_task_destroy(dmt); return r; }
int dm_geteventnr (char *name) { struct dm_task *dmt; struct dm_info info; int event = -1; if (!(dmt = dm_task_create(DM_DEVICE_INFO))) return -1; 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)) goto out; if (info.exists) event = info.event_nr; out: dm_task_destroy(dmt); return event; }
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; }
extern int dm_map_present (const char * str) { int r = 0; struct dm_task *dmt; struct dm_info info; if (!(dmt = dm_task_create(DM_DEVICE_INFO))) return 0; if (!dm_task_set_name(dmt, str)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &info)) goto out; if (info.exists) r = 1; out: dm_task_destroy(dmt); return r; }
int dm_addmap(int task, const char *name, const char *target, const char *params, uint64_t size, int ro, const char *uuid, int part, mode_t mode, uid_t uid, gid_t gid) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; #ifdef LIBDM_API_COOKIE uint32_t cookie = 0; uint16_t udev_flags = 0; #endif if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, name)) goto addout; if (!dm_task_add_target (dmt, 0, size, target, params)) goto addout; if (ro && !dm_task_set_ro (dmt)) goto addout; if (task == DM_DEVICE_CREATE && uuid) { prefixed_uuid = make_prefixed_uuid(part, uuid); if (prefixed_uuid == NULL) goto addout; if (!dm_task_set_uuid(dmt, prefixed_uuid)) goto addout; } if (!dm_task_set_mode(dmt, mode)) goto addout; if (!dm_task_set_uid(dmt, uid)) goto addout; if (!dm_task_set_gid(dmt, gid)) goto addout; dm_task_no_open_count(dmt); #ifdef LIBDM_API_COOKIE if (!udev_sync) udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK; if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto addout; #endif r = dm_task_run (dmt); #ifdef LIBDM_API_COOKIE if (task == DM_DEVICE_CREATE) dm_udev_wait(cookie); #endif addout: dm_task_destroy (dmt); free(prefixed_uuid); return r; }
char * dm_mapname(int major, int minor) { char * response = NULL; const char *map; struct dm_task *dmt; int r; int loop = MAX_WAIT * LOOPS_PER_SEC; if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) return NULL; if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) goto bad; dm_task_no_open_count(dmt); /* * device map might not be ready when we get here from * daemon uev_trigger -> uev_add_map */ while (--loop) { r = dm_task_run(dmt); if (r) break; usleep(1000 * 1000 / LOOPS_PER_SEC); } if (!r) { condlog(0, "%i:%i: timeout fetching map name", major, minor); goto bad; } map = dm_task_get_name(dmt); if (map && strlen(map)) response = STRDUP((char *)dm_task_get_name(dmt)); dm_task_destroy(dmt); return response; bad: dm_task_destroy(dmt); condlog(0, "%i:%i: error fetching map name", major, minor); return NULL; }
/* 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; }
int dm_drv_version (unsigned int * version, char * str) { int r = 2; struct dm_task *dmt; struct dm_versions *target; struct dm_versions *last_target; unsigned int *v; version[0] = 0; version[1] = 0; version[2] = 0; if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) return 1; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) { condlog(0, "Can not communicate with kernel DM"); goto out; } target = dm_task_get_versions(dmt); do { last_target = target; if (!strncmp(str, target->name, strlen(str))) { r = 1; break; } target = (void *) target + target->next; } while (last_target != target); if (r == 2) { condlog(0, "DM %s kernel driver not loaded", str); goto out; } v = target->version; version[0] = v[0]; version[1] = v[1]; version[2] = v[2]; r = 0; 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 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; }
int dm_get_info (char * mapname, struct dm_info ** dmi) { int r = 1; struct dm_task *dmt = NULL; if (!mapname) return 1; if (!*dmi) *dmi = alloc_dminfo(); if (!*dmi) return 1; if (!(dmt = dm_task_create(DM_DEVICE_INFO))) goto out; if (!dm_task_set_name(dmt, mapname)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, *dmi)) goto out; r = 0; out: if (r) { memset(*dmi, 0, sizeof(struct dm_info)); FREE(*dmi); *dmi = NULL; } if (dmt) 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 dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) { int r = 0; int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || task == DM_DEVICE_REMOVE)); uint32_t cookie = 0; struct dm_task *dmt; if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, name)) goto out; dm_task_no_open_count(dmt); dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ #ifdef LIBDM_API_FLUSH if (no_flush) dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ #endif #ifdef LIBDM_API_DEFERRED if (do_deferred(deferred_remove)) dm_task_deferred_remove(dmt); #endif if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK | udev_flags)) goto out; r = dm_task_run (dmt); if (udev_wait_flag) dm_udev_wait(cookie); out: dm_task_destroy (dmt); return r; }
int dm_simplecmd(int task, const char *name, int no_flush, uint16_t udev_flags) { int r = 0; int udev_wait_flag = (task == DM_DEVICE_RESUME || task == DM_DEVICE_REMOVE); #ifdef LIBDM_API_COOKIE uint32_t cookie = 0; #endif struct dm_task *dmt; if (!(dmt = dm_task_create(task))) return 0; if (!dm_task_set_name(dmt, name)) goto out; dm_task_no_open_count(dmt); dm_task_skip_lockfs(dmt); if (no_flush) dm_task_no_flush(dmt); #ifdef LIBDM_API_COOKIE if (!udev_sync) udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK; if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto out; #endif r = dm_task_run(dmt); #ifdef LIBDM_API_COOKIE if (udev_wait_flag) dm_udev_wait(cookie); #endif out: dm_task_destroy(dmt); return r; }
static int virStorageBackendGetMaps(virStoragePoolObjPtr pool) { int retval = 0; struct dm_task *dmt = NULL; struct dm_names *names = NULL; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) { retval = 1; goto out; } dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) { retval = 1; goto out; } if (!(names = dm_task_get_names(dmt))) { retval = 1; goto out; } if (!names->dev) { /* No devices found */ goto out; } virStorageBackendCreateVols(pool, names); out: if (dmt != NULL) { dm_task_destroy (dmt); } return retval; }
static int dm_map_present(char *str, char **uuid) { int r = 0; struct dm_task *dmt; const char *uuidtmp; struct dm_info info; if (uuid) *uuid = NULL; if (!(dmt = dm_task_create(DM_DEVICE_INFO))) return 0; if (!dm_task_set_name(dmt, str)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &info)) goto out; if (!info.exists) goto out; r = 1; if (uuid) { uuidtmp = dm_task_get_uuid(dmt); if (uuidtmp && strlen(uuidtmp)) *uuid = strdup(uuidtmp); } out: dm_task_destroy(dmt); return r; }
int dm_prereq(char * str, int x, int y, int z) { int r = 1; struct dm_task *dmt; struct dm_versions *target; struct dm_versions *last_target; if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) return 1; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; target = dm_task_get_versions(dmt); /* Fetch targets and print 'em */ do { last_target = target; if (!strncmp(str, target->name, strlen(str)) && /* dummy prereq on multipath version */ target->version[0] >= x && target->version[1] >= y && target->version[2] >= z ) r = 0; target = (void *) target + target->next; } while (last_target != target); out: dm_task_destroy(dmt); return r; }
static int do_foreach_partmaps (const char * mapname, int (*partmap_func)(const char *, void *), void *data) { struct dm_task *dmt; struct dm_names *names; unsigned next = 0; char params[PARAMS_SIZE]; unsigned long long size; char dev_t[32]; int r = 1; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) return 1; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!(names = dm_task_get_names(dmt))) goto out; if (!names->dev) { r = 0; /* this is perfectly valid */ goto out; } if (dm_dev_t(mapname, &dev_t[0], 32)) goto out; do { if ( /* * if devmap target is "linear" */ (dm_type(names->name, TGT_PART) > 0) && /* * and both uuid end with same suffix starting * at UUID_PREFIX */ (!dm_compare_uuid(names->name, mapname)) && /* * and we can fetch the map table from the kernel */ !dm_get_map(names->name, &size, ¶ms[0]) && /* * and the table maps over the multipath map */ strstr(params, dev_t) ) { if (partmap_func(names->name, data) != 0) goto out; } next = names->next; names = (void *) names + next; } while (next); r = 0; out: dm_task_destroy (dmt); return r; }
/* * returns the reschedule delay * negative means *stop* */ int waiteventloop (struct event_thread *waiter) { sigset_t set; int event_nr; int r; if (!waiter->event_nr) waiter->event_nr = dm_geteventnr(waiter->mapname); if (!(waiter->dmt = dm_task_create(DM_DEVICE_WAITEVENT))) { condlog(0, "%s: devmap event #%i dm_task_create error", waiter->mapname, waiter->event_nr); return 1; } if (!dm_task_set_name(waiter->dmt, waiter->mapname)) { condlog(0, "%s: devmap event #%i dm_task_set_name error", waiter->mapname, waiter->event_nr); dm_task_destroy(waiter->dmt); return 1; } if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt, waiter->event_nr)) { condlog(0, "%s: devmap event #%i dm_task_set_event_nr error", waiter->mapname, waiter->event_nr); dm_task_destroy(waiter->dmt); return 1; } dm_task_no_open_count(waiter->dmt); /* accept wait interruption */ set = unblock_signals(); /* wait */ r = dm_task_run(waiter->dmt); /* wait is over : event or interrupt */ pthread_sigmask(SIG_SETMASK, &set, NULL); if (!r) /* wait interrupted by signal */ return -1; dm_task_destroy(waiter->dmt); waiter->dmt = NULL; waiter->event_nr++; /* * upon event ... */ while (1) { condlog(3, "%s: devmap event #%i", waiter->mapname, waiter->event_nr); /* * event might be : * * 1) a table reload, which means our mpp structure is * obsolete : refresh it through update_multipath() * 2) a path failed by DM : mark as such through * update_multipath() * 3) map has gone away : stop the thread. * 4) a path reinstate : nothing to do * 5) a switch group : nothing to do */ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock); lock(waiter->vecs->lock); r = update_multipath(waiter->vecs, waiter->mapname); lock_cleanup_pop(waiter->vecs->lock); if (r) { condlog(2, "%s: event checker exit", waiter->mapname); return -1; /* stop the thread */ } event_nr = dm_geteventnr(waiter->mapname); if (waiter->event_nr == event_nr) return 1; /* upon problem reschedule 1s later */ waiter->event_nr = event_nr; } return -1; /* never reach there */ }
static int dm_addmap (int task, const char *target, struct multipath *mpp, char * params, int ro) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; uint32_t cookie = 0; if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, mpp->alias)) goto addout; if (!dm_task_add_target (dmt, 0, mpp->size, target, params)) goto addout; if (ro) dm_task_set_ro(dmt); if (task == DM_DEVICE_CREATE) { if (strlen(mpp->wwid) > 0) { prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(mpp->wwid) + 1); if (!prefixed_uuid) { condlog(0, "cannot create prefixed uuid : %s", strerror(errno)); goto addout; } sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid); if (!dm_task_set_uuid(dmt, prefixed_uuid)) goto freeout; } dm_task_skip_lockfs(dmt); #ifdef LIBDM_API_FLUSH dm_task_no_flush(dmt); #endif } if (mpp->attribute_flags & (1 << ATTR_MODE) && !dm_task_set_mode(dmt, mpp->mode)) goto freeout; if (mpp->attribute_flags & (1 << ATTR_UID) && !dm_task_set_uid(dmt, mpp->uid)) goto freeout; if (mpp->attribute_flags & (1 << ATTR_GID) && !dm_task_set_gid(dmt, mpp->gid)) goto freeout; condlog(4, "%s: %s [0 %llu %s %s]", mpp->alias, task == DM_DEVICE_RELOAD ? "reload" : "addmap", mpp->size, target, params); dm_task_no_open_count(dmt); if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK)) goto freeout; r = dm_task_run (dmt); if (task == DM_DEVICE_CREATE) dm_udev_wait(cookie); freeout: if (prefixed_uuid) FREE(prefixed_uuid); addout: 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 dm_get_maps (vector mp) { struct multipath * mpp; int r = 1; struct dm_task *dmt; struct dm_names *names; unsigned next = 0; if (!mp) return 1; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) return 1; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!(names = dm_task_get_names(dmt))) goto out; if (!names->dev) { r = 0; /* this is perfectly valid */ goto out; } do { if (!dm_is_mpath(names->name)) goto next; mpp = alloc_multipath(); if (!mpp) goto out; mpp->alias = STRDUP(names->name); if (!mpp->alias) goto out1; if (dm_get_map(names->name, &mpp->size, NULL)) goto out1; dm_get_uuid(names->name, mpp->wwid); dm_get_info(names->name, &mpp->dmi); if (!vector_alloc_slot(mp)) goto out1; vector_set_slot(mp, mpp); mpp = NULL; next: next = names->next; names = (void *) names + next; } while (next); r = 0; goto out; out1: free_multipath(mpp, KEEP_PATHS); out: dm_task_destroy (dmt); return r; }