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; }
/* * 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 }