Beispiel #1
0
static int
dm_get_deferred_remove (char * mapname)
{
	int r = -1;
	struct dm_task *dmt;
	struct dm_info info;

	if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
		return -1;

	if (!dm_task_set_name(dmt, mapname))
		goto out;

	if (!dm_task_run(dmt))
		goto out;

	if (!dm_task_get_info(dmt, &info))
		goto out;

	r = info.deferred_remove;
out:
	dm_task_destroy(dmt);
	return r;
}
/*
 * Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
 */
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
{
	int ret = 0;
	const char *uuid = NULL;
	char *reply_dso = NULL, *reply_uuid = NULL;
	enum dm_event_mask reply_mask = 0;
	struct dm_task *dmt = NULL;
	struct dm_event_daemon_message msg = { 0, 0, NULL };
	struct dm_info info;

	if (!(dmt = _get_device_info(dmevh))) {
		stack;
		return 0;
	}

	uuid = dm_task_get_uuid(dmt);

	if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
			     DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
			      &msg, dmevh->dso, uuid, dmevh->mask, 0))) {
		/* FIXME this will probably horribly break if we get
		   ill-formatted reply */
		ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
	} else {
		ret = -ENOENT;
		goto fail;
	}

	dm_task_destroy(dmt);
	dmt = NULL;

	dm_free(msg.data);
	msg.data = NULL;

	_dm_event_handler_clear_dev_info(dmevh);
	dmevh->uuid = dm_strdup(reply_uuid);
	if (!dmevh->uuid) {
		ret = -ENOMEM;
		goto fail;
	}

	if (!(dmt = _get_device_info(dmevh))) {
		ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
		goto fail;
	}

	dm_event_handler_set_dso(dmevh, reply_dso);
	dm_event_handler_set_event_mask(dmevh, reply_mask);

	dm_free(reply_dso);
	reply_dso = NULL;

	dm_free(reply_uuid);
	reply_uuid = NULL;

	dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
	if (!dmevh->dev_name) {
		ret = -ENOMEM;
		goto fail;
	}

	if (!dm_task_get_info(dmt, &info)) {
		ret = -1;
		goto fail;
	}

	dmevh->major = info.major;
	dmevh->minor = info.minor;

	dm_task_destroy(dmt);

	return ret;

 fail:
	dm_free(msg.data);
	dm_free(reply_dso);
	dm_free(reply_uuid);
	_dm_event_handler_clear_dev_info(dmevh);
	if (dmt)
		dm_task_destroy(dmt);
	return ret;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
0
int era_dm_info(const char *name,
                const char *uuid,
                struct era_dm_info *info,
                size_t name_size, char *name_ptr,
                size_t uuid_size, char *uuid_ptr)
{
	struct dm_task *dmt;
	struct dm_info dmi;
	int rc = -1;

	if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
		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 (info)
	{
		info->target_count = dmi.target_count;
		info->open_count = dmi.open_count;
		info->suspended = dmi.suspended;
		info->exists = dmi.exists;
		info->major = dmi.major;
		info->minor = dmi.minor;
	}

	if (dmi.exists && name_size > 0 && name_ptr)
	{
		const char *dm_name;
		size_t dm_name_len;

		dm_name = dm_task_get_name(dmt);
		if (!dm_name)
			goto out;

		dm_name_len = strlen(dm_name);
		if (dm_name_len >= name_size)
		{
			rc = dm_name_len + 1;
			goto out;
		}

		strcpy(name_ptr, dm_name);
	}

	if (dmi.exists && uuid_size > 0 && uuid_ptr)
	{
		const char *dm_uuid;
		size_t dm_uuid_len;

		dm_uuid = dm_task_get_uuid(dmt);
		if (!dm_uuid)
			goto out;

		dm_uuid_len = strlen(dm_uuid);
		if (dm_uuid_len >= uuid_size)
		{
			dm_task_destroy(dmt);
			return dm_uuid_len + 1;
		}

		strcpy(uuid_ptr, dm_uuid);
	}

	rc = 0;
out:
	dm_task_destroy(dmt);
	return rc;
}
Beispiel #7
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;
}
Beispiel #8
0
int dm_create_device(const char *name,
		     const char *device,
		     const char *cipher,
		     const char *type,
		     const char *uuid,
		     uint64_t size,
		     uint64_t skip,
		     uint64_t offset,
		     size_t key_size,
		     const char *key,
		     int read_only,
		     int reload)
{
	struct dm_task *dmt = NULL;
	struct dm_info dmi;
	char *params = NULL;
	char *error = NULL;
	char dev_uuid[DM_UUID_LEN] = {0};
	int r = -EINVAL;
	uint32_t read_ahead = 0;
	uint32_t cookie = 0;
	uint16_t udev_flags = 0;

	params = get_params(device, skip, offset, cipher, key_size, key);
	if (!params)
		goto out_no_removal;

	if (type && !strncmp(type, "TEMP", 4))
		udev_flags = CRYPT_TEMP_UDEV_FLAGS;

	/* All devices must have DM_UUID, only resize on old device is exception */
	if (reload) {
		if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
			goto out_no_removal;

		if (!dm_task_set_name(dmt, name))
			goto out_no_removal;
	} else {
		dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid));

		if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
			goto out_no_removal;

		if (!dm_task_set_name(dmt, name))
			goto out_no_removal;

		if (!dm_task_set_uuid(dmt, dev_uuid))
			goto out_no_removal;

		if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, udev_flags))
			goto out_no_removal;
	}

	if (read_only && !dm_task_set_ro(dmt))
		goto out_no_removal;
	if (!dm_task_add_target(dmt, 0, size, DM_CRYPT_TARGET, params))
		goto out_no_removal;

#ifdef DM_READ_AHEAD_MINIMUM_FLAG
	if (_dev_read_ahead(device, &read_ahead) &&
	    !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
		goto out_no_removal;
#endif

	if (!dm_task_run(dmt))
		goto out_no_removal;

	if (reload) {
		dm_task_destroy(dmt);
		if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
			goto out;
		if (!dm_task_set_name(dmt, name))
			goto out;
		if (uuid && !dm_task_set_uuid(dmt, dev_uuid))
			goto out;
		if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, udev_flags))
			goto out;
		if (!dm_task_run(dmt))
			goto out;
	}

	if (!dm_task_get_info(dmt, &dmi))
		goto out;

	r = 0;
out:
	if (_dm_use_udev()) {
		(void)dm_udev_wait(cookie);
		cookie = 0;
	}

	if (r < 0 && !reload) {
		if (get_error())
			error = strdup(get_error());

		dm_remove_device(name, 0, 0);

		if (error) {
			set_error(error);
			free(error);
		}
	}

out_no_removal:
	if (cookie && _dm_use_udev())
		(void)dm_udev_wait(cookie);

	if (params)
		safe_free(params);
	if (dmt)
		dm_task_destroy(dmt);

	dm_task_update_nodes();
	return r;
}