Esempio n. 1
0
/*
 * Return actual state of device to libdevmapper.
 */
int
dm_dev_status_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	const char *name, *uuid;
	uint32_t flags, j, minor;

	name = NULL;
	uuid = NULL;
	flags = 0;
	j = 0;

	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor);

	if ((dmv = dm_dev_lookup(name, uuid, minor)) == NULL) {
		DM_REMOVE_FLAG(flags, DM_EXISTS_FLAG);
		return ENOENT;
	}
	dm_dbg_print_flags(dmv->flags);

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_OPEN, dmv->table_head.io_cnt);
	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);
	prop_dictionary_set_cstring(dm_dict, DM_IOCTL_UUID, dmv->uuid);

	if (dmv->flags & DM_SUSPEND_FLAG)
		DM_ADD_FLAG(flags, DM_SUSPEND_FLAG);

	/*
	 * Add status flags for tables I have to check both active and
	 * inactive tables.
	 */
	if ((j = dm_table_get_target_count(&dmv->table_head, DM_TABLE_ACTIVE))) {
		DM_ADD_FLAG(flags, DM_ACTIVE_PRESENT_FLAG);
	} else
		DM_REMOVE_FLAG(flags, DM_ACTIVE_PRESENT_FLAG);

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_TARGET_COUNT, j);

	if (dm_table_get_target_count(&dmv->table_head, DM_TABLE_INACTIVE))
		DM_ADD_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
	else
		DM_REMOVE_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);

	dm_dev_unbusy(dmv);

	return 0;
}
Esempio n. 2
0
/*
 * Set only flag to suggest that device is suspended. This call is
 * not supported in NetBSD.
 *
 */
int
dm_dev_suspend_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	const char *name, *uuid;
	uint32_t flags, minor;

	name = NULL;
	uuid = NULL;
	flags = 0;

	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor);

	if ((dmv = dm_dev_lookup(name, uuid, minor)) == NULL) {
		DM_REMOVE_FLAG(flags, DM_EXISTS_FLAG);
		return ENOENT;
	}
	atomic_set_int(&dmv->flags, DM_SUSPEND_FLAG);

	dm_dbg_print_flags(dmv->flags);

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_OPEN, dmv->table_head.io_cnt);
	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_FLAGS, dmv->flags);
	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);

	dm_dev_unbusy(dmv);

	/* Add flags to dictionary flag after dmv -> dict copy */
	DM_ADD_FLAG(flags, DM_EXISTS_FLAG);

	return 0;
}
Esempio n. 3
0
/*
 * Create in-kernel entry for device. Device attributes such as name, uuid are
 * taken from proplib dictionary.
 *
 */
int
dm_dev_create_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	const char *name, *uuid;
	int r, flags;

	r = 0;
	flags = 0;
	name = NULL;
	uuid = NULL;

	/* Get needed values from dictionary. */
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);

	dm_dbg_print_flags(flags);

	/* Lookup name and uuid if device already exist quit. */
	if ((dmv = dm_dev_lookup(name, uuid, -1)) != NULL) {
		DM_ADD_FLAG(flags, DM_EXISTS_FLAG);	/* Device already exists */
		dm_dev_unbusy(dmv);
		return EEXIST;
	}

	r = dm_dev_create(&dmv, name, uuid, flags);
	
	if (r == 0) {
		prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);
		DM_ADD_FLAG(flags, DM_EXISTS_FLAG);
		DM_REMOVE_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
	}

	return r;
}
Esempio n. 4
0
/*
 * Simulate Linux behaviour better and switch tables here and not in
 * dm_table_load_ioctl.
 */
int
dm_dev_resume_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	const char *name, *uuid;
	uint32_t flags, minor;

	name = NULL;
	uuid = NULL;
	flags = 0;

	/*
	 * char *xml; xml = prop_dictionary_externalize(dm_dict);
	 * printf("%s\n",xml);
	 */

	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor);

	/* Remove device from global device list */
	if ((dmv = dm_dev_lookup(name, uuid, minor)) == NULL) {
		DM_REMOVE_FLAG(flags, DM_EXISTS_FLAG);
		return ENOENT;
	}
	atomic_clear_int(&dmv->flags, (DM_SUSPEND_FLAG | DM_INACTIVE_PRESENT_FLAG));
	atomic_set_int(&dmv->flags, DM_ACTIVE_PRESENT_FLAG);

	dm_table_switch_tables(&dmv->table_head);

	DM_ADD_FLAG(flags, DM_EXISTS_FLAG);

	dmsetdiskinfo(dmv->diskp, &dmv->table_head);

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_OPEN, dmv->table_head.io_cnt);
	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_FLAGS, flags);
	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);

	dm_dev_unbusy(dmv);

	/* Destroy inactive table after resume. */
	dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);

	return 0;
}
Esempio n. 5
0
/*
 * Get description of all tables loaded to device from kernel
 * and send it to libdevmapper.
 *
 * Output dictionary for every table:
 *
 * <key>cmd_data</key>
 * <array>
 *   <dict>
 *    <key>type<key>
 *    <string>...</string>
 *
 *    <key>start</key>
 *    <integer>...</integer>
 *
 *    <key>length</key>
 *    <integer>...</integer>
 *
 *    <key>params</key>
 *    <string>...</string>
 *   </dict>
 * </array>
 *
 */
