libmultipath: rework sysfs handling
authorHannes Reinecke <hare@suse.de>
Thu, 27 May 2010 11:51:23 +0000 (13:51 +0200)
committerHannes Reinecke <hare@suse.de>
Tue, 17 May 2011 10:32:17 +0000 (12:32 +0200)
sysfs_get_device() is called extremely often, so we need
to make sure to have that as streamlined as possible.
So remove all unused fields and use caching as often as
possible.

Signed-off-by: Hannes Reinecke <hare@suse.de>
libmultipath/discovery.c
libmultipath/structs.h
libmultipath/sysfs.c
libmultipath/sysfs.h

index 73f84a7..b5e2e4f 100644 (file)
@@ -638,6 +638,9 @@ struct sysfs_device *sysfs_device_from_path(struct path *pp)
 {
        char sysdev[FILE_NAME_SIZE];
 
+       if (pp->sysdev && sysfs_device_verify(pp->sysdev))
+               return pp->sysdev;
+
        strlcpy(sysdev,"/block/", FILE_NAME_SIZE);
        strlcat(sysdev,pp->dev, FILE_NAME_SIZE);
 
@@ -708,17 +711,13 @@ sysfs_pathinfo(struct path * pp)
                return 1;
        }
 
+       pp->bus = SYSFS_BUS_UNDEF;
        if (!strncmp(pp->dev,"cciss",5))
-               strcpy(parent->subsystem,"cciss");
-
-       condlog(3, "%s: subsystem = %s", pp->dev, parent->subsystem);
-
-       if (!strncmp(parent->subsystem, "scsi",4))
-               pp->bus = SYSFS_BUS_SCSI;
-       if (!strncmp(parent->subsystem, "ccw",3))
-               pp->bus = SYSFS_BUS_CCW;
-       if (!strncmp(parent->subsystem,"cciss",5))
                pp->bus = SYSFS_BUS_CCISS;
+       if (!strncmp(pp->dev,"dasd", 4))
+               pp->bus = SYSFS_BUS_CCW;
+       if (!strncmp(pp->dev,"sd", 2))
+               pp->bus = SYSFS_BUS_SCSI;
 
        if (pp->bus == SYSFS_BUS_UNDEF)
                return 0;
index 0afa340..8380c32 100644 (file)
@@ -113,10 +113,7 @@ struct scsi_dev {
 struct sysfs_device {
        struct sysfs_device *parent;            /* parent device */
        char devpath[PATH_SIZE];
-       char subsystem[NAME_SIZE];              /* $class, $bus, drivers, module */
        char kernel[NAME_SIZE];                 /* device instance name */
-       char kernel_number[NAME_SIZE];
-       char driver[NAME_SIZE];                 /* device driver name */
 };
 
 # ifndef HDIO_GETGEO
index 2bc605c..9a27e74 100644 (file)
@@ -68,16 +68,11 @@ void sysfs_cleanup(void)
        }
 }
 
-void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath,
-                            const char *subsystem, const char *driver)
+void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath)
 {
        char *pos;
 
        strlcpy(dev->devpath, devpath, sizeof(dev->devpath));
-       if (subsystem != NULL)
-               strlcpy(dev->subsystem, subsystem, sizeof(dev->subsystem));
-       if (driver != NULL)
-               strlcpy(dev->driver, driver, sizeof(dev->driver));
 
        /* set kernel name */
        pos = strrchr(dev->devpath, '/');
@@ -93,13 +88,6 @@ void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath,
                        pos[0] = '/';
                pos++;
        }
-
-       /* get kernel number */
-       pos = &dev->kernel[strlen(dev->kernel)];
-       while (isdigit(pos[-1]))
-               pos--;
-       strlcpy(dev->kernel_number, pos, sizeof(dev->kernel_number));
-       dbg("kernel_number='%s'", dev->kernel_number);
 }
 
 int sysfs_resolve_link(char *devpath, size_t size)
@@ -134,6 +122,10 @@ int sysfs_resolve_link(char *devpath, size_t size)
        return 0;
 }
 
+/*
+ * Caution: this routine is called extremely often.
+ * Should be as efficient as possible.
+ */
 struct sysfs_device *sysfs_device_get(const char *devpath)
 {
        char path[PATH_SIZE];
@@ -141,22 +133,6 @@ struct sysfs_device *sysfs_device_get(const char *devpath)
        struct sysfs_device *dev = NULL;
        struct sysfs_dev *sysdev_loop, *sysdev;
        struct stat statbuf;
-       char link_path[PATH_SIZE];
-       char link_target[PATH_SIZE];
-       int len;
-       char *pos;
-
-       /* we handle only these devpathes */
-       if (devpath != NULL &&
-           strncmp(devpath, "/devices/", 9) != 0 &&
-           strncmp(devpath, "/subsystem/", 11) != 0 &&
-           strncmp(devpath, "/module/", 8) != 0 &&
-           strncmp(devpath, "/bus/", 5) != 0 &&
-           strncmp(devpath, "/class/", 7) != 0 &&
-           strncmp(devpath, "/block/", 7) != 0) {
-               dbg("invalid devpath '%s'", devpath);
-               return NULL;
-       }
 
        dbg("open '%s'", devpath);
        strlcpy(devpath_real, devpath, sizeof(devpath_real));
@@ -203,53 +179,7 @@ struct sysfs_device *sysfs_device_get(const char *devpath)
                dev = &sysdev->dev;
        }
 
