From: Hannes Reinecke Date: Thu, 27 May 2010 11:51:23 +0000 (+0200) Subject: libmultipath: rework sysfs handling X-Git-Tag: upstream/0.5.0~106^2~37 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e7b54e70bdd1d6020351a2af2e92dfb16724f2cd;p=platform%2Fupstream%2Fmultipath-tools.git libmultipath: rework sysfs handling 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 --- diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 73f84a7..b5e2e4f 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -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; diff --git a/libmultipath/structs.h b/libmultipath/structs.h index 0afa340..8380c32 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -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 diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c index 2bc605c..9a27e74 100644 --- a/libmultipath/sysfs.c +++ b/libmultipath/sysfs.c @@ -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; } diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h index b03166b..7e8fff8 100644 --- a/libmultipath/sysfs.h +++ b/libmultipath/sysfs.h @@ -13,12 +13,11 @@ 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,