]> sourceware.org Git - lvm2.git/commitdiff
libdm: implement search for device names for older kernels
authorZdenek Kabelac <zkabelac@redhat.com>
Fri, 5 Jul 2019 23:21:39 +0000 (01:21 +0200)
committerZdenek Kabelac <zkabelac@redhat.com>
Fri, 9 Aug 2019 10:57:07 +0000 (12:57 +0200)
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.

device_mapper/libdm-common.c
libdm/libdm-common.c

index 45dcb4c0dc6e5a324a628ce3e1310621ea0a86ab..1cb29f1e895e6d3cdf33dfb375fe1bcfd7aa9dc5 100644 (file)
@@ -1874,6 +1874,120 @@ 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;
@@ -1896,8 +2010,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';
index 7d19f751ac565dfcffe61312288c1232419d7a00..d17c284f2e031746b3b83cd1f35509f92a9b5f3f 100644 (file)
@@ -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';
This page took 0.039379 seconds and 5 git commands to generate.