summaryrefslogtreecommitdiff
path: root/libdm/libdm-common.c
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2019-07-06 01:21:39 +0200
committerZdenek Kabelac <zkabelac@redhat.com>2019-08-09 12:57:07 +0200
commit46f1d17c743145d3ffa045557a6a792eb99f478a (patch)
tree7205c1ad9b756824ffccbe07c79a198c74c76286 /libdm/libdm-common.c
parent2f5ea9e61acf56aa244715570710ba1e229a77cd (diff)
downloadlvm2-46f1d17c743145d3ffa045557a6a792eb99f478a.tar.gz
libdm: implement search for device names for older kernels
Kernels <2.6.27 don't have /sys/dev dir - add code for looking out device name via longre seach in /sys/block This makes commands like 'dmsetup dep -o blkdevname' working.
Diffstat (limited to 'libdm/libdm-common.c')
-rw-r--r--libdm/libdm-common.c119
1 files changed, 118 insertions, 1 deletions
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index 7d19f751a..d17c284f2 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -1872,6 +1872,121 @@ bad:
return r;
}
+static int _sysfs_get_dev_major_minor(const char *path, uint32_t major, uint32_t minor)
+{
+ FILE *fp;
+ uint32_t ma, mi;
+ int r;
+
+ if (!(fp = fopen(path, "r")))
+ return 0;
+
+ r = (fscanf(fp, "%" PRIu32 ":%" PRIu32 , &ma, &mi) == 2) &&
+ (ma == major) && (mi == minor);
+ // log_debug("Checking %s %u:%u -> %d", path, ma, mi, r);
+
+ if (fclose(fp))
+ log_sys_error("fclose", path);
+
+ return r;
+}
+
+
+static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
+{
+ const char *name, *name_dev;
+ char path[PATH_MAX];
+ struct dirent *dirent, *dirent_dev;
+ DIR *d, *d_dev;
+ struct stat st;
+ int r = 0, sz;
+
+ if (!*_sysfs_dir ||
+ dm_snprintf(path, sizeof(path), "%s/block/", _sysfs_dir) < 0) {
+ log_error("Failed to build sysfs_path.");
+ return 0;
+ }
+
+ if (!(d = opendir(path))) {
+ log_sys_error("opendir", path);
+ return 0;
+ }
+
+ while (!r && (dirent = readdir(d))) {
+ name = dirent->d_name;
+
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ continue;
+
+ if ((sz = dm_snprintf(path, sizeof(path), "%sblock/%s/dev",
+ _sysfs_dir, name)) == -1) {
+ log_warn("Couldn't create path for %s.", name);
+ continue;
+ }
+
+ if (_sysfs_get_dev_major_minor(path, major, minor)) {
+ r = dm_strncpy(buf, name, buf_size);
+ break; /* found */
+ }
+
+ path[sz - 4] = 0; /* strip /dev from end of path string */
+ if (stat(path, &st))
+ continue;
+
+ if (S_ISDIR(st.st_mode)) {
+
+ /* let's assume there is no tree-complex device in past systems */
+ if (!(d_dev = opendir(path))) {
+ log_sys_debug("opendir", path);
+ continue;
+ }
+
+ while ((dirent_dev = readdir(d_dev))) {
+ name_dev = dirent_dev->d_name;
+
+ /* skip known ignorable paths */
+ if (!strcmp(name_dev, ".") || !strcmp(name_dev, "..") ||
+ !strcmp(name_dev, "bdi") ||
+ !strcmp(name_dev, "dev") ||
+ !strcmp(name_dev, "device") ||
+ !strcmp(name_dev, "holders") ||
+ !strcmp(name_dev, "integrity") ||
+ !strcmp(name_dev, "loop") ||
+ !strcmp(name_dev, "queueu") ||
+ !strcmp(name_dev, "md") ||
+ !strcmp(name_dev, "mq") ||
+ !strcmp(name_dev, "power") ||
+ !strcmp(name_dev, "removable") ||
+ !strcmp(name_dev, "slave") ||
+ !strcmp(name_dev, "slaves") ||
+ !strcmp(name_dev, "subsystem") ||
+ !strcmp(name_dev, "trace") ||
+ !strcmp(name_dev, "uevent"))
+ continue;
+
+ if (dm_snprintf(path, sizeof(path), "%sblock/%s/%s/dev",
+ _sysfs_dir, name, name_dev) == -1) {
+ log_warn("Couldn't create path for %s/%s.", name, name_dev);
+ continue;
+ }
+
+ if (_sysfs_get_dev_major_minor(path, major, minor)) {
+ r = dm_strncpy(buf, name_dev, buf_size);
+ break; /* found */
+ }
+ }
+
+ if (closedir(d_dev))
+ log_sys_debug("closedir", name);
+ }
+ }
+
+ if (closedir(d))
+ log_sys_debug("closedir", path);
+
+ return r;
+}
+
static int _sysfs_get_kernel_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
{
char *name, *sysfs_path, *temp_buf = NULL;
@@ -1894,8 +2009,10 @@ static int _sysfs_get_kernel_name(uint32_t major, uint32_t minor, char *buf, siz
if ((size = readlink(sysfs_path, temp_buf, PATH_MAX - 1)) < 0) {
if (errno != ENOENT)
log_sys_error("readlink", sysfs_path);
- else
+ else {
log_sys_debug("readlink", sysfs_path);
+ return _sysfs_find_kernel_name(major, minor, buf, buf_size);
+ }
goto bad;
}
temp_buf[size] = '\0';