Hi Christophe, whenever a device is finally removed from a multipath map we should also remove it from the sysfs cache. Otherwise we'll hogging up memory with multipathd. And we might rely on wrong information as the device in the sysfs cache might in fact be a different device if the system decided to assign the same number to a different device or if some values have changed. Please apply. Cheers, Hannes -- Dr. Hannes Reinecke zSeries & Storage hare@xxxxxxx +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Markus Rex, HRB 16746 (AG Nürnberg)
multipathd: remove sysfs devices from cache Whenever a device is really removed from any multipath map we should also remove it from the cache. Otherwise we'll induce a memory leak. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c index d8c65b2..b9621ac 100644 --- a/libmultipath/sysfs.c +++ b/libmultipath/sysfs.c @@ -342,6 +342,25 @@ struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device return NULL; } +void sysfs_device_put(struct sysfs_device *dev) +{ + struct sysfs_dev *sysdev_loop; + + list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) { + if (&sysdev_loop->dev == dev) { + dbg("removed dev '%s' from cache", + sysdev_loop->dev.devpath); + list_del(&sysdev_loop->node); + free(sysdev_loop); + return; + } + } + dbg("dev '%s' not found in cache", + sysdev_loop->dev.devpath); + + return; +} + char *sysfs_attr_get_value(const char *devpath, const char *attr_name) { char path_full[PATH_SIZE]; diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h index 6d83489..e7fa3e7 100644 --- a/libmultipath/sysfs.h +++ b/libmultipath/sysfs.h @@ -18,6 +18,7 @@ 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); char *sysfs_attr_get_value(const char *devpath, const char *attr_name); int sysfs_resolve_link(char *path, size_t size); diff --git a/multipathd/main.c b/multipathd/main.c index b1620b5..da5fd8f 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -442,8 +442,14 @@ out: static int uev_remove_path (struct sysfs_device * dev, struct vectors * vecs) { + int retval; + condlog(2, "%s: remove path (uevent)", dev->kernel); - return ev_remove_path(dev->kernel, vecs); + retval = ev_remove_path(dev->kernel, vecs); + if (!retval) + sysfs_device_put(dev); + + return retval; } int
-- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel