This patch depends on a kernel patch yet to be merged. Beware.
Also fixed callers of dm_info() to check for <=0 as an error instead of
just == 0.
Edward Goggin, EMC.
cmpp = find_mp_by_wwid(curmp, mpp->wwid);
if (cmpp && !conf->dry_run) {
- condlog(2, "remove: %s (dup of %s)",
+ condlog(2, "%s: rename: %s to %s", mpp->wwid,
cmpp->alias, mpp->alias);
dm_flush_map(cmpp->alias, DEFAULT_TARGET);
+ strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
+ mpp->action = ACT_RENAME;
+ }
+ else {
+ condlog(3, "set ACT_CREATE: map does not exist");
+ mpp->action = ACT_CREATE;
}
mpp->action = ACT_CREATE;
condlog(3, "set ACT_CREATE: map does not exists");
if (!find_mp_by_wwid(curmp, mpp->wwid)) {
condlog(2, "remove: %s (wwid changed)", cmpp->alias);
- dm_flush_map(mpp->alias, NULL);
+ dm_flush_map(mpp->alias, DEFAULT_TARGET);
strncat(cmpp->wwid, mpp->wwid, WWID_SIZE);
drop_multipath(curmp, cmpp->wwid, KEEP_PATHS);
mpp->action = ACT_CREATE;
condlog(3, "%s: failed to load map "
"(a path might be in use)",
mpp->alias);
- dm_flush_map(mpp->alias, NULL);
+ dm_flush_map(mpp->alias, DEFAULT_TARGET);
}
lock_multipath(mpp, 0);
dm_simplecmd(DM_DEVICE_RESUME, mpp->alias));
break;
+ case ACT_RENAME:
+ r = dm_rename(mpp->alias_old, mpp->alias);
+ break;
+
default:
break;
}
if (r) {
/*
- * DM_DEVICE_CREATE or DM_DEVICE_RELOAD succeeded
+ * DM_DEVICE_CREATE, DM_DEIVCE_RENAME, or DM_DEVICE_RELOAD
+ * succeeded
*/
#ifndef DAEMON
dm_switchgroup(mpp->alias, mpp->bestpg);
if (pp1->priority < 0)
mpp->action = ACT_REJECT;
- if (!mpp->paths)
- return 1;
+ if (!mpp->paths) {
+ condlog(0, "%s coalesce_paths: no paths", mpp->alias);
+ remove_map(mpp, vecs, NULL, 0);
+ continue;
+ }
for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
pp2 = VECTOR_SLOT(pathvec, i);
r = domap(mpp);
if (!r) {
- condlog(0, "%s: domap failure for create/reload map",
- mpp->alias);
+ condlog(0, "%s: domap (%u) failure "
+ "for create/reload map",
+ mpp->alias, r);
remove_map(mpp, vecs, NULL, 0);
continue;
}
- else if (r < 0)
+ else if (r < 0) {
+ condlog(0, "%s: domap (%u) failure "
+ "for create/reload map",
+ mpp->alias, r);
return r;
+ }
if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
* configurator actions
*/
#define ACT_NOTHING_STR "unchanged"
+#define ACT_REJECT_STR "reject"
#define ACT_RELOAD_STR "reload"
#define ACT_SWITCHPG_STR "switchpg"
+#define ACT_RENAME_STR "rename"
#define ACT_CREATE_STR "create"
enum actions {
ACT_REJECT,
ACT_RELOAD,
ACT_SWITCHPG,
+ ACT_RENAME,
ACT_CREATE
};
if (!dm_map_present(mapname))
return 0;
- if (!dm_type(mapname, type))
+ if (dm_type(mapname, type) <= 0)
return 1;
if (dm_remove_partmaps(mapname))
do {
info = dm_type(names->name, type);
- if (!info)
+ if (info <= 0)
goto next;
mpp = alloc_multipath();
return r;
}
+extern int
+dm_get_name(char *uuid, char *type, char *name)
+{
+ vector vec;
+ struct multipath *mpp;
+ int i;
+
+ vec = vector_alloc();
+
+ if (!vec)
+ return 0;
+
+ if (dm_get_maps(vec, type)) {
+ vector_free(vec);
+ return 0;
+ }
+
+ vector_foreach_slot(vec, mpp, i) {
+ if (!strcmp(uuid, mpp->wwid)) {
+ vector_free(vec);
+ strcpy(name, mpp->alias);
+ return 1;
+ }
+ }
+
+ vector_free(vec);
+ return 0;
+}
+
int
dm_geteventnr (char *name)
{
/*
* if devmap target is "linear"
*/
- dm_type(names->name, "linear") &&
+ (dm_type(names->name, "linear") > 0) &&
/*
* and the multipath mapname and the part mapname start
return r;
}
-#if 0
int
dm_rename (char * old, char * new)
{
dm_task_destroy(dmt);
return r;
}
-#endif
int dm_remove_partmaps (char * mapname);
int dm_get_uuid(char *name, char *uuid);
int dm_get_info (char * mapname, struct dm_info ** dmi);
-
-#if 0
int dm_rename (char * old, char * new);
-#endif
+int dm_get_name(char * uuid, char * type, char * name);
#include "structs.h"
#include "config.h"
#include "debug.h"
+#include "structs_vec.h"
struct path *
alloc_path (void)
if (mpp->dmi)
FREE(mpp->dmi);
+#if DAEMON
+ /*
+ * better own vecs->lock here
+ */
+ if (mpp->waiter)
+ ((struct event_thread *)mpp->waiter)->mpp = NULL;
+#endif
+
free_pathvec(mpp->paths, free_paths);
free_pgvec(mpp->pg, free_paths);
FREE(mpp);
struct multipath {
char wwid[WWID_SIZE];
+ char alias_old[WWID_SIZE];
int pgpolicy;
pgpolicyfn *pgpolicyfn;
int nextpg;
#include <unistd.h>
#include "vector.h"
+#include "defaults.h"
#include "debug.h"
#include "structs.h"
#include "structs_vec.h"
extern int
setup_multipath (struct vectors * vecs, struct multipath * mpp)
{
+retry:
if (dm_get_info(mpp->alias, &mpp->dmi))
goto out;
set_multipath_wwid(mpp);
mpp->mpe = find_mpe(mpp->wwid);
- condlog(4, "discovered map %s", mpp->alias);
+ condlog(3, "discovered map %s", mpp->alias);
- if (update_multipath_strings(mpp, vecs->pathvec))
+ if (update_multipath_strings(mpp, vecs->pathvec)) {
+ char new_alias[WWID_SIZE];
+
+ /*
+ * detect an external rename of the multipath device
+ */
+ if (dm_get_name(mpp->wwid, DEFAULT_TARGET, new_alias)) {
+ condlog(3, "%s multipath mapped device name has "
+ "changed from %s to %s", mpp->wwid,
+ mpp->alias, new_alias);
+ strcpy(mpp->alias, new_alias);
+#if DAEMON
+ if (mpp->waiter)
+ strncpy(((struct event_thread *)mpp->waiter)->mapname,
+ new_alias, WWID_SIZE);
+#endif
+ goto retry;
+ }
goto out;
+ }
//adopt_paths(vecs->pathvec, mpp);
mpp->hwe = extract_hwe_from_path(mpp);
vector mpvec;
};
+#if DAEMON
+struct event_thread {
+ struct dm_task *dmt;
+ pthread_t thread;
+ int event_nr;
+ char mapname[WWID_SIZE];
+ struct vectors *vecs;
+ struct multipath *mpp;
+};
+#endif
+
typedef void (stop_waiter_thread_func) (struct multipath *, struct vectors *);
typedef int (start_waiter_thread_func) (struct multipath *, struct vectors *);
*/
struct vectors * gvecs; /* global copy of vecs for use in sig handlers */
-struct event_thread {
- struct dm_task *dmt;
- pthread_t thread;
- int event_nr;
- char mapname[WWID_SIZE];
- struct vectors *vecs;
-};
-
static struct event_thread *
alloc_waiter (void)
{
{
struct event_thread * wp = (struct event_thread *)data;
+ /*
+ * indicate in mpp that the wp is already freed storage
+ */
+ lock(wp->vecs->lock);
+
+ if (wp->mpp)
+ /*
+ * be careful, mpp may already be freed -- null if so
+ */
+ wp->mpp->waiter = NULL;
+ else
+ condlog(3, "free_waiter, mpp freed before wp=%p,", wp);
+
+ unlock(wp->vecs->lock);
+
if (wp->dmt)
dm_task_destroy(wp->dmt);
+
FREE(wp);
}
mpp->waiter = (void *)wp;
strncpy(wp->mapname, mpp->alias, WWID_SIZE);
wp->vecs = vecs;
+ wp->mpp = mpp;
if (pthread_create(&wp->thread, &attr, waitevent, wp)) {
condlog(0, "%s: cannot create event checker", wp->mapname);
if (!alias)
return 1;
- if (!dm_type(alias, DEFAULT_TARGET)) {
+ if (dm_type(alias, DEFAULT_TARGET) <= 0) {
condlog(4, "%s: not a multipath map", alias);
FREE(alias);
return 0;
if (dm_get_maps(vecs->mpvec, "multipath"))
return 1;
- vector_foreach_slot (vecs->mpvec, mpp, i) {
+ vector_foreach_slot (vecs->mpvec, mpp, i)
if (setup_multipath(vecs, mpp))
return 1;
- if (start_waiter_thread(mpp, vecs))
- return 1;
- }
return 0;
}
r = uev_add_map(devname, vecs);
goto out;
}
-#if 0
if (!strncmp(uev->action, "remove", 6)) {
r = uev_remove_map(devname, vecs);
goto out;
}
-#endif
goto out;
}