-       sysfs_device_set_values(dev, devpath_real, NULL, NULL);
-
-       /* get subsystem name */
-       strlcpy(link_path, sysfs_path, sizeof(link_path));
-       strlcat(link_path, dev->devpath, sizeof(link_path));
-       strlcat(link_path, "/subsystem", sizeof(link_path));
-       len = readlink(link_path, link_target, sizeof(link_target));
-       if (len > 0) {
-               /* get subsystem from "subsystem" link */
-               link_target[len] = '\0';
-               dbg("subsystem link '%s' points to '%s'", link_path, link_target);
-               pos = strrchr(link_target, '/');
-               if (pos != NULL)
-                       strlcpy(dev->subsystem, &pos[1], sizeof(dev->subsystem));
-       } else if (strstr(dev->devpath, "/drivers/") != NULL) {
-               strlcpy(dev->subsystem, "drivers", sizeof(dev->subsystem));
-       } else if (strncmp(dev->devpath, "/module/", 8) == 0) {
-               strlcpy(dev->subsystem, "module", sizeof(dev->subsystem));
-       } else if (strncmp(dev->devpath, "/subsystem/", 11) == 0) {
-               pos = strrchr(dev->devpath, '/');
-               if (pos == &dev->devpath[10])
-                       strlcpy(dev->subsystem, "subsystem",
-                               sizeof(dev->subsystem));
-       } else if (strncmp(dev->devpath, "/class/", 7) == 0) {
-               pos = strrchr(dev->devpath, '/');
-               if (pos == &dev->devpath[6])
-                       strlcpy(dev->subsystem, "subsystem",
-                               sizeof(dev->subsystem));
-       } else if (strncmp(dev->devpath, "/bus/", 5) == 0) {
-               pos = strrchr(dev->devpath, '/');
-               if (pos == &dev->devpath[4])
-                       strlcpy(dev->subsystem, "subsystem",
-                               sizeof(dev->subsystem));
-       }
-
-       /* get driver name */
-       strlcpy(link_path, sysfs_path, sizeof(link_path));
-       strlcat(link_path, dev->devpath, sizeof(link_path));
-       strlcat(link_path, "/driver", sizeof(link_path));
-       len = readlink(link_path, link_target, sizeof(link_target));
-       if (len > 0) {
-               link_target[len] = '\0';
-               dbg("driver link '%s' points to '%s'", link_path, link_target);
-               pos = strrchr(link_target, '/');
-               if (pos != NULL)
-                       strlcpy(dev->driver, &pos[1], sizeof(dev->driver));
-       }
+       sysfs_device_set_values(dev, devpath_real);
 
        return dev;
 }
@@ -306,16 +236,17 @@ device_link:
        return dev->parent;
 }
 
-struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device *dev, const char *subsystem)
+struct sysfs_device *sysfs_device_verify(struct sysfs_device *dev)
 {
-       struct sysfs_device *dev_parent;
+       char path[PATH_SIZE];
+       struct stat statbuf;
+
+       strlcpy(path, sysfs_path, sizeof(path));
+       strlcat(path, dev->devpath, sizeof(path));
+       if (stat(dev->devpath, &statbuf) == 0 &&
+           S_ISDIR(statbuf.st_mode))
+               return dev;
 
-       dev_parent = sysfs_device_get_parent(dev);
-       while (dev_parent != NULL) {
-               if (strcmp(dev_parent->subsystem, subsystem) == 0)
-                       return dev_parent;
-               dev_parent = sysfs_device_get_parent(dev_parent);
-       }
        return NULL;
 }
 
@@ -438,7 +369,7 @@ ssize_t sysfs_attr_set_value(const char *devpath, const char *attr_name,
        if ((statbuf.st_mode & S_IWUSR) == 0)
                goto out;
 
-       /* read attribute value */
+       /* write attribute value */
        fd = open(path_full, O_WRONLY);
        if (fd < 0) {
                dbg("attribute '%s' can not be opened: %s",
@@ -453,8 +384,9 @@ ssize_t sysfs_attr_set_value(const char *devpath, const char *attr_name,
                    path_full, size);
                size = -1;
        }
-       close(fd);
 
+       close(fd);
 out:
+
        return size;
 }
index b03166b..7e8fff8 100644 (file)
 
 int sysfs_init(char *path, size_t len);
 void sysfs_cleanup(void);
-void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath,
-                            const char *subsystem, const char *driver);
+void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath);
 struct sysfs_device *sysfs_device_get(const char *devpath);
 struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev);
-struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device *dev, const char *subsystem);
 void sysfs_device_put(struct sysfs_device *dev);
+struct sysfs_device *sysfs_device_verify(struct sysfs_device *dev);
 size_t sysfs_attr_get_value(const char *devpath, const char *attr_name,
                            char *attr_value, int attr_len);
 ssize_t sysfs_attr_set_value(const char *devpath, const char *attr_name,