static int _control_device_number(uint32_t *major, uint32_t *minor)
{
	if (!_get_proc_number(PROC_DEVICES, MISC_NAME, major) ||
	    !_get_proc_number(PROC_MISC, DM_NAME, minor)) {
		*major = 0;
		return 0;
	}

	return 1;
}
Esempio n. 2
0
/*
 * FIXME Update bitset in long-running process if dm claims new major numbers.
 */
static int _create_dm_bitset(void)
{
#ifdef DM_IOCTLS
	struct utsname uts;

	if (_dm_bitset || _dm_device_major)
		return 1;

	if (uname(&uts))
		return 0;

	/*
	 * 2.6 kernels are limited to one major number.
	 * Assume 2.4 kernels are patched not to.
	 * FIXME Check _dm_version and _dm_version_minor if 2.6 changes this.
	 */
	if (!strncmp(uts.release, "2.6.", 4))
		_dm_multiple_major_support = 0;

	if (!_dm_multiple_major_support) {
		if (!_get_proc_number(PROC_DEVICES, DM_NAME, &_dm_device_major))
			return 0;
		return 1;
	}

	/* Multiple major numbers supported */
	if (!(_dm_bitset = dm_bitset_create(NULL, NUMBER_OF_MAJORS)))
		return 0;

	if (!_get_proc_number(PROC_DEVICES, DM_NAME, NULL)) {
		dm_bitset_destroy(_dm_bitset);
		_dm_bitset = NULL;
		return 0;
	}

	return 1;
#else
	return 0;
#endif
}
static int _open_control(void)
{
#ifdef DM_IOCTLS
	char control[PATH_MAX];
	uint32_t major = 0, minor;
	int dm_mod_autoload_support, needs_open;

	if (_control_fd != -1)
		return 1;

	if (!_uname())
		return 0;

	snprintf(control, sizeof(control), "%s/%s", dm_dir(), DM_CONTROL_NODE);

	/*
	 * dm-mod autoloading is supported since kernel 2.6.36.
	 * Udev daemon will try to read modules.devname file extracted
	 * by depmod and create any static nodes needed.
	 * The /dev/mapper/control node can be created and prepared this way.
	 * First access to such node should load dm-mod module automatically.
	 */
	dm_mod_autoload_support = KERNEL_VERSION(_kernel_major, _kernel_minor,
				  _kernel_release) >= KERNEL_VERSION(2, 6, 36);

	/*
	 *  If dm-mod autoloading is supported and the control node exists
	 *  already try to open it now. This should autoload dm-mod module.
	 */
	if (dm_mod_autoload_support) {
		if (!_get_proc_number(PROC_DEVICES, MISC_NAME, &major))
			/* If major not found, just fallback to hardcoded value. */
			major = MISC_MAJOR;

		/* Recreate the node with correct major and minor if needed. */
		if (!_control_exists(control, major, MAPPER_CTRL_MINOR) &&
		    !_create_control(control, major, MAPPER_CTRL_MINOR))
			goto error;

		_open_and_assign_control_fd(control, 1);
	}

	/*
	 * Get major and minor number assigned for the control node.
	 * In case we make use of the module autoload support, this
	 * information should be accessible now as well.
	 */
	if (!_control_device_number(&major, &minor))
		log_error("Is device-mapper driver missing from kernel?");

	/*
	 * Check the control node and its major and minor number.
	 * If there's anything wrong, remove the old node and create
	 * a correct one.
	 */
	if ((needs_open = !_control_exists(control, major, minor)) &&
	    !_create_control(control, major, minor)) {
		_close_control_fd();
		goto error;
	}

	/*
	 * For older kernels without dm-mod autoloading support, we always
	 * need to open the control node here - we still haven't done that!
	 * For newer kernels with dm-mod autoloading, we open it only if the
	 * node was recreated and corrected in previous step.
	 */
	if ((!dm_mod_autoload_support || needs_open) &&
	     !_open_and_assign_control_fd(control, 0))
		goto error;

	if (!_create_dm_bitset()) {
		log_error("Failed to set up list of device-mapper major numbers");
		return 0;
	}

	return 1;

error:
	log_error("Failure to communicate with kernel device-mapper driver.");
	return 0;
#else
	return 1;
#endif
}