示例#1
0
/* Run dm command which is descirbed in dm_task structure. */
int dm_task_run(struct dm_task *dmt)
{
	struct dm_ioctl *dmi;
	unsigned command;

	if ((unsigned) dmt->type >=
	    (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
		log_error("Internal error: unknown device-mapper task %d",
			  dmt->type);
		return 0;
	}

	command = _cmd_data_v4[dmt->type].cmd;

	/* Old-style creation had a table supplied */
	if (dmt->type == DM_DEVICE_CREATE && dmt->head)
		return _create_and_load_v4(dmt);

	if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
	    !dmt->uuid && dmt->major <= 0)
		return _mknodes_v4(dmt);

	if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)
		return _reload_with_suppression_v4(dmt);

	if (!_open_control())
		return 0;

	if (!(dmi = _do_dm_ioctl(dmt, command)))
		return 0;

	switch (dmt->type) {
	case DM_DEVICE_CREATE:
		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
		    dmt->uid, dmt->gid, dmt->mode, 0);
		break;

	case DM_DEVICE_REMOVE:
		/* FIXME Kernel needs to fill in dmi->name */
		if (dmt->dev_name)
			rm_dev_node(dmt->dev_name, 0);
		break;

	case DM_DEVICE_RENAME:
		/* FIXME Kernel needs to fill in dmi->name */
		if (dmt->dev_name)
			rename_dev_node(dmt->dev_name, dmt->newname, 0);
		break;

	case DM_DEVICE_RESUME:
		/* FIXME Kernel needs to fill in dmi->name */
		set_dev_node_read_ahead(dmt->dev_name, dmt->read_ahead,
					dmt->read_ahead_flags);
		break;

	case DM_DEVICE_MKNODES:
		if (dmi->flags & DM_EXISTS_FLAG)
			add_dev_node(dmi->name, MAJOR(dmi->dev),
				     MINOR(dmi->dev),
			    dmt->uid, dmt->gid, dmt->mode, 0);
		else if (dmt->dev_name)
			rm_dev_node(dmt->dev_name, 0);
		break;

	case DM_DEVICE_STATUS:
	case DM_DEVICE_TABLE:
	case DM_DEVICE_WAITEVENT:
		if (!_unmarshal_status(dmt, dmi))
			goto bad;
		break;
	}

	/* Was structure reused? */
	if (dmt->dmi.v4)
		dm_free(dmt->dmi.v4);

	dmt->dmi.v4 = dmi;
	return 1;

      bad:
	dm_free(dmi);
	return 0;
}
static int _dm_task_run_v1(struct dm_task *dmt)
{
	struct dm_ioctl_v1 *dmi;
	unsigned int command;

	dmi = _flatten_v1(dmt);
	if (!dmi) {
		log_error("Couldn't create ioctl argument.");
		return 0;
	}

	if (!_open_control())
		return 0;

	if ((unsigned) dmt->type >=
	    (sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) {
		log_error(INTERNAL_ERROR "unknown device-mapper task %d",
			  dmt->type);
		goto bad;
	}

	command = _cmd_data_v1[dmt->type].cmd;

	if (dmt->type == DM_DEVICE_TABLE)
		dmi->flags |= DM_STATUS_TABLE_FLAG;

	if (dmt->new_uuid) {
		log_error("Changing UUID is not supported by kernel.");
		goto bad;
	}

	log_debug("dm %s %s %s%s%s [%u]", _cmd_data_v1[dmt->type].name,
		  dmi->name, dmi->uuid, dmt->newname ? " " : "",
		  dmt->newname ? dmt->newname : "",
		  dmi->data_size);
	if (dmt->type == DM_DEVICE_LIST) {
		if (!_dm_names_v1(dmi))
			goto bad;
	} 
#ifdef DM_IOCTLS
	else if (ioctl(_control_fd, command, dmi) < 0) {
		if (_log_suppress)
			log_verbose("device-mapper: %s ioctl failed: %s", 
				    _cmd_data_v1[dmt->type].name,
				    strerror(errno));
		else
			log_error("device-mapper: %s ioctl failed: %s",
				  _cmd_data_v1[dmt->type].name,
				  strerror(errno));
		goto bad;
	}
#else /* Userspace alternative for testing */
#endif

	if (dmi->flags & DM_BUFFER_FULL_FLAG)
		/* FIXME Increase buffer size and retry operation (if query) */
		log_error("WARNING: libdevmapper buffer too small for data");

	switch (dmt->type) {
	case DM_DEVICE_CREATE:
		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
			     dmt->uid, dmt->gid, dmt->mode, 0);
		break;

	case DM_DEVICE_REMOVE:
		rm_dev_node(dmt->dev_name, 0);
		break;

	case DM_DEVICE_RENAME:
		rename_dev_node(dmt->dev_name, dmt->newname, 0);
		break;

	case DM_DEVICE_MKNODES:
		if (dmi->flags & DM_EXISTS_FLAG)
			add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
				     MINOR(dmi->dev), dmt->uid,
				     dmt->gid, dmt->mode, 0);
		else
			rm_dev_node(dmt->dev_name, 0);
		break;

	case DM_DEVICE_STATUS:
	case DM_DEVICE_TABLE:
		if (!_unmarshal_status_v1(dmt, dmi))
			goto bad;
		break;

	case DM_DEVICE_SUSPEND:
	case DM_DEVICE_RESUME:
		dmt->type = DM_DEVICE_INFO;
		if (!dm_task_run(dmt))
			goto bad;
		_dm_zfree_dmi_v1(dmi);	/* We'll use what info returned */
		return 1;
	}

	dmt->dmi.v1 = dmi;
	return 1;

      bad:
	_dm_zfree_dmi_v1(dmi);
	return 0;
}
示例#3
0
/*
 * This function is heart of NetBSD libdevmapper-> device-mapper kernel protocol
 * It creates proplib_dictionary from dm task structure and sends it to NetBSD
 * kernel driver. After succesfull ioctl it create dmi structure from returned
 * proplib dictionary. This way I keep number of changes in NetBSD version of
 * libdevmapper as small as posible.
 */
static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command)
{
	struct dm_ioctl *dmi;
	prop_dictionary_t dm_dict_in, dm_dict_out;
	
	uint32_t flags;

	dm_dict_in = NULL;
	
	dm_dict_in = prop_dictionary_create(); /* Dictionary send to kernel */
	dm_dict_out = prop_dictionary_create(); /* Dictionary received from kernel */

	/* Set command name to dictionary */
	prop_dictionary_set_cstring(dm_dict_in, DM_IOCTL_COMMAND,
	    _cmd_data_v4[dmt->type].name);

	/* Parse dmi from libdevmapper to dictionary */
	if (_flatten(dmt, dm_dict_in) < 0)
		goto bad;

	prop_dictionary_get_uint32(dm_dict_in, DM_IOCTL_FLAGS, &flags);
		
	if (dmt->type == DM_DEVICE_TABLE)
		flags |= DM_STATUS_TABLE_FLAG;

	if (dmt->no_open_count)
		flags |= DM_SKIP_BDGET_FLAG;

	flags |= DM_EXISTS_FLAG;
	
	/* Set flags to dictionary. */
	prop_dictionary_set_uint32(dm_dict_in,DM_IOCTL_FLAGS,flags);
	
	prop_dictionary_externalize_to_file(dm_dict_in,"/tmp/test_in");
	
	log_very_verbose("Ioctl type  %s --- flags %d",_cmd_data_v4[dmt->type].name,flags);
	//printf("name %s, major %d minor %d\n uuid %s\n", 
        //dm_task_get_name(dmt), dmt->minor, dmt->major, dm_task_get_uuid(dmt));
	/* Send dictionary to kernel and wait for reply. */
#ifdef RUMP_ACTION
	struct plistref prefp;
	int err;
	prop_dictionary_externalize_to_pref(dm_dict_in, &prefp);

	if (rump_sys_ioctl(_control_fd, NETBSD_DM_IOCTL, &prefp) != 0) {

		dm_dict_out = prop_dictionary_internalize(prefp.pref_plist);
#else	
	if (prop_dictionary_sendrecv_ioctl(dm_dict_in,_control_fd,
		NETBSD_DM_IOCTL,&dm_dict_out) != 0) {
#endif
		if (errno == ENOENT &&
		    ((dmt->type == DM_DEVICE_INFO) ||
			(dmt->type == DM_DEVICE_MKNODES) ||
			(dmt->type == DM_DEVICE_STATUS))) {

			/*
			 * Linux version doesn't fail when ENOENT is returned
			 * for nonexisting device after info, deps, mknodes call.
			 * It returns dmi sent to kernel with DM_EXISTS_FLAG = 0;
			 */
			
			dmi = nbsd_dm_dict_to_dmi(dm_dict_in,_cmd_data_v4[dmt->type].cmd);

			dmi->flags &= ~DM_EXISTS_FLAG; 

			prop_object_release(dm_dict_in);
			prop_object_release(dm_dict_out);

			goto out;
		} else {
			log_error("ioctl %s call failed with errno %d\n", 
					  _cmd_data_v4[dmt->type].name, errno);

			prop_object_release(dm_dict_in);
			prop_object_release(dm_dict_out);

			goto bad;
		}
	}

#ifdef RUMP_ACTION
	dm_dict_out = prop_dictionary_internalize(prefp.pref_plist);
#endif	
	prop_dictionary_externalize_to_file(dm_dict_out,"/tmp/test_out");

	/* Parse kernel dictionary to dmi structure and return it to libdevmapper. */
	dmi = nbsd_dm_dict_to_dmi(dm_dict_out,_cmd_data_v4[dmt->type].cmd);

	prop_object_release(dm_dict_in);
	prop_object_release(dm_dict_out);
out:	
	return dmi;
bad:
	return NULL;
}

/* Create new edvice nodes in mapper/ dir. */
void dm_task_update_nodes(void)
{
	update_devs();
}

/* Run dm command which is descirbed in dm_task structure. */
int dm_task_run(struct dm_task *dmt)
{
	struct dm_ioctl *dmi;
	unsigned command;

	if ((unsigned) dmt->type >=
	    (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
		log_error("Internal error: unknown device-mapper task %d",
			  dmt->type);
		return 0;
	}

	command = _cmd_data_v4[dmt->type].cmd;

	/* Old-style creation had a table supplied */
	if (dmt->type == DM_DEVICE_CREATE && dmt->head)
		return _create_and_load_v4(dmt);

	if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
	    !dmt->uuid && dmt->major <= 0)
		return _mknodes_v4(dmt);

	if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)
		return _reload_with_suppression_v4(dmt);
	
	if (!_open_control())
		return 0;

	if (!(dmi = _do_dm_ioctl(dmt, command)))
		return 0;

	switch (dmt->type) {
	case DM_DEVICE_CREATE:
		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
		    dmt->uid, dmt->gid, dmt->mode, 0);
		break;

	case DM_DEVICE_REMOVE:
		/* FIXME Kernel needs to fill in dmi->name */
		if (dmt->dev_name)
			rm_dev_node(dmt->dev_name, 0);
		break;

	case DM_DEVICE_RENAME:
		/* FIXME Kernel needs to fill in dmi->name */
		if (dmt->dev_name)
			rename_dev_node(dmt->dev_name, dmt->newname, 0);
		break;

	case DM_DEVICE_RESUME:
		/* FIXME Kernel needs to fill in dmi->name */
		set_dev_node_read_ahead(dmt->dev_name, dmt->read_ahead,
					dmt->read_ahead_flags);
		break;
	
	case DM_DEVICE_MKNODES:
		if (dmi->flags & DM_EXISTS_FLAG)
			add_dev_node(dmi->name, MAJOR(dmi->dev),
				     MINOR(dmi->dev),
			    dmt->uid, dmt->gid, dmt->mode, 0);
		else if (dmt->dev_name)
			rm_dev_node(dmt->dev_name, 0);
		break;

	case DM_DEVICE_STATUS:
	case DM_DEVICE_TABLE:
	case DM_DEVICE_WAITEVENT:
		if (!_unmarshal_status(dmt, dmi))
			goto bad;
		break;
	}

	/* Was structure reused? */
	if (dmt->dmi.v4)
		dm_free(dmt->dmi.v4);

	dmt->dmi.v4 = dmi;
	return 1;

      bad:
	dm_free(dmi);
	return 0;
}

void dm_lib_release(void)
{
	if (_control_fd != -1) {
		close(_control_fd);
		_control_fd = -1;
	}
	update_devs();
}

void dm_lib_exit(void)
{
	dm_lib_release();
	dm_dump_memory();
	_version_ok = 1;
	_version_checked = 0;
}