int
dm_table_status_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	dm_table_t *tbl;
	dm_table_entry_t *table_en;

	prop_array_t cmd_array;
	prop_dictionary_t target_dict;

	uint32_t rec_size, minor;

	const char *name, *uuid;
	char *params;
	int flags;
	int table_type;

	dmv = NULL;
	uuid = NULL;
	name = NULL;
	params = NULL;
	flags = 0;
	rec_size = 0;

	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor);

	cmd_array = prop_array_create();

	if ((dmv = dm_dev_lookup(name, uuid, minor)) == NULL) {
		DM_REMOVE_FLAG(flags, DM_EXISTS_FLAG);
		return ENOENT;
	}
	/*
	 * if DM_QUERY_INACTIVE_TABLE_FLAG is passed we need to query
	 * INACTIVE TABLE
	 */
	if (flags & DM_QUERY_INACTIVE_TABLE_FLAG)
		table_type = DM_TABLE_INACTIVE;
	else
		table_type = DM_TABLE_ACTIVE;

	if (dm_table_get_target_count(&dmv->table_head, DM_TABLE_ACTIVE))
		DM_ADD_FLAG(flags, DM_ACTIVE_PRESENT_FLAG);
	else {
		DM_REMOVE_FLAG(flags, DM_ACTIVE_PRESENT_FLAG);

		if (dm_table_get_target_count(&dmv->table_head, DM_TABLE_INACTIVE))
			DM_ADD_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
		else {
			DM_REMOVE_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
		}
	}

	if (dmv->flags & DM_SUSPEND_FLAG)
		DM_ADD_FLAG(flags, DM_SUSPEND_FLAG);

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);

	aprint_debug("Status of device tables: %s--%d\n",
	    name, dmv->table_head.cur_active_table);

	tbl = dm_table_get_entry(&dmv->table_head, table_type);

	SLIST_FOREACH(table_en, tbl, next) {
		target_dict = prop_dictionary_create();
		aprint_debug("%016" PRIu64 ", length %016" PRIu64
		    ", target %s\n", table_en->start, table_en->length,
		    table_en->target->name);

		prop_dictionary_set_uint64(target_dict, DM_TABLE_START,
		    table_en->start);
		prop_dictionary_set_uint64(target_dict, DM_TABLE_LENGTH,
		    table_en->length);

		prop_dictionary_set_cstring(target_dict, DM_TABLE_TYPE,
		    table_en->target->name);

		/* dm_table_get_cur_actv.table ?? */
		prop_dictionary_set_int32(target_dict, DM_TABLE_STAT,
		    dmv->table_head.cur_active_table);

		if (flags & DM_STATUS_TABLE_FLAG) {
			params = table_en->target->status
			    (table_en->target_config);

			if (params != NULL) {
				prop_dictionary_set_cstring(target_dict,
				    DM_TABLE_PARAMS, params);

				kfree(params, M_DM);
			}
		}
		prop_array_add(cmd_array, target_dict);
		prop_object_release(target_dict);
	}
Esempio n. 6
0
/*
 * Load new table/tables to device.
 * Call apropriate target init routine open all physical pdev's and
 * link them to device. For other targets mirror, strip, snapshot
 * etc. also add dependency devices to upcalls list.
 *
 * Load table to inactive slot table are switched in dm_device_resume_ioctl.
 * This simulates Linux behaviour better there should not be any difference.
 *
 */
int
dm_table_load_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	dm_table_entry_t *table_en, *last_table;
	dm_table_t *tbl;
	dm_target_t *target;

	prop_object_iterator_t iter;
	prop_array_t cmd_array;
	prop_dictionary_t target_dict;

	const char *name, *uuid, *type;

	uint32_t flags, ret, minor;

	char *str;

	ret = 0;
	flags = 0;
	name = NULL;
	uuid = NULL;
	dmv = NULL;
	last_table = NULL;
	str = NULL;

	/*
	 * char *xml; xml = prop_dictionary_externalize(dm_dict);
	 * printf("%s\n",xml);
	 */

	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor);

	cmd_array = prop_dictionary_get(dm_dict, DM_IOCTL_CMD_DATA);
	iter = prop_array_iterator(cmd_array);
	dm_dbg_print_flags(flags);

	if ((dmv = dm_dev_lookup(name, uuid, minor)) == NULL) {
		DM_REMOVE_FLAG(flags, DM_EXISTS_FLAG);
		return ENOENT;
	}
	aprint_debug("Loading table to device: %s--%d\n", name,
	    dmv->table_head.cur_active_table);

	/*
	 * I have to check if this table slot is not used by another table list.
	 * if it is used I should free them.
	 */
	if (dmv->flags & DM_INACTIVE_PRESENT_FLAG)
		dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);

	dm_dbg_print_flags(dmv->flags);
	tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_INACTIVE);

	aprint_debug("dmv->name = %s\n", dmv->name);

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);

	while ((target_dict = prop_object_iterator_next(iter)) != NULL) {
		prop_dictionary_get_cstring_nocopy(target_dict,
		    DM_TABLE_TYPE, &type);
		/*
		 * If we want to deny table with 2 or more different
		 * target we should do it here
		 */
		if (((target = dm_target_lookup(type)) == NULL) &&
		    ((target = dm_target_autoload(type)) == NULL)) {
			dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);
			dm_dev_unbusy(dmv);
			return ENOENT;
		}
		if ((table_en = kmalloc(sizeof(dm_table_entry_t),
			    M_DM, M_WAITOK)) == NULL) {
			dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);
			dm_dev_unbusy(dmv);
			dm_target_unbusy(target);
			return ENOMEM;
		}
		prop_dictionary_get_uint64(target_dict, DM_TABLE_START,
		    &table_en->start);
		prop_dictionary_get_uint64(target_dict, DM_TABLE_LENGTH,
		    &table_en->length);

		aprint_debug("dm_ioctl.c... table_en->start = %ju, "
			     "table_en->length = %ju\n",
			     (uintmax_t)table_en->start,
			     (uintmax_t)table_en->length);

		table_en->target = target;
		table_en->dm_dev = dmv;
		table_en->target_config = NULL;

		/*
		 * There is a parameter string after dm_target_spec
		 * structure which  points to /dev/wd0a 284 part of
		 * table. String str points to this text. This can be
		 * null and therefore it should be checked before we try to
		 * use it.
		 */
		prop_dictionary_get_cstring(target_dict,
		    DM_TABLE_PARAMS, &str);

		if (SLIST_EMPTY(tbl))
			/* insert this table to head */
			SLIST_INSERT_HEAD(tbl, table_en, next);
		else
			SLIST_INSERT_AFTER(last_table, table_en, next);

		/*
		 * Params string is different for every target,
		 * therfore I have to pass it to target init
		 * routine and parse parameters there.
		 */
		aprint_debug("DM: str passed in is: %s", str);
		if ((ret = target->init(dmv, &table_en->target_config,
			    str)) != 0) {

			dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);
			dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);
			kfree(str, M_TEMP);

			dm_dev_unbusy(dmv);
			dm_target_unbusy(target);
			return ret;
		}
		last_table = table_en;
		kfree(str, M_TEMP);
	}
	prop_object_iterator_release(iter);

	DM_ADD_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
	atomic_set_int(&dmv->flags, DM_INACTIVE_PRESENT_FLAG);

	dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);

	dm_dev_unbusy(dmv);
#if 0
	dmsetdiskinfo(dmv->diskp, &dmv->table_head);
#endif
	return 0;
}
Esempio n. 7
0
/*
 * Create in-kernel entry for device. Device attributes such as name, uuid are
 * taken from proplib dictionary.
 *
 */
int
dm_dev_create_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	const char *name, *uuid;
	int r, flags;
	device_t devt;

	r = 0;
	flags = 0;
	name = NULL;
	uuid = NULL;

	/* Get needed values from dictionary. */
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);

	dm_dbg_print_flags(flags);

	/* Lookup name and uuid if device already exist quit. */
	if ((dmv = dm_dev_lookup(name, uuid, -1)) != NULL) {
		DM_ADD_FLAG(flags, DM_EXISTS_FLAG);	/* Device already exists */
		dm_dev_unbusy(dmv);
		return EEXIST;
	}
	if ((devt = config_attach_pseudo(&dm_cfdata)) == NULL) {
		aprint_error("Unable to attach pseudo device dm/%s\n", name);
		return (ENOMEM);
	}
	if ((dmv = dm_dev_alloc()) == NULL)
		return ENOMEM;

	if (uuid)
		strncpy(dmv->uuid, uuid, DM_UUID_LEN);
	else
		dmv->uuid[0] = '\0';

	if (name)
		strlcpy(dmv->name, name, DM_NAME_LEN);

	dmv->minor = (uint64_t)atomic_inc_32_nv(&sc_minor_num);
	dmv->flags = 0;		/* device flags are set when needed */
	dmv->ref_cnt = 0;
	dmv->event_nr = 0;
	dmv->dev_type = 0;
	dmv->devt = devt;

	dm_table_head_init(&dmv->table_head);

	mutex_init(&dmv->dev_mtx, MUTEX_DEFAULT, IPL_NONE);
	mutex_init(&dmv->diskp_mtx, MUTEX_DEFAULT, IPL_NONE);
	cv_init(&dmv->dev_cv, "dm_dev");

	if (flags & DM_READONLY_FLAG)
		dmv->flags |= DM_READONLY_FLAG;

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);

	disk_init(dmv->diskp, dmv->name, &dmdkdriver);
	disk_attach(dmv->diskp);

	dmv->diskp->dk_info = NULL;

	if ((r = dm_dev_insert(dmv)) != 0)
		dm_dev_free(dmv);

	DM_ADD_FLAG(flags, DM_EXISTS_FLAG);
	DM_REMOVE_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);

	/* Increment device counter After creating device */
	atomic_inc_32(&dm_dev_counter);

	return r;
}