aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2011-10-31 12:06:02 +0100
committerHannes Reinecke <hare@suse.de>2011-10-31 12:06:02 +0100
commitba81365ca9669de9b5a22d246d6cce379150b7fc (patch)
tree33bfb808c24ea45f779c19469bd6684c6852a69b
parent88be678f8fc7f41910eafc6120100d0be9744e2e (diff)
downloadmultipath-tools-sles10-sp4.tar.gz
Do not lookup sysfs devices in cache for 'add' eventssles10-sp4
For 'add' events the same devpath might point to a different device, so we really shouldn't lookup the device in the cache. Rather we should omit the cache altogether and use a new one. For any sane operation the stale device should have received a 'remove' event, so the cache should've been cleaned up. References: bnc#719838 Signed-off-by: Hannes Reinecke <hare@suse.de>
-rw-r--r--libmultipath/discovery.c2
-rw-r--r--libmultipath/sysfs.c25
-rw-r--r--libmultipath/sysfs.h2
-rw-r--r--multipathd/cli_handlers.c2
-rw-r--r--multipathd/main.c3
5 files changed, 21 insertions, 13 deletions
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index f4bdbef..d7354b0 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -612,7 +612,7 @@ struct sysfs_device *sysfs_device_from_path(struct path *pp)
strlcpy(sysdev,"/block/", FILE_NAME_SIZE);
strlcat(sysdev,pp->dev, FILE_NAME_SIZE);
- return sysfs_device_get(sysdev);
+ return sysfs_device_get(sysdev, 0);
}
extern int
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
index b9621ac..576368c 100644
--- a/libmultipath/sysfs.c
+++ b/libmultipath/sysfs.c
@@ -150,7 +150,7 @@ int sysfs_resolve_link(char *devpath, size_t size)
return 0;
}
-struct sysfs_device *sysfs_device_get(const char *devpath)
+struct sysfs_device *sysfs_device_get(const char *devpath, int add_event)
{
char path[PATH_SIZE];
char devpath_real[PATH_SIZE];
@@ -172,9 +172,13 @@ struct sysfs_device *sysfs_device_get(const char *devpath)
if (lstat(path, &statbuf) != 0) {
/* if stat fails look in the cache */
dbg("stat '%s' failed: %s", path, strerror(errno));
+ /* For 'add' events the path always has to exist */
+ if (add_event)
+ return NULL;
list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) {
if (strcmp(sysdev_loop->dev.devpath, devpath_real) == 0) {
- dbg("found vanished dev in cache '%s'", sysdev_loop->dev.devpath);
+ dbg("found vanished dev in cache '%s'",
+ sysdev_loop->dev.devpath);
return &sysdev_loop->dev;
}
}
@@ -183,16 +187,19 @@ struct sysfs_device *sysfs_device_get(const char *devpath)
if (S_ISLNK(statbuf.st_mode)) {
if (sysfs_resolve_link(devpath_real, sizeof(devpath_real)) != 0)
return NULL;
-
}
- list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) {
- if (strcmp(sysdev_loop->dev.devpath, devpath_real) == 0) {
- dbg("found dev in cache '%s'", sysdev_loop->dev.devpath);
+ if (!add_event) {
+ list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) {
+ if (!strcmp(sysdev_loop->dev.devpath, devpath_real)) {
+ dbg("found dev in cache '%s'",
+ sysdev_loop->dev.devpath);
dev = &sysdev_loop->dev;
+ }
}
}
- if(!dev) {
+
+ if (!dev) {
/* it is a new device */
dbg("new device '%s'", devpath_real);
sysdev = malloc(sizeof(struct sysfs_dev));
@@ -315,7 +322,7 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev)
}
/* get parent and remember it */
- dev->parent = sysfs_device_get(parent_devpath);
+ dev->parent = sysfs_device_get(parent_devpath, 0);
return dev->parent;
device_link:
@@ -325,7 +332,7 @@ device_link:
return NULL;
/* get parent and remember it */
- dev->parent = sysfs_device_get(parent_devpath);
+ dev->parent = sysfs_device_get(parent_devpath, 0);
return dev->parent;
}
diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h
index e7fa3e7..aee7b2c 100644
--- a/libmultipath/sysfs.h
+++ b/libmultipath/sysfs.h
@@ -15,7 +15,7 @@ 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);
-struct sysfs_device *sysfs_device_get(const char *devpath);
+struct sysfs_device *sysfs_device_get(const char *devpath, int add_event);
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);
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 2f36592..add716d 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -331,7 +331,7 @@ cli_add_map (void * v, char ** reply, int * len, void * data)
return 0;
}
sprintf(dev_path,"/block/dm-%d", minor);
- sysdev = sysfs_device_get(dev_path);
+ sysdev = sysfs_device_get(dev_path, 1);
if (!sysdev) {
condlog(2, "%s: not found in sysfs", param);
return 0;
diff --git a/multipathd/main.c b/multipathd/main.c
index adc2d95..9ad6a44 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -629,7 +629,8 @@ uev_trigger (struct uevent * uev, void * trigger_data)
if (uev_discard(uev->devpath))
return 0;
- sysdev = sysfs_device_get(uev->devpath);
+ sysdev = sysfs_device_get(uev->devpath,
+ !strncmp(uev->action, "add", 3));
if(!sysdev)
return 0;