diff options
author | Hannes Reinecke <hare@suse.de> | 2011-10-31 12:06:02 +0100 |
---|---|---|
committer | Hannes Reinecke <hare@suse.de> | 2011-10-31 12:06:02 +0100 |
commit | ba81365ca9669de9b5a22d246d6cce379150b7fc (patch) | |
tree | 33bfb808c24ea45f779c19469bd6684c6852a69b | |
parent | 88be678f8fc7f41910eafc6120100d0be9744e2e (diff) | |
download | multipath-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.c | 2 | ||||
-rw-r--r-- | libmultipath/sysfs.c | 25 | ||||
-rw-r--r-- | libmultipath/sysfs.h | 2 | ||||
-rw-r--r-- | multipathd/cli_handlers.c | 2 | ||||
-rw-r--r-- | multipathd/main.c | 3 |
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; |