static int _create_control(const char *control, uint32_t major, uint32_t minor) { int ret; mode_t old_umask; if (!major) return 0; old_umask = umask(DM_DEV_DIR_UMASK); ret = dm_create_dir(dm_dir()); umask(old_umask); if (!ret) return 0; log_verbose("Creating device %s (%u, %u)", control, major, minor); if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR, MKDEV(major, minor)) < 0) { log_sys_error("mknod", control); return 0; } #ifdef HAVE_SELINUX if (!dm_set_selinux_context(control, S_IFCHR)) { stack; return 0; } #endif return 1; }
static int _create_control(const char *control, uint32_t major, uint32_t minor) { int ret; mode_t old_umask; if (!major) return 0; old_umask = umask(0022); ret = dm_create_dir(dm_dir()); umask(old_umask); if (!ret) return 0; log_verbose("Creating device %s (%u, %u)", control, major, minor); if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR, MKDEV(major, minor)) < 0) { log_sys_error("mknod", control); return 0; } return 1; }
static int _process_mapper_dir(struct dm_task *dmt) { struct dirent *dirent; DIR *d; const char *dir; int r = 1; dir = dm_dir(); if (!(d = opendir(dir))) { log_sys_error("opendir", dir); return 0; } while ((dirent = readdir(d))) { if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..") || !strcmp(dirent->d_name, "control")) continue; dm_task_set_name(dmt, dirent->d_name); dm_task_run(dmt); } if (closedir(d)) log_sys_error("closedir", dir); return r; }
/* Open control device if doesn't exist create it. */ static int _open_control(void) { char control[PATH_MAX]; uint32_t major = 0, minor = 0; if (_control_fd != -1) return 1; #ifdef RUMP_ACTION rump_init(); #endif snprintf(control, sizeof(control), "%s/control", dm_dir()); if (!_control_device_number(&major, &minor)) log_error("Is device-mapper driver missing from kernel?"); if (!_control_exists(control, major, minor) && !_create_control(control, major, minor)) goto error; if ((_control_fd = open(control, O_RDWR)) < 0) { log_sys_error("open", control); goto error; } return 1; error: log_error("Failure to communicate with kernel device-mapper driver."); return 0; }
static int _create_control(const char *control, uint32_t major, uint32_t minor) { int ret; mode_t old_umask; if (!major) return 0; old_umask = umask(DM_DEV_DIR_UMASK); ret = dm_create_dir(dm_dir()); umask(old_umask); if (!ret) return 0; log_verbose("Creating device %s (%u, %u)", control, major, minor); old_umask = umask(0); if (mknod(control, S_IFCHR | DM_CONTROL_DEVICE_MODE, MKDEV(major, minor)) < 0) { umask(old_umask); log_sys_error("mknod", control); return 0; } umask(old_umask); if (chown(control, DM_DEVICE_UID, DM_DEVICE_GID) == -1) { log_sys_error("chown", control); return 0; } return 1; }
static char *lookup_dev(const char *dev_id) { uint32_t major, minor; dev_t dev; char *result = NULL, buf[PATH_MAX + 1]; if (sscanf(dev_id, "%" PRIu32 ":%" PRIu32, &major, &minor) != 2) return NULL; dev = makedev(major, minor); strncpy(buf, DEVICE_DIR, PATH_MAX); buf[PATH_MAX] = '\0'; /* First try low level device */ if ((result = __lookup_dev(buf, dev, 0, 0))) return result; /* If it is dm, try DM dir */ if (dm_is_dm_major(major)) { strncpy(buf, dm_dir(), PATH_MAX); if ((result = __lookup_dev(buf, dev, 0, 0))) return result; } strncpy(buf, DEVICE_DIR, PATH_MAX); result = __lookup_dev(buf, dev, 0, 4); /* If not found, return NULL */ return result; }
/* Make up a dm path. */ char * mkdm_path(struct lib_context *lc, const char *name) { char *ret; const char *dir = dm_dir(); if ((ret = dbg_malloc(strlen(dir) + strlen(name) + 2))) sprintf(ret, "%s/%s", dir, name); else log_alloc_err(lc, __func__); return ret; }
static int _open_control(void) { #ifdef DM_IOCTLS char control[PATH_MAX]; uint32_t major = 0, minor; if (_control_fd != -1) return 1; snprintf(control, sizeof(control), "%s/control", dm_dir()); if (!_control_device_number(&major, &minor)) log_error("Is device-mapper driver missing from kernel?"); if (!_control_exists(control, major, minor) && !_create_control(control, major, minor)) goto error; if ((_control_fd = open(control, O_RDWR)) < 0) { log_sys_error("open", control); 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 }
static int _dm_names_v1(struct dm_ioctl_v1 *dmi) { const char *dev_dir = dm_dir(); int r = 1, len; const char *name; struct dirent *dirent; DIR *d; struct dm_names *names, *old_names = NULL; void *end = (void *) dmi + dmi->data_size; struct stat buf; char path[PATH_MAX]; log_warn("WARNING: Device list may be incomplete with interface " "version 1."); log_warn("Please upgrade your kernel device-mapper driver."); if (!(d = opendir(dev_dir))) { log_sys_error("opendir", dev_dir); return 0; } names = (struct dm_names *) ((void *) dmi + dmi->data_start); names->dev = 0; /* Flags no data */ while ((dirent = readdir(d))) { name = dirent->d_name; if (name[0] == '.' || !strcmp(name, "control")) continue; if (old_names) old_names->next = (uint32_t) ((void *) names - (void *) old_names); snprintf(path, sizeof(path), "%s/%s", dev_dir, name); if (stat(path, &buf)) { log_sys_error("stat", path); continue; } if (!S_ISBLK(buf.st_mode)) continue; names->dev = (uint64_t) buf.st_rdev; names->next = 0; len = strlen(name); if (((void *) (names + 1) + len + 1) >= end) { log_error("Insufficient buffer space for device list"); r = 0; break; } strcpy(names->name, name); old_names = names; names = _align((void *) ++names + len + 1, ALIGNMENT); } if (closedir(d)) log_sys_error("closedir", dev_dir); return r; }
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 }
const char *dm_get_dir(void) { return dm_dir(); }