device-mapper-multipath-0.4.9-71
Add 0103-RH-cleanup-partmaps-code.patch * code refactoring to prepare for next patch Add 0104-RHBZ-631009-deferred-remove.patch * add deferred_remove option to /etc/multipath.conf Add 0105-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch * Only run kpartx on device activation Add 0106-RHBZ-1159337-fix-double-free.patch * made ev_remove_path exit immediately after failing setup_multipath, since it handles cleaning up the device Add 0107-RHBZ-1169935-no-new-devs.patch * Add new multipathd option '-n' which keeps multipathd from creating any multipath devices that aren't in the /etc/multipath/wwids file. Add 0108-RHBZ-1153832-kpartx-remove-devs.patch * switch from 'kpartx -a' to 'kpartx -u' to remove missing devices as well. Add 0109-RH-read-only-bindings.patch * re-enabled -B option for multipathd
This commit is contained in:
parent
8795157d36
commit
fdb6ec8779
199
0103-RH-cleanup-partmaps-code.patch
Normal file
199
0103-RH-cleanup-partmaps-code.patch
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 155 ++++++++++++++++++-----------------------------
|
||||||
|
1 file changed, 61 insertions(+), 94 deletions(-)
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/libmultipath/devmapper.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/devmapper.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/devmapper.c
|
||||||
|
@@ -1006,8 +1006,9 @@ bad:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-dm_remove_partmaps (const char * mapname, int need_sync)
|
||||||
|
+static int
|
||||||
|
+do_foreach_partmaps (const char * mapname, int (*partmap_func)(char *, void *),
|
||||||
|
+ void *data)
|
||||||
|
{
|
||||||
|
struct dm_task *dmt;
|
||||||
|
struct dm_names *names;
|
||||||
|
@@ -1059,26 +1060,8 @@ dm_remove_partmaps (const char * mapname
|
||||||
|
*/
|
||||||
|
strstr(params, dev_t)
|
||||||
|
) {
|
||||||
|
- /*
|
||||||
|
- * then it's a kpartx generated partition.
|
||||||
|
- * remove it.
|
||||||
|
- */
|
||||||
|
- /*
|
||||||
|
- * if the opencount is 0 maybe some other
|
||||||
|
- * partitions depend on it.
|
||||||
|
- */
|
||||||
|
- if (dm_get_opencount(names->name)) {
|
||||||
|
- dm_remove_partmaps(names->name, need_sync);
|
||||||
|
- if (dm_get_opencount(names->name)) {
|
||||||
|
- condlog(2, "%s: map in use",
|
||||||
|
- names->name);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- condlog(4, "partition map %s removed",
|
||||||
|
- names->name);
|
||||||
|
- dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name,
|
||||||
|
- need_sync, 0);
|
||||||
|
+ if (partmap_func(names->name, data) != 0)
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
next = names->next;
|
||||||
|
@@ -1091,6 +1074,35 @@ out:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct remove_data {
|
||||||
|
+ int need_sync;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+remove_partmap(char *name, void *data)
|
||||||
|
+{
|
||||||
|
+ struct remove_data *rd = (struct remove_data *)data;
|
||||||
|
+
|
||||||
|
+ if (dm_get_opencount(name)) {
|
||||||
|
+ dm_remove_partmaps(name, rd->need_sync);
|
||||||
|
+ if (dm_get_opencount(name)) {
|
||||||
|
+ condlog(2, "%s: map in use", name);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ condlog(4, "partition map %s removed", name);
|
||||||
|
+ dm_simplecmd_flush(DM_DEVICE_REMOVE, name,
|
||||||
|
+ rd->need_sync, 0);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+dm_remove_partmaps (const char * mapname, int need_sync)
|
||||||
|
+{
|
||||||
|
+ struct remove_data rd = { need_sync };
|
||||||
|
+ return do_foreach_partmaps(mapname, remove_partmap, &rd);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct dm_info *
|
||||||
|
alloc_dminfo (void)
|
||||||
|
{
|
||||||
|
@@ -1140,86 +1152,41 @@ out:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-dm_rename_partmaps (char * old, char * new)
|
||||||
|
+struct rename_data {
|
||||||
|
+ char *old;
|
||||||
|
+ char *new;
|
||||||
|
+ char *delim;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+rename_partmap (char *name, void *data)
|
||||||
|
{
|
||||||
|
- struct dm_task *dmt;
|
||||||
|
- struct dm_names *names;
|
||||||
|
- unsigned next = 0;
|
||||||
|
char buff[PARAMS_SIZE];
|
||||||
|
- unsigned long long size;
|
||||||
|
- char dev_t[32];
|
||||||
|
- int r = 1;
|
||||||
|
int offset;
|
||||||
|
- char *delim;
|
||||||
|
-
|
||||||
|
- if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
|
||||||
|
- return 1;
|
||||||
|
+ struct rename_data *rd = (struct rename_data *)data;
|
||||||
|
|
||||||
|
- dm_task_no_open_count(dmt);
|
||||||
|
-
|
||||||
|
- if (!dm_task_run(dmt))
|
||||||
|
- goto out;
|
||||||
|
-
|
||||||
|
- if (!(names = dm_task_get_names(dmt)))
|
||||||
|
- goto out;
|
||||||
|
-
|
||||||
|
- if (!names->dev) {
|
||||||
|
- r = 0; /* this is perfectly valid */
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
+ if (strncmp(name, rd->old, strlen(rd->old)) != 0)
|
||||||
|
+ return 0;
|
||||||
|
+ for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */
|
||||||
|
+ snprintf(buff, PARAMS_SIZE, "%s%s%s", rd->new, rd->delim,
|
||||||
|
+ name + offset);
|
||||||
|
+ dm_rename(name, buff);
|
||||||
|
+ condlog(4, "partition map %s renamed", name);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- if (dm_dev_t(old, &dev_t[0], 32))
|
||||||
|
- goto out;
|
||||||
|
+int
|
||||||
|
+dm_rename_partmaps (char * old, char * new)
|
||||||
|
+{
|
||||||
|
+ struct rename_data rd;
|
||||||
|
|
||||||
|
+ rd.old = old;
|
||||||
|
+ rd.new = new;
|
||||||
|
if (isdigit(new[strlen(new)-1]))
|
||||||
|
- delim = "p";
|
||||||
|
+ rd.delim = "p";
|
||||||
|
else
|
||||||
|
- delim = "";
|
||||||
|
-
|
||||||
|
- do {
|
||||||
|
- if (
|
||||||
|
- /*
|
||||||
|
- * if devmap target is "linear"
|
||||||
|
- */
|
||||||
|
- (dm_type(names->name, TGT_PART) > 0) &&
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * and the multipath mapname and the part mapname start
|
||||||
|
- * the same
|
||||||
|
- */
|
||||||
|
- !strncmp(names->name, old, strlen(old)) &&
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * and we can fetch the map table from the kernel
|
||||||
|
- */
|
||||||
|
- !dm_get_map(names->name, &size, &buff[0]) &&
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * and the table maps over the multipath map
|
||||||
|
- */
|
||||||
|
- strstr(buff, dev_t)
|
||||||
|
- ) {
|
||||||
|
- /*
|
||||||
|
- * then it's a kpartx generated partition.
|
||||||
|
- * Rename it.
|
||||||
|
- */
|
||||||
|
- for (offset = strlen(old); names->name[offset] && !(isdigit(names->name[offset])); offset++); /* do nothing */
|
||||||
|
- snprintf(buff, PARAMS_SIZE, "%s%s%s",
|
||||||
|
- new, delim, names->name + offset);
|
||||||
|
- dm_rename(names->name, buff);
|
||||||
|
- condlog(4, "partition map %s renamed",
|
||||||
|
- names->name);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- next = names->next;
|
||||||
|
- names = (void *) names + next;
|
||||||
|
- } while (next);
|
||||||
|
-
|
||||||
|
- r = 0;
|
||||||
|
-out:
|
||||||
|
- dm_task_destroy (dmt);
|
||||||
|
- return r;
|
||||||
|
+ rd.delim = "";
|
||||||
|
+ return do_foreach_partmaps(old, rename_partmap, &rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
751
0104-RHBZ-631009-deferred-remove.patch
Normal file
751
0104-RHBZ-631009-deferred-remove.patch
Normal file
@ -0,0 +1,751 @@
|
|||||||
|
---
|
||||||
|
libmultipath/Makefile | 6 ++
|
||||||
|
libmultipath/config.c | 3 +
|
||||||
|
libmultipath/config.h | 3 +
|
||||||
|
libmultipath/configure.c | 1
|
||||||
|
libmultipath/defaults.h | 1
|
||||||
|
libmultipath/devmapper.c | 130 +++++++++++++++++++++++++++++++++++++++------
|
||||||
|
libmultipath/devmapper.h | 12 ++--
|
||||||
|
libmultipath/dict.c | 116 +++++++++++++++++++++++++++++++++++++++-
|
||||||
|
libmultipath/propsel.c | 28 +++++++++
|
||||||
|
libmultipath/propsel.h | 1
|
||||||
|
libmultipath/structs.h | 8 ++
|
||||||
|
libmultipath/structs_vec.c | 3 -
|
||||||
|
multipath/multipath.conf.5 | 14 ++++
|
||||||
|
multipathd/main.c | 23 +++++--
|
||||||
|
14 files changed, 322 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/libmultipath/config.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/config.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/config.c
|
||||||
|
@@ -337,6 +337,7 @@ merge_hwe (struct hwentry * dst, struct
|
||||||
|
merge_num(user_friendly_names);
|
||||||
|
merge_num(retain_hwhandler);
|
||||||
|
merge_num(detect_prio);
|
||||||
|
+ merge_num(deferred_remove);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure features is consistent with
|
||||||
|
@@ -394,6 +395,7 @@ overwrite_hwe (struct hwentry * dst, str
|
||||||
|
overwrite_num(user_friendly_names);
|
||||||
|
overwrite_num(retain_hwhandler);
|
||||||
|
overwrite_num(detect_prio);
|
||||||
|
+ overwrite_num(deferred_remove);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure features is consistent with
|
||||||
|
@@ -617,6 +619,7 @@ load_config (char * file, struct udev *u
|
||||||
|
conf->fast_io_fail = DEFAULT_FAST_IO_FAIL;
|
||||||
|
conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
|
||||||
|
conf->detect_prio = DEFAULT_DETECT_PRIO;
|
||||||
|
+ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE;
|
||||||
|
conf->hw_strmatch = 0;
|
||||||
|
conf->force_sync = 0;
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/libmultipath/config.h
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/config.h
|
||||||
|
+++ multipath-tools-130222/libmultipath/config.h
|
||||||
|
@@ -61,6 +61,7 @@ struct hwentry {
|
||||||
|
int user_friendly_names;
|
||||||
|
int retain_hwhandler;
|
||||||
|
int detect_prio;
|
||||||
|
+ int deferred_remove;
|
||||||
|
char * bl_product;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -84,6 +85,7 @@ struct mpentry {
|
||||||
|
int flush_on_last_del;
|
||||||
|
int attribute_flags;
|
||||||
|
int user_friendly_names;
|
||||||
|
+ int deferred_remove;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
mode_t mode;
|
||||||
|
@@ -128,6 +130,7 @@ struct config {
|
||||||
|
int retain_hwhandler;
|
||||||
|
int detect_prio;
|
||||||
|
int force_sync;
|
||||||
|
+ int deferred_remove;
|
||||||
|
unsigned int version[3];
|
||||||
|
|
||||||
|
char * dev;
|
||||||
|
Index: multipath-tools-130222/libmultipath/configure.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/configure.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/configure.c
|
||||||
|
@@ -290,6 +290,7 @@ setup_map (struct multipath * mpp, char
|
||||||
|
select_dev_loss(mpp);
|
||||||
|
select_reservation_key(mpp);
|
||||||
|
select_retain_hwhandler(mpp);
|
||||||
|
+ select_deferred_remove(mpp);
|
||||||
|
|
||||||
|
sysfs_set_scsi_tmo(mpp);
|
||||||
|
/*
|
||||||
|
Index: multipath-tools-130222/libmultipath/defaults.h
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/defaults.h
|
||||||
|
+++ multipath-tools-130222/libmultipath/defaults.h
|
||||||
|
@@ -19,6 +19,7 @@
|
||||||
|
#define DEFAULT_FAST_IO_FAIL 5
|
||||||
|
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
|
||||||
|
#define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF
|
||||||
|
+#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF
|
||||||
|
|
||||||
|
#define DEFAULT_CHECKINT 5
|
||||||
|
#define MAX_CHECKINT(a) (a << 2)
|
||||||
|
Index: multipath-tools-130222/libmultipath/devmapper.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/devmapper.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/devmapper.c
|
||||||
|
@@ -103,7 +103,9 @@ dm_lib_prereq (void)
|
||||||
|
{
|
||||||
|
char version[64];
|
||||||
|
int v[3];
|
||||||
|
-#if defined(DM_SUBSYSTEM_UDEV_FLAG0)
|
||||||
|
+#if defined(LIBDM_API_DEFERRED)
|
||||||
|
+ int minv[3] = {1, 2, 89};
|
||||||
|
+#elif defined(DM_SUBSYSTEM_UDEV_FLAG0)
|
||||||
|
int minv[3] = {1, 2, 82};
|
||||||
|
#elif defined(LIBDM_API_COOKIE)
|
||||||
|
int minv[3] = {1, 2, 38};
|
||||||
|
@@ -202,7 +204,7 @@ dm_prereq (void)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags) {
|
||||||
|
+dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) {
|
||||||
|
int r = 0;
|
||||||
|
int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME ||
|
||||||
|
task == DM_DEVICE_REMOVE));
|
||||||
|
@@ -220,7 +222,10 @@ dm_simplecmd (int task, const char *name
|
||||||
|
if (no_flush)
|
||||||
|
dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */
|
||||||
|
#endif
|
||||||
|
-
|
||||||
|
+#ifdef LIBDM_API_DEFERRED
|
||||||
|
+ if (deferred_remove)
|
||||||
|
+ dm_task_deferred_remove(dmt);
|
||||||
|
+#endif
|
||||||
|
if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags))
|
||||||
|
goto out;
|
||||||
|
r = dm_task_run (dmt);
|
||||||
|
@@ -232,12 +237,18 @@ dm_simplecmd (int task, const char *name
|
||||||
|
|
||||||
|
extern int
|
||||||
|
dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) {
|
||||||
|
- return dm_simplecmd(task, name, 0, needsync, udev_flags);
|
||||||
|
+ return dm_simplecmd(task, name, 0, needsync, udev_flags, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int
|
||||||
|
dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) {
|
||||||
|
- return dm_simplecmd(task, name, 1, 1, udev_flags);
|
||||||
|
+ return dm_simplecmd(task, name, 1, 1, udev_flags, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+extern int
|
||||||
|
+dm_device_remove (const char *name, int needsync, int deferred_remove) {
|
||||||
|
+ return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, needsync, 0,
|
||||||
|
+ deferred_remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int
|
||||||
|
@@ -653,7 +664,7 @@ out:
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int
|
||||||
|
-_dm_flush_map (const char * mapname, int need_sync)
|
||||||
|
+_dm_flush_map (const char * mapname, int need_sync, int deferred_remove)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
@@ -663,23 +674,46 @@ _dm_flush_map (const char * mapname, int
|
||||||
|
if (dm_type(mapname, TGT_MPATH) <= 0)
|
||||||
|
return 0; /* nothing to do */
|
||||||
|
|
||||||
|
- if (dm_remove_partmaps(mapname, need_sync))
|
||||||
|
+ if (dm_remove_partmaps(mapname, need_sync, deferred_remove))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- if (dm_get_opencount(mapname)) {
|
||||||
|
+ if (!deferred_remove && dm_get_opencount(mapname)) {
|
||||||
|
condlog(2, "%s: map in use", mapname);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync, 0);
|
||||||
|
+ r = dm_device_remove(mapname, need_sync, deferred_remove);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
+ if (deferred_remove && dm_map_present(mapname)) {
|
||||||
|
+ condlog(4, "multipath map %s remove deferred",
|
||||||
|
+ mapname);
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
condlog(4, "multipath map %s removed", mapname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef LIBDM_API_DEFERRED
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+dm_flush_map_nopaths(const char * mapname, int deferred_remove)
|
||||||
|
+{
|
||||||
|
+ return _dm_flush_map(mapname, 1, deferred_remove);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#else
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+dm_flush_map_nopaths(const char * mapname, int deferred_remove)
|
||||||
|
+{
|
||||||
|
+ return _dm_flush_map(mapname, 1, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
extern int
|
||||||
|
dm_suspend_and_flush_map (const char * mapname)
|
||||||
|
{
|
||||||
|
@@ -1076,6 +1110,7 @@ out:
|
||||||
|
|
||||||
|
struct remove_data {
|
||||||
|
int need_sync;
|
||||||
|
+ int deferred_remove;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -1084,25 +1119,90 @@ remove_partmap(char *name, void *data)
|
||||||
|
struct remove_data *rd = (struct remove_data *)data;
|
||||||
|
|
||||||
|
if (dm_get_opencount(name)) {
|
||||||
|
- dm_remove_partmaps(name, rd->need_sync);
|
||||||
|
- if (dm_get_opencount(name)) {
|
||||||
|
+ dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove);
|
||||||
|
+ if (!rd->deferred_remove && dm_get_opencount(name)) {
|
||||||
|
condlog(2, "%s: map in use", name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
condlog(4, "partition map %s removed", name);
|
||||||
|
- dm_simplecmd_flush(DM_DEVICE_REMOVE, name,
|
||||||
|
- rd->need_sync, 0);
|
||||||
|
+ dm_device_remove(name, rd->need_sync, rd->deferred_remove);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-dm_remove_partmaps (const char * mapname, int need_sync)
|
||||||
|
+dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove)
|
||||||
|
{
|
||||||
|
- struct remove_data rd = { need_sync };
|
||||||
|
+ struct remove_data rd = { need_sync, deferred_remove };
|
||||||
|
return do_foreach_partmaps(mapname, remove_partmap, &rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef LIBDM_API_DEFERRED
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+cancel_remove_partmap (char *name, void *unused)
|
||||||
|
+{
|
||||||
|
+ if (dm_message(name, "@cancel_deferred_remove") != 0)
|
||||||
|
+ condlog(0, "%s: can't cancel deferred remove: %s", name,
|
||||||
|
+ strerror(errno));
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+dm_get_deferred_remove (char * mapname)
|
||||||
|
+{
|
||||||
|
+ int r = -1;
|
||||||
|
+ struct dm_task *dmt;
|
||||||
|
+ struct dm_info info;
|
||||||
|
+
|
||||||
|
+ if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ 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.deferred_remove;
|
||||||
|
+out:
|
||||||
|
+ dm_task_destroy(dmt);
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+dm_cancel_deferred_remove (struct multipath *mpp)
|
||||||
|
+{
|
||||||
|
+ int r = 0;
|
||||||
|
+
|
||||||
|
+ if (!dm_get_deferred_remove(mpp->alias))
|
||||||
|
+ return 0;
|
||||||
|
+ if (mpp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS)
|
||||||
|
+ mpp->deferred_remove = DEFERRED_REMOVE_ON;
|
||||||
|
+
|
||||||
|
+ do_foreach_partmaps(mpp->alias, cancel_remove_partmap, NULL);
|
||||||
|
+ r = dm_message(mpp->alias, "@cancel_deferred_remove");
|
||||||
|
+ if (r)
|
||||||
|
+ condlog(0, "%s: can't cancel deferred remove: %s", mpp->alias,
|
||||||
|
+ strerror(errno));
|
||||||
|
+ else
|
||||||
|
+ condlog(2, "%s: canceled deferred remove", mpp->alias);
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#else
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+dm_cancel_deferred_remove (struct multipath *mpp)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static struct dm_info *
|
||||||
|
alloc_dminfo (void)
|
||||||
|
{
|
||||||
|
Index: multipath-tools-130222/libmultipath/devmapper.h
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/devmapper.h
|
||||||
|
+++ multipath-tools-130222/libmultipath/devmapper.h
|
||||||
|
@@ -17,15 +17,18 @@ int dm_prereq (void);
|
||||||
|
int dm_drv_version (unsigned int * version, char * str);
|
||||||
|
int dm_simplecmd_flush (int, const char *, int, uint16_t);
|
||||||
|
int dm_simplecmd_noflush (int, const char *, uint16_t);
|
||||||
|
+int dm_device_remove (const char *, int, int);
|
||||||
|
int dm_addmap_create (struct multipath *mpp, char *params);
|
||||||
|
int dm_addmap_reload (struct multipath *mpp, char *params);
|
||||||
|
int dm_map_present (const char *);
|
||||||
|
int dm_get_map(const char *, unsigned long long *, char *);
|
||||||
|
int dm_get_status(char *, char *);
|
||||||
|
int dm_type(const char *, char *);
|
||||||
|
-int _dm_flush_map (const char *, int);
|
||||||
|
-#define dm_flush_map(mapname) _dm_flush_map(mapname, 1)
|
||||||
|
-#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0)
|
||||||
|
+int _dm_flush_map (const char *, int, int);
|
||||||
|
+int dm_flush_map_nopaths(const char * mapname, int deferred_remove);
|
||||||
|
+#define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0)
|
||||||
|
+#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0, 0)
|
||||||
|
+int dm_cancel_deferred_remove(struct multipath *mpp);
|
||||||
|
int dm_suspend_and_flush_map(const char * mapname);
|
||||||
|
int dm_flush_maps (void);
|
||||||
|
int dm_fail_path(char * mapname, char * path);
|
||||||
|
@@ -40,7 +43,8 @@ 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, int need_sync);
|
||||||
|
+int dm_remove_partmaps (const char * mapname, int need_sync,
|
||||||
|
+ int deferred_remove);
|
||||||
|
int dm_get_uuid(char *name, char *uuid);
|
||||||
|
int dm_get_info (char * mapname, struct dm_info ** dmi);
|
||||||
|
int dm_rename (char * old, char * new);
|
||||||
|
Index: multipath-tools-130222/libmultipath/dict.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/dict.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/dict.c
|
||||||
|
@@ -738,6 +738,29 @@ def_force_sync_handler(vector strvec)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+def_deferred_remove_handler(vector strvec)
|
||||||
|
+{
|
||||||
|
+ char * buff;
|
||||||
|
+
|
||||||
|
+ buff = set_value(strvec);
|
||||||
|
+
|
||||||
|
+ if (!buff)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
|
||||||
|
+ (strlen(buff) == 1 && !strcmp(buff, "0")))
|
||||||
|
+ conf->deferred_remove = DEFERRED_REMOVE_OFF;
|
||||||
|
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
|
||||||
|
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
|
||||||
|
+ conf->deferred_remove = DEFERRED_REMOVE_ON;
|
||||||
|
+ else
|
||||||
|
+ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE;
|
||||||
|
+
|
||||||
|
+ FREE(buff);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* blacklist block handlers
|
||||||
|
*/
|
||||||
|
@@ -1445,6 +1468,33 @@ hw_detect_prio_handler(vector strvec)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+hw_deferred_remove_handler(vector strvec)
|
||||||
|
+{
|
||||||
|
+ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
|
||||||
|
+ char * buff;
|
||||||
|
+
|
||||||
|
+ if (!hwe)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ buff = set_value(strvec);
|
||||||
|
+
|
||||||
|
+ if (!buff)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
|
||||||
|
+ (strlen(buff) == 1 && !strcmp(buff, "0")))
|
||||||
|
+ hwe->deferred_remove = DEFERRED_REMOVE_OFF;
|
||||||
|
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
|
||||||
|
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
|
||||||
|
+ hwe->deferred_remove = DEFERRED_REMOVE_ON;
|
||||||
|
+ else
|
||||||
|
+ hwe->deferred_remove = DEFERRED_REMOVE_UNDEF;
|
||||||
|
+
|
||||||
|
+ FREE(buff);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* multipaths block handlers
|
||||||
|
*/
|
||||||
|
@@ -1920,6 +1970,32 @@ mp_names_handler(vector strvec)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+mp_deferred_remove_handler(vector strvec)
|
||||||
|
+{
|
||||||
|
+ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
|
||||||
|
+ char * buff;
|
||||||
|
+
|
||||||
|
+ if (!mpe)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ buff = set_value(strvec);
|
||||||
|
+ if (!buff)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) ||
|
||||||
|
+ (strlen(buff) == 1 && strcmp(buff, "0") == 0))
|
||||||
|
+ mpe->deferred_remove = DEFERRED_REMOVE_OFF;
|
||||||
|
+ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) ||
|
||||||
|
+ (strlen(buff) == 1 && strcmp(buff, "1") == 0))
|
||||||
|
+ mpe->deferred_remove = DEFERRED_REMOVE_ON;
|
||||||
|
+ else
|
||||||
|
+ mpe->deferred_remove = DEFERRED_REMOVE_UNDEF;
|
||||||
|
+
|
||||||
|
+ FREE(buff);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* config file keywords printing
|
||||||
|
*/
|
||||||
|
@@ -2165,7 +2241,7 @@ snprint_mp_reservation_key (char * buff,
|
||||||
|
return snprintf(buff, len, "0x%" PRIx64, prkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
- static int
|
||||||
|
+static int
|
||||||
|
snprint_mp_user_friendly_names (char * buff, int len, void * data)
|
||||||
|
{
|
||||||
|
struct mpentry * mpe = (struct mpentry *)data;
|
||||||
|
@@ -2179,6 +2255,19 @@ snprint_mp_user_friendly_names (char * b
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
+snprint_mp_deferred_remove (char * buff, int len, void * data)
|
||||||
|
+{
|
||||||
|
+ struct mpentry * mpe = (struct mpentry *)data;
|
||||||
|
+
|
||||||
|
+ if (mpe->deferred_remove == DEFERRED_REMOVE_UNDEF)
|
||||||
|
+ return 0;
|
||||||
|
+ else if (mpe->deferred_remove == DEFERRED_REMOVE_OFF)
|
||||||
|
+ return snprintf(buff, len, "no");
|
||||||
|
+ else
|
||||||
|
+ return snprintf(buff, len, "yes");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
snprint_hw_fast_io_fail(char * buff, int len, void * data)
|
||||||
|
{
|
||||||
|
struct hwentry * hwe = (struct hwentry *)data;
|
||||||
|
@@ -2507,6 +2596,19 @@ snprint_hw_retain_hwhandler_handler(char
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
+snprint_hw_deferred_remove(char * buff, int len, void * data)
|
||||||
|
+{
|
||||||
|
+ struct hwentry * hwe = (struct hwentry *)data;
|
||||||
|
+
|
||||||
|
+ if (hwe->deferred_remove == DEFERRED_REMOVE_ON)
|
||||||
|
+ return snprintf(buff, len, "yes");
|
||||||
|
+ else if (hwe->deferred_remove == DEFERRED_REMOVE_OFF)
|
||||||
|
+ return snprintf(buff, len, "no");
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
snprint_detect_prio(char * buff, int len, void * data)
|
||||||
|
{
|
||||||
|
struct hwentry * hwe = (struct hwentry *)data;
|
||||||
|
@@ -2900,6 +3002,15 @@ snprint_def_force_sync(char * buff, int
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
+snprint_def_deferred_remove(char * buff, int len, void * data)
|
||||||
|
+{
|
||||||
|
+ if (conf->deferred_remove == DEFERRED_REMOVE_ON)
|
||||||
|
+ return snprintf(buff, len, "yes");
|
||||||
|
+ else
|
||||||
|
+ return snprintf(buff, len, "no");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
snprint_ble_simple (char * buff, int len, void * data)
|
||||||
|
{
|
||||||
|
struct blentry * ble = (struct blentry *)data;
|
||||||
|
@@ -2968,6 +3079,7 @@ init_keywords(void)
|
||||||
|
install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio);
|
||||||
|
install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch);
|
||||||
|
install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
|
||||||
|
+ install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
|
||||||
|
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
|
||||||
|
@@ -3032,6 +3144,7 @@ init_keywords(void)
|
||||||
|
install_keyword("user_friendly_names", &hw_names_handler, &snprint_hw_user_friendly_names);
|
||||||
|
install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler);
|
||||||
|
install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_detect_prio);
|
||||||
|
+ install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove);
|
||||||
|
install_sublevel_end();
|
||||||
|
|
||||||
|
install_keyword_root("multipaths", &multipaths_handler);
|
||||||
|
@@ -3056,5 +3169,6 @@ init_keywords(void)
|
||||||
|
install_keyword("gid", &mp_gid_handler, &snprint_mp_gid);
|
||||||
|
install_keyword("reservation_key", &mp_reservation_key_handler, &snprint_mp_reservation_key);
|
||||||
|
install_keyword("user_friendly_names", &mp_names_handler, &snprint_mp_user_friendly_names);
|
||||||
|
+ install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove);
|
||||||
|
install_sublevel_end();
|
||||||
|
}
|
||||||
|
Index: multipath-tools-130222/libmultipath/propsel.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/propsel.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/propsel.c
|
||||||
|
@@ -744,6 +744,34 @@ select_retain_hwhandler (struct multipat
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int
|
||||||
|
+select_deferred_remove (struct multipath *mp)
|
||||||
|
+{
|
||||||
|
+ if (mp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) {
|
||||||
|
+ condlog(3, "%s: deferred_remove in progress", mp->alias);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ if (mp->mpe && mp->mpe->deferred_remove) {
|
||||||
|
+ mp->deferred_remove = mp->mpe->deferred_remove;
|
||||||
|
+ condlog(3, "%s: deferred_remove = %i (multipath setting)",
|
||||||
|
+ mp->alias, mp->deferred_remove);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ if (mp->hwe && mp->hwe->deferred_remove) {
|
||||||
|
+ mp->deferred_remove = mp->hwe->deferred_remove;
|
||||||
|
+ condlog(3, "%s: deferred_remove = %d (controller default)", mp->alias, mp->deferred_remove);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ if (conf->deferred_remove) {
|
||||||
|
+ mp->deferred_remove = conf->deferred_remove;
|
||||||
|
+ condlog(3, "%s: deferred_remove = %d (config file default)", mp->alias, mp->deferred_remove);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ mp->deferred_remove = DEFAULT_DEFERRED_REMOVE;
|
||||||
|
+ condlog(3, "%s: deferred_remove = %d (compiled in default)", mp->alias, mp->deferred_remove);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+extern int
|
||||||
|
select_detect_prio (struct path * pp)
|
||||||
|
{
|
||||||
|
if (pp->hwe && pp->hwe->detect_prio) {
|
||||||
|
Index: multipath-tools-130222/libmultipath/propsel.h
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/propsel.h
|
||||||
|
+++ multipath-tools-130222/libmultipath/propsel.h
|
||||||
|
@@ -20,3 +20,4 @@ int select_dev_loss(struct multipath *mp
|
||||||
|
int select_reservation_key(struct multipath *mp);
|
||||||
|
int select_retain_hwhandler (struct multipath * mp);
|
||||||
|
int select_detect_prio(struct path * pp);
|
||||||
|
+int select_deferred_remove(struct multipath *mp);
|
||||||
|
Index: multipath-tools-130222/libmultipath/structs.h
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/structs.h
|
||||||
|
+++ multipath-tools-130222/libmultipath/structs.h
|
||||||
|
@@ -114,6 +114,13 @@ enum detect_prio_states {
|
||||||
|
DETECT_PRIO_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
+enum deferred_remove_states {
|
||||||
|
+ DEFERRED_REMOVE_UNDEF,
|
||||||
|
+ DEFERRED_REMOVE_OFF,
|
||||||
|
+ DEFERRED_REMOVE_ON,
|
||||||
|
+ DEFERRED_REMOVE_IN_PROGRESS,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
enum scsi_protocol {
|
||||||
|
SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
|
||||||
|
SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
|
||||||
|
@@ -207,6 +214,7 @@ struct multipath {
|
||||||
|
int attribute_flags;
|
||||||
|
int fast_io_fail;
|
||||||
|
int retain_hwhandler;
|
||||||
|
+ int deferred_remove;
|
||||||
|
unsigned int dev_loss;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
Index: multipath-tools-130222/multipathd/main.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/multipathd/main.c
|
||||||
|
+++ multipath-tools-130222/multipathd/main.c
|
||||||
|
@@ -214,19 +214,30 @@ sync_maps_state(vector mpvec)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-flush_map(struct multipath * mpp, struct vectors * vecs)
|
||||||
|
+flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
|
||||||
|
{
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ if (nopaths)
|
||||||
|
+ r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove);
|
||||||
|
+ else
|
||||||
|
+ r = dm_flush_map(mpp->alias);
|
||||||
|
/*
|
||||||
|
* clear references to this map before flushing so we can ignore
|
||||||
|
* the spurious uevent we may generate with the dm_flush_map call below
|
||||||
|
*/
|
||||||
|
- if (dm_flush_map(mpp->alias)) {
|
||||||
|
+ if (r) {
|
||||||
|
/*
|
||||||
|
* May not really be an error -- if the map was already flushed
|
||||||
|
* from the device mapper by dmsetup(8) for instance.
|
||||||
|
*/
|
||||||
|
- condlog(0, "%s: can't flush", mpp->alias);
|
||||||
|
- return 1;
|
||||||
|
+ if (r == 1)
|
||||||
|
+ condlog(0, "%s: can't flush", mpp->alias);
|
||||||
|
+ else {
|
||||||
|
+ condlog(2, "%s: devmap deferred remove", mpp->alias);
|
||||||
|
+ mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS;
|
||||||
|
+ }
|
||||||
|
+ return r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dm_lib_release();
|
||||||
|
@@ -372,7 +383,7 @@ ev_remove_map (char * devname, char * al
|
||||||
|
mpp->alias, mpp->dmi->minor, minor);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
- return flush_map(mpp, vecs);
|
||||||
|
+ return flush_map(mpp, vecs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -628,7 +639,7 @@ ev_remove_path (struct path *pp, struct
|
||||||
|
mpp->flush_on_last_del = FLUSH_IN_PROGRESS;
|
||||||
|
dm_queue_if_no_path(mpp->alias, 0);
|
||||||
|
}
|
||||||
|
- if (!flush_map(mpp, vecs)) {
|
||||||
|
+ if (!flush_map(mpp, vecs, 1)) {
|
||||||
|
condlog(2, "%s: removed map after"
|
||||||
|
" removing all paths",
|
||||||
|
alias);
|
||||||
|
Index: multipath-tools-130222/libmultipath/structs_vec.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/structs_vec.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/structs_vec.c
|
||||||
|
@@ -392,6 +392,8 @@ __setup_multipath (struct vectors * vecs
|
||||||
|
set_no_path_retry(mpp);
|
||||||
|
select_pg_timeout(mpp);
|
||||||
|
select_flush_on_last_del(mpp);
|
||||||
|
+ if (VECTOR_SIZE(mpp->paths) != 0)
|
||||||
|
+ dm_cancel_deferred_remove(mpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -565,7 +567,6 @@ int update_multipath (struct vectors *ve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/multipath/multipath.conf.5
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/multipath/multipath.conf.5
|
||||||
|
+++ multipath-tools-130222/multipath/multipath.conf.5
|
||||||
|
@@ -420,6 +420,16 @@ only one checker will run at a time. Th
|
||||||
|
multipathd checkers running in parallel causes significant CPU pressure. The
|
||||||
|
Default is
|
||||||
|
.I no
|
||||||
|
+.TP
|
||||||
|
+.B deferred_remove
|
||||||
|
+If set to
|
||||||
|
+.I yes
|
||||||
|
+, multipathd will do a deferred remove instead of a regular remove when the
|
||||||
|
+last path device has been deleted. This means that if the multipath device is
|
||||||
|
+still in use, it will be freed when the last user closes it. If path is added
|
||||||
|
+to the multipath device before the last user closes it, the deferred remove
|
||||||
|
+will be canceled. Default is
|
||||||
|
+.I no
|
||||||
|
.
|
||||||
|
.SH "blacklist section"
|
||||||
|
The
|
||||||
|
@@ -521,6 +531,8 @@ section:
|
||||||
|
.B features
|
||||||
|
.TP
|
||||||
|
.B reservation_key
|
||||||
|
+.TP
|
||||||
|
+.B deferred_remove
|
||||||
|
.RE
|
||||||
|
.PD
|
||||||
|
.LP
|
||||||
|
@@ -611,6 +623,8 @@ section:
|
||||||
|
.B retain_attached_hw_handler
|
||||||
|
.TP
|
||||||
|
.B detect_prio
|
||||||
|
+.TP
|
||||||
|
+.B deferred_remove
|
||||||
|
.RE
|
||||||
|
.PD
|
||||||
|
.LP
|
||||||
|
Index: multipath-tools-130222/libmultipath/Makefile
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/Makefile
|
||||||
|
+++ multipath-tools-130222/libmultipath/Makefile
|
||||||
|
@@ -36,6 +36,12 @@ ifneq ($(strip $(LIBUDEV_API_RECVBUF)),0
|
||||||
|
CFLAGS += -DLIBUDEV_API_RECVBUF
|
||||||
|
endif
|
||||||
|
|
||||||
|
+LIBDM_API_DEFERRED = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_deferred_remove' /usr/include/libdevmapper.h)
|
||||||
|
+
|
||||||
|
+ifneq ($(strip $(LIBDM_API_DEFERRED)),0)
|
||||||
|
+ CFLAGS += -DLIBDM_API_DEFERRED
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
|
||||||
|
all: $(LIBS)
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
diff -purN multipath-tools-130222.orig/multipath/multipath.rules multipath-tools-130222/multipath/multipath.rules
|
||||||
|
--- multipath-tools-130222.orig/multipath/multipath.rules 2014-11-03 14:37:41.269413134 +0100
|
||||||
|
+++ multipath-tools-130222/multipath/multipath.rules 2014-11-03 14:38:43.694281901 +0100
|
||||||
|
@@ -45,5 +45,5 @@ ACTION!="change", GOTO="end_mpath"
|
||||||
|
ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath"
|
||||||
|
ENV{DM_SUSPENDED}=="1", GOTO="end_mpath"
|
||||||
|
ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath"
|
||||||
|
-RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode"
|
||||||
|
+ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode"
|
||||||
|
LABEL="end_mpath"
|
20
0106-RHBZ-1159337-fix-double-free.patch
Normal file
20
0106-RHBZ-1159337-fix-double-free.patch
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
multipathd/main.c | 5 ++---
|
||||||
|
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/multipathd/main.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/multipathd/main.c
|
||||||
|
+++ multipath-tools-130222/multipathd/main.c
|
||||||
|
@@ -669,9 +669,8 @@ ev_remove_path (struct path *pp, struct
|
||||||
|
/*
|
||||||
|
* update our state from kernel
|
||||||
|
*/
|
||||||
|
- if (setup_multipath(vecs, mpp)) {
|
||||||
|
- goto fail;
|
||||||
|
- }
|
||||||
|
+ if (setup_multipath(vecs, mpp))
|
||||||
|
+ return 1;
|
||||||
|
sync_map_state(mpp);
|
||||||
|
|
||||||
|
condlog(2, "%s [%s]: path removed from map %s",
|
117
0107-RHBZ-1169935-no-new-devs.patch
Normal file
117
0107-RHBZ-1169935-no-new-devs.patch
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
---
|
||||||
|
libmultipath/config.h | 1 +
|
||||||
|
libmultipath/configure.c | 4 ++--
|
||||||
|
libmultipath/wwids.c | 16 +++++++++-------
|
||||||
|
multipathd/main.c | 8 ++++++--
|
||||||
|
multipathd/multipathd.8 | 6 ++++++
|
||||||
|
5 files changed, 24 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/libmultipath/config.h
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/config.h
|
||||||
|
+++ multipath-tools-130222/libmultipath/config.h
|
||||||
|
@@ -131,6 +131,7 @@ struct config {
|
||||||
|
int detect_prio;
|
||||||
|
int force_sync;
|
||||||
|
int deferred_remove;
|
||||||
|
+ int no_new_devs;
|
||||||
|
unsigned int version[3];
|
||||||
|
|
||||||
|
char * dev;
|
||||||
|
Index: multipath-tools-130222/libmultipath/configure.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/configure.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/configure.c
|
||||||
|
@@ -776,8 +776,8 @@ coalesce_paths (struct vectors * vecs, v
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If find_multipaths was selected check if the path is valid */
|
||||||
|
- if (conf->find_multipaths && !refwwid &&
|
||||||
|
- !should_multipath(pp1, pathvec)) {
|
||||||
|
+ if ((conf->find_multipaths || conf->no_new_devs)
|
||||||
|
+ && !refwwid && !should_multipath(pp1, pathvec)) {
|
||||||
|
orphan_path(pp1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Index: multipath-tools-130222/libmultipath/wwids.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/libmultipath/wwids.c
|
||||||
|
+++ multipath-tools-130222/libmultipath/wwids.c
|
||||||
|
@@ -270,13 +270,15 @@ should_multipath(struct path *pp1, vecto
|
||||||
|
struct path *pp2;
|
||||||
|
|
||||||
|
condlog(4, "checking if %s should be multipathed", pp1->dev);
|
||||||
|
- vector_foreach_slot(pathvec, pp2, i) {
|
||||||
|
- if (pp1->dev == pp2->dev)
|
||||||
|
- continue;
|
||||||
|
- if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
|
||||||
|
- condlog(3, "found multiple paths with wwid %s, "
|
||||||
|
- "multipathing %s", pp1->wwid, pp1->dev);
|
||||||
|
- return 1;
|
||||||
|
+ if (!conf->no_new_devs) {
|
||||||
|
+ vector_foreach_slot(pathvec, pp2, i) {
|
||||||
|
+ if (pp1->dev == pp2->dev)
|
||||||
|
+ continue;
|
||||||
|
+ if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
|
||||||
|
+ condlog(3, "found multiple paths with wwid %s, "
|
||||||
|
+ "multipathing %s", pp1->wwid, pp1->dev);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (check_wwids_file(pp1->wwid, 0) < 0) {
|
||||||
|
Index: multipath-tools-130222/multipathd/main.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/multipathd/main.c
|
||||||
|
+++ multipath-tools-130222/multipathd/main.c
|
||||||
|
@@ -503,7 +503,7 @@ rescan:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (conf->find_multipaths &&
|
||||||
|
+ if ((conf->find_multipaths || conf->no_new_devs) &&
|
||||||
|
!should_multipath(pp, vecs->pathvec)) {
|
||||||
|
orphan_path(pp);
|
||||||
|
return 0;
|
||||||
|
@@ -1427,6 +1427,7 @@ reconfigure (struct vectors * vecs)
|
||||||
|
|
||||||
|
if (!load_config(DEFAULT_CONFIGFILE, udev)) {
|
||||||
|
conf->verbosity = old->verbosity;
|
||||||
|
+ conf->no_new_devs = old->no_new_devs;
|
||||||
|
conf->daemon = 1;
|
||||||
|
configure(vecs, 1);
|
||||||
|
free_config(old);
|
||||||
|
@@ -1880,12 +1881,15 @@ main (int argc, char *argv[])
|
||||||
|
if (!conf)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
- while ((arg = getopt(argc, argv, ":dv:k::")) != EOF ) {
|
||||||
|
+ while ((arg = getopt(argc, argv, ":dnv:k::")) != EOF ) {
|
||||||
|
switch(arg) {
|
||||||
|
case 'd':
|
||||||
|
logsink = 0;
|
||||||
|
//debug=1; /* ### comment me out ### */
|
||||||
|
break;
|
||||||
|
+ case 'n':
|
||||||
|
+ conf->no_new_devs = 1;
|
||||||
|
+ break;
|
||||||
|
case 'v':
|
||||||
|
if (sizeof(optarg) > sizeof(char *) ||
|
||||||
|
!isdigit(optarg[0]))
|
||||||
|
Index: multipath-tools-130222/multipathd/multipathd.8
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/multipathd/multipathd.8
|
||||||
|
+++ multipath-tools-130222/multipathd/multipathd.8
|
||||||
|
@@ -22,6 +22,12 @@ devmap reconfiguration, so that it can r
|
||||||
|
.B \-d
|
||||||
|
Forground Mode. Don't daemonize, and print all messages to stdout and stderr.
|
||||||
|
.TP
|
||||||
|
+.B -n
|
||||||
|
+No new devs mode. When multipathd is started in this mode, it will only
|
||||||
|
+create multipath devices if the device wwid is listed in /etc/multipath/wwids.
|
||||||
|
+This means multipathd will never create a device that hasn't never been
|
||||||
|
+created before.
|
||||||
|
+.TP
|
||||||
|
.B -v "level"
|
||||||
|
Verbosity level. Print additional information while running multipathd. A level of 0 means only print errors. A level of 3 or greater prints debugging information as well.
|
||||||
|
.TP
|
15
0108-RHBZ-1153832-kpartx-remove-devs.patch
Normal file
15
0108-RHBZ-1153832-kpartx-remove-devs.patch
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
multipath/multipath.rules | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/multipath/multipath.rules
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/multipath/multipath.rules
|
||||||
|
+++ multipath-tools-130222/multipath/multipath.rules
|
||||||
|
@@ -45,5 +45,5 @@ ACTION!="change", GOTO="end_mpath"
|
||||||
|
ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath"
|
||||||
|
ENV{DM_SUSPENDED}=="1", GOTO="end_mpath"
|
||||||
|
ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath"
|
||||||
|
-ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode"
|
||||||
|
+ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -u $tempnode"
|
||||||
|
LABEL="end_mpath"
|
27
0109-RH-read-only-bindings.patch
Normal file
27
0109-RH-read-only-bindings.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
multipathd/main.c | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Index: multipath-tools-130222/multipathd/main.c
|
||||||
|
===================================================================
|
||||||
|
--- multipath-tools-130222.orig/multipathd/main.c
|
||||||
|
+++ multipath-tools-130222/multipathd/main.c
|
||||||
|
@@ -1881,7 +1881,7 @@ main (int argc, char *argv[])
|
||||||
|
if (!conf)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
- while ((arg = getopt(argc, argv, ":dnv:k::")) != EOF ) {
|
||||||
|
+ while ((arg = getopt(argc, argv, ":dnv:k::B")) != EOF ) {
|
||||||
|
switch(arg) {
|
||||||
|
case 'd':
|
||||||
|
logsink = 0;
|
||||||
|
@@ -1900,6 +1900,9 @@ main (int argc, char *argv[])
|
||||||
|
case 'k':
|
||||||
|
uxclnt(optarg);
|
||||||
|
exit(0);
|
||||||
|
+ case 'B':
|
||||||
|
+ conf->bindings_read_only = 1;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
Summary: Tools to manage multipath devices using device-mapper
|
Summary: Tools to manage multipath devices using device-mapper
|
||||||
Name: device-mapper-multipath
|
Name: device-mapper-multipath
|
||||||
Version: 0.4.9
|
Version: 0.4.9
|
||||||
Release: 70%{?dist}
|
Release: 71%{?dist}
|
||||||
License: GPL+
|
License: GPL+
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
URL: http://christophe.varoqui.free.fr/
|
URL: http://christophe.varoqui.free.fr/
|
||||||
@ -110,6 +110,13 @@ Patch0099: 0099-RH-add-all-devs.patch
|
|||||||
Patch0100: 0100-RHBZ-1067171-multipath-i-update.patch
|
Patch0100: 0100-RHBZ-1067171-multipath-i-update.patch
|
||||||
Patch0101: 0101-RH-adapter-name-wildcard.patch
|
Patch0101: 0101-RH-adapter-name-wildcard.patch
|
||||||
Patch0102: 0102-RHBZ-1160478-mpathconf-template.patch
|
Patch0102: 0102-RHBZ-1160478-mpathconf-template.patch
|
||||||
|
Patch0103: 0103-RH-cleanup-partmaps-code.patch
|
||||||
|
Patch0104: 0104-RHBZ-631009-deferred-remove.patch
|
||||||
|
Patch0105: 0105-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch
|
||||||
|
Patch0106: 0106-RHBZ-1159337-fix-double-free.patch
|
||||||
|
Patch0107: 0107-RHBZ-1169935-no-new-devs.patch
|
||||||
|
Patch0108: 0108-RHBZ-1153832-kpartx-remove-devs.patch
|
||||||
|
Patch0109: 0109-RH-read-only-bindings.patch
|
||||||
|
|
||||||
# runtime
|
# runtime
|
||||||
Requires: %{name}-libs = %{version}-%{release}
|
Requires: %{name}-libs = %{version}-%{release}
|
||||||
@ -263,6 +270,13 @@ kpartx manages partition creation and removal for device-mapper devices.
|
|||||||
%patch0100 -p1
|
%patch0100 -p1
|
||||||
%patch0101 -p1
|
%patch0101 -p1
|
||||||
%patch0102 -p1
|
%patch0102 -p1
|
||||||
|
%patch0103 -p1
|
||||||
|
%patch0104 -p1
|
||||||
|
%patch0105 -p1
|
||||||
|
%patch0106 -p1
|
||||||
|
%patch0107 -p1
|
||||||
|
%patch0108 -p1
|
||||||
|
%patch0109 -p1
|
||||||
cp %{SOURCE1} .
|
cp %{SOURCE1} .
|
||||||
|
|
||||||
%build
|
%build
|
||||||
@ -361,6 +375,24 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||:
|
|||||||
%{_mandir}/man8/kpartx.8.gz
|
%{_mandir}/man8/kpartx.8.gz
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Dec 15 2014 Benjamin Marzinski <bmarzins@redhat.com> 0.4.9-71
|
||||||
|
- Add 0103-RH-cleanup-partmaps-code.patch
|
||||||
|
* code refactoring to prepare for next patch
|
||||||
|
- Add 0104-RHBZ-631009-deferred-remove.patch
|
||||||
|
* add deferred_remove option to /etc/multipath.conf
|
||||||
|
- Add 0105-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch
|
||||||
|
* Only run kpartx on device activation
|
||||||
|
- Add 0106-RHBZ-1159337-fix-double-free.patch
|
||||||
|
* made ev_remove_path exit immediately after failing setup_multipath, since
|
||||||
|
it handles cleaning up the device
|
||||||
|
- Add 0107-RHBZ-1169935-no-new-devs.patch
|
||||||
|
* Add new multipathd option '-n' which keeps multipathd from creating any
|
||||||
|
multipath devices that aren't in the /etc/multipath/wwids file.
|
||||||
|
- Add 0108-RHBZ-1153832-kpartx-remove-devs.patch
|
||||||
|
* switch from 'kpartx -a' to 'kpartx -u' to remove missing devices as well.
|
||||||
|
- Add 0109-RH-read-only-bindings.patch
|
||||||
|
* re-enabled -B option for multipathd
|
||||||
|
|
||||||
* Tue Dec 9 2014 Benjamin Marzinski <bmarzins@redhat.com> 0.4.9-70
|
* Tue Dec 9 2014 Benjamin Marzinski <bmarzins@redhat.com> 0.4.9-70
|
||||||
- Add 0102-RHBZ-1160478-mpathconf-template.patch
|
- Add 0102-RHBZ-1160478-mpathconf-template.patch
|
||||||
* mpathconf no longer copies the default config template for the
|
* mpathconf no longer copies the default config template for the
|
||||||
|
Loading…
Reference in New Issue
Block a user