Пример #1
0
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;
}
Пример #2
0
/*
 * 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, &params);

	if (!target_type)
		r = -1;
	else if (!strcmp(target_type, type))
		r = 1;

out:
	dm_task_destroy(dmt);
	return r;
}
Пример #3
0
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, &params);
    if (g_strcmp0 (type, "multipath") == 0)
        ret = TRUE;
    else
        ret = FALSE;
    dm_task_destroy (task);

    return ret;
}
Пример #4
0
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, &params);
		printf("%" PRIu64 " %" PRIu64 " %s %s\n", start, length, target_type, params);
	} while(next);


	dm_task_destroy(dmt);

	return 0;
}
Пример #5
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, &params);
		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;
}
Пример #6
0
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, &params);

    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;
}
Пример #7
0
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, &params);
	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;
}
Пример #8
0
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, &params);
		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;
}
Пример #9
0
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, &params);

	if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
		goto out;

	r = 1;
out:
	dm_task_destroy(dmt);
	return r;
}
Пример #10
0
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, &params);

	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;
}
Пример #11
0
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,
					  &params);
		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;
}
Пример #12
0
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, &params);
		/* 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;
}
Пример #13
0
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;
}
Пример #14
0
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, &params);
	if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 ||
	    start != 0 || next)
		goto out;

	if (size)
		*size = length;

	rcipher = strsep(&params, " ");
	/* cipher */
	if (cipher)
		*cipher = strdup(rcipher);

	/* skip */
	key_ = strsep(&params, " ");
	if (!params)
		goto out;
	val64 = strtoull(params, &params, 10);
	if (*params != ' ')
		goto out;
	params++;
	if (skip)
		*skip = val64;

	/* device */
	rdevice = strsep(&params, " ");
	if (device)
		*device = lookup_dev(rdevice);

	/*offset */
	if (!params)
		goto out;
	val64 = strtoull(params, &params, 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;
}