Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1
multipath-tools
multipath-tools-rework-sysfs-device-handling
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File multipath-tools-rework-sysfs-device-handling of Package multipath-tools
From e8f4746fa0aec8422022f52d917d6f82915128ce Mon Sep 17 00:00:00 2001 From: Hannes Reinecke <hare@suse.de> Date: Thu, 20 Nov 2008 12:14:42 +0100 Subject: [PATCH] Rework sysfs device handling in multipathd Relying on sysfs devices has the disadvantage that the device might already been gone by the time we look at it. And we don't actually need it for eg device-mapper events as we can get all required information via the device-mapper ioctl. So only access sysfs if we absolutely have to and try to get the information from other places if possible. Signed-off-by: Hannes Reinecke <hare@suse.de> --- libmultipath/devmapper.c | 25 ++++++++++++ libmultipath/devmapper.h | 1 + libmultipath/uevent.c | 46 +++++++++++++++++++++- libmultipath/uevent.h | 8 ++++ multipathd/cli_handlers.c | 13 +++--- multipathd/main.c | 94 +++++++++++++++++++++++++------------------- multipathd/main.h | 2 +- 7 files changed, 139 insertions(+), 50 deletions(-) diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c index bc4f9db..cde98eb 100644 --- a/libmultipath/devmapper.c +++ b/libmultipath/devmapper.c @@ -494,6 +494,31 @@ out: } int +dm_get_major (char * mapname) +{ + int r = -1; + struct dm_task *dmt; + struct dm_info info; + + if (!(dmt = dm_task_create(DM_DEVICE_INFO))) + return 0; + + if (!dm_task_set_name(dmt, mapname)) + goto out; + + if (!dm_task_run(dmt)) + goto out; + + if (!dm_task_get_info(dmt, &info)) + goto out; + + r = info.major; +out: + dm_task_destroy(dmt); + return r; +} + +int dm_get_minor (char * mapname) { int r = -1; diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h index b262efa..0c7b6b6 100644 --- a/libmultipath/devmapper.h +++ b/libmultipath/devmapper.h @@ -27,6 +27,7 @@ int dm_enablegroup(char * mapname, int index); int dm_disablegroup(char * mapname, int index); int dm_get_maps (vector mp); int dm_geteventnr (char *name); +int dm_get_major (char *name); int dm_get_minor (char *name); char * dm_mapname(int major, int minor); int dm_remove_partmaps (const char * mapname); diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c index 99757fe..13986da 100644 --- a/libmultipath/uevent.c +++ b/libmultipath/uevent.c @@ -262,10 +262,13 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data), uev->envp[i] = NULL; condlog(3, "uevent '%s' from '%s'", uev->action, uev->devpath); + uev->kernel = strrchr(uev->devpath, '/'); + if (uev->kernel) + uev->kernel++; /* print payload environment */ for (i = 0; uev->envp[i] != NULL; i++) - condlog(3, "%s", uev->envp[i]); + condlog(5, "%s", uev->envp[i]); /* * Queue uevent and poke service pthread. @@ -297,3 +300,44 @@ exit: return 1; } + +extern int +uevent_get_major(struct uevent *uev) +{ + char *p, *q; + int i, major = -1; + + for (i = 0; uev->envp[i] != NULL; i++) { + if (!strncmp(uev->envp[i], "MAJOR", 5) && strlen(uev->envp[i]) > 6) { + p = uev->envp[i] + 6; + major = strtoul(p, &q, 10); + if (p == q) { + condlog(2, "invalid major '%s'", p); + major = -1; + } + break; + } + } + return major; +} + +extern int +uevent_get_minor(struct uevent *uev) +{ + char *p, *q; + int i, minor = -1; + + for (i = 0; uev->envp[i] != NULL; i++) { + if (!strncmp(uev->envp[i], "MINOR", 5) && strlen(uev->envp[i]) > 6) { + p = uev->envp[i] + 6; + minor = strtoul(p, &q, 10); + if (p == q) { + condlog(2, "invalid minor '%s'", p); + minor = -1; + } + break; + } + } + return minor; +} + diff --git a/libmultipath/uevent.h b/libmultipath/uevent.h index 55ce42c..43d163b 100644 --- a/libmultipath/uevent.h +++ b/libmultipath/uevent.h @@ -1,3 +1,6 @@ +#ifndef _UEVENT_H +#define _UEVENT_H + /* environment buffer, the kernel's size in lib/kobject_uevent.c should fit in */ #define HOTPLUG_BUFFER_SIZE 1024 #define HOTPLUG_NUM_ENVP 32 @@ -12,8 +15,13 @@ struct uevent { char buffer[HOTPLUG_BUFFER_SIZE + OBJECT_SIZE]; char *devpath; char *action; + char *kernel; char *envp[HOTPLUG_NUM_ENVP]; }; int uevent_listen(int (*store_uev)(struct uevent *, void * trigger_data), void * trigger_data); +int uevent_get_major(struct uevent *uev); +int uevent_get_minor(struct uevent *uev); + +#endif /* _UEVENT_H */ diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c index fca09ed..f9b0da4 100644 --- a/multipathd/cli_handlers.c +++ b/multipathd/cli_handlers.c @@ -372,9 +372,8 @@ cli_add_map (void * v, char ** reply, int * len, void * data) { struct vectors * vecs = (struct vectors *)data; char * param = get_keyparam(v, MAP); - int minor; + int major, minor; char dev_path[PATH_SIZE]; - struct sysfs_device *sysdev; condlog(2, "%s: add map (operator)", param); @@ -389,13 +388,13 @@ cli_add_map (void * v, char ** reply, int * len, void * data) condlog(2, "%s: not a device mapper table", param); return 0; } - sprintf(dev_path,"/block/dm-%d", minor); - sysdev = sysfs_device_get(dev_path); - if (!sysdev) { - condlog(2, "%s: not found in sysfs", param); + major = dm_get_major(param); + if (major < 0) { + condlog(2, "%s: not a device mapper table", param); return 0; } - return ev_add_map(sysdev, vecs); + sprintf(dev_path,"dm-%d", minor); + return ev_add_map(dev_path, major, minor, vecs); } int diff --git a/multipathd/main.c b/multipathd/main.c index 6908902..bb396ec 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -46,6 +46,7 @@ #include <print.h> #include <configure.h> #include <prio.h> +#include <uevent.h> #include "main.h" #include "pidfile.h" @@ -212,32 +213,32 @@ flush_map(struct multipath * mpp, struct vectors * vecs) } static int -uev_add_map (struct sysfs_device * dev, struct vectors * vecs) +uev_add_map (struct uevent * uev, struct vectors * vecs) { - condlog(2, "%s: add map (uevent)", dev->kernel); - return ev_add_map(dev, vecs); + int major, minor; + + condlog(2, "%s: add map (uevent)", uev->kernel); + major = uevent_get_major(uev); + minor = uevent_get_minor(uev); + return ev_add_map(uev->kernel, major, minor, vecs); } int -ev_add_map (struct sysfs_device * dev, struct vectors * vecs) +ev_add_map (char * dev, int major, int minor, struct vectors * vecs) { char * alias; - char *dev_t; - int major, minor; char * refwwid; struct multipath * mpp; int map_present; int r = 1; - dev_t = sysfs_attr_get_value(dev->devpath, "dev"); - - if (!dev_t || sscanf(dev_t, "%d:%d", &major, &minor) != 2) - return 1; - alias = dm_mapname(major, minor); - if (!alias) + if (!alias) { + condlog(2, "%s: mapname not found for %d:%d", + dev, major, minor); return 1; + } map_present = dm_map_present(alias); @@ -254,8 +255,7 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) * if we create a multipath mapped device as a result * of uev_add_path */ - condlog(0, "%s: devmap already registered", - dev->kernel); + condlog(0, "%s: devmap already registered", dev); return 0; } @@ -264,10 +264,10 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) */ if (map_present && (mpp = add_map_without_path(vecs, minor, alias))) { sync_map_state(mpp); - condlog(2, "%s: devmap %s added", alias, dev->kernel); + condlog(2, "%s: devmap %s added", alias, dev); return 0; } - refwwid = get_refwwid(dev->kernel, DEV_DEVMAP, vecs->pathvec); + refwwid = get_refwwid(dev, DEV_DEVMAP, vecs->pathvec); if (refwwid) { r = coalesce_paths(vecs, NULL, refwwid, 0); @@ -275,19 +275,19 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs) } if (!r) - condlog(2, "%s: devmap %s added", alias, dev->kernel); + condlog(2, "%s: devmap %s added", alias, dev); else - condlog(0, "%s: uev_add_map %s failed", alias, dev->kernel); + condlog(0, "%s: uev_add_map %s failed", alias, dev); FREE(refwwid); return r; } static int -uev_remove_map (struct sysfs_device * dev, struct vectors * vecs) +uev_remove_map (struct uevent * uev, struct vectors * vecs) { - condlog(2, "%s: remove map (uevent)", dev->kernel); - return ev_remove_map(dev->kernel, vecs); + condlog(2, "%s: remove map (uevent)", uev->kernel); + return ev_remove_map(uev->kernel, vecs); } int @@ -308,13 +308,13 @@ ev_remove_map (char * devname, struct vectors * vecs) } static int -uev_umount_map (struct sysfs_device * dev, struct vectors * vecs) +uev_umount_map (struct uevent * uev, struct vectors * vecs) { struct multipath * mpp; - condlog(2, "%s: umount map (uevent)", dev->kernel); + condlog(2, "%s: umount map (uevent)", uev->kernel); - mpp = find_mp_by_str(vecs->mpvec, dev->kernel); + mpp = find_mp_by_str(vecs->mpvec, uev->kernel); if (!mpp) return 0; @@ -328,14 +328,21 @@ uev_umount_map (struct sysfs_device * dev, struct vectors * vecs) return 0; } + static int -uev_add_path (struct sysfs_device * dev, struct vectors * vecs) +uev_add_path (struct uevent *uev, struct vectors * vecs) { + struct sysfs_device * dev; + + dev = sysfs_device_get(uev->devpath); + if (!dev) { + condlog(2, "%s: not found in sysfs", uev->devpath); + return 1; + } condlog(2, "%s: add path (uevent)", dev->kernel); return (ev_add_path(dev->kernel, vecs) != 1)? 0 : 1; } - /* * returns: * 0: added @@ -448,12 +455,19 @@ out: } static int -uev_remove_path (struct sysfs_device * dev, struct vectors * vecs) +uev_remove_path (struct uevent *uev, struct vectors * vecs) { + struct sysfs_device * dev; int retval; - condlog(2, "%s: remove path (uevent)", dev->kernel); - retval = ev_remove_path(dev->kernel, vecs); + dev = sysfs_device_get(uev->devpath); + if (!dev) { + condlog(2, "%s: not found in sysfs", uev->devpath); + return 1; + } + condlog(2, "%s: remove path (uevent)", uev->kernel); + retval = ev_remove_path(uev->kernel, vecs); + if (!retval) sysfs_device_put(dev); @@ -625,7 +639,6 @@ int uev_trigger (struct uevent * uev, void * trigger_data) { int r = 0; - struct sysfs_device *sysdev; struct vectors * vecs; vecs = (struct vectors *)trigger_data; @@ -633,10 +646,6 @@ uev_trigger (struct uevent * uev, void * trigger_data) if (uev_discard(uev->devpath)) return 0; - sysdev = sysfs_device_get(uev->devpath); - if(!sysdev) - return 0; - lock(vecs->lock); /* @@ -644,17 +653,17 @@ uev_trigger (struct uevent * uev, void * trigger_data) * Add events are ignored here as the tables * are not fully initialised then. */ - if (!strncmp(sysdev->kernel, "dm-", 3)) { + if (!strncmp(uev->kernel, "dm-", 3)) { if (!strncmp(uev->action, "change", 6)) { - r = uev_add_map(sysdev, vecs); + r = uev_add_map(uev, vecs); goto out; } if (!strncmp(uev->action, "remove", 6)) { - r = uev_remove_map(sysdev, vecs); + r = uev_remove_map(uev, vecs); goto out; } if (!strncmp(uev->action, "umount", 6)) { - r = uev_umount_map(sysdev, vecs); + r = uev_umount_map(uev, vecs); goto out; } goto out; @@ -664,15 +673,15 @@ uev_trigger (struct uevent * uev, void * trigger_data) * path add/remove event */ if (filter_devnode(conf->blist_devnode, conf->elist_devnode, - sysdev->kernel) > 0) + uev->kernel) > 0) goto out; if (!strncmp(uev->action, "add", 3)) { - r = uev_add_path(sysdev, vecs); + r = uev_add_path(uev, vecs); goto out; } if (!strncmp(uev->action, "remove", 6)) { - r = uev_remove_path(sysdev, vecs); + r = uev_remove_path(uev, vecs); goto out; } @@ -1383,6 +1392,9 @@ child (void * param) FREE(vecs); vecs = NULL; + cleanup_checkers(); + cleanup_prio(); + condlog(2, "--------shut down-------"); if (logsink) diff --git a/multipathd/main.h b/multipathd/main.h index d73cd70..5d6f1b8 100644 --- a/multipathd/main.h +++ b/multipathd/main.h @@ -7,7 +7,7 @@ int reconfigure (struct vectors *); int ev_add_path (char *, struct vectors *); int ev_remove_path (char *, struct vectors *); -int ev_add_map (struct sysfs_device *, struct vectors *); +int ev_add_map (char *, int, int, struct vectors *); int ev_remove_map (char *, struct vectors *); void sync_map_state (struct multipath *); -- 1.5.3.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor