* [PATCH 00/15] Multipath patch resync
@ 2015-03-08 3:31 Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 01/15] correctly set partition delimiter on rename Benjamin Marzinski
` (15 more replies)
0 siblings, 16 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
The first eight of these patches are resends of earlier patches, just
rebased with minor changes. The next two are minor changes, adding
multipath's -B option to mutipathd, and blacklisting vd.* devices.
The two after that allow multipath to read additional configuration
files in a configuration directory /etc/multipath/conf.d by default,
and then do some cleanup of the parser code that I noticed while
adding the configuration directories. The next patch adds two new
configuration parameters that allow multipathd to delay the
reintegration of paths that are failing repeatedly. The next one
fixes a hard to hit memory corruption bug, and the last one
updates the EMC builtin configuration to autodetect ALUA setups.
Benjamin Marzinski (15):
correctly set partition delimiter on rename
libmultipath: fix sysfs_get_size bug
Revert "libmultipath: fixup strlcpy"
libmultipath: refactor partmaps code
multipathd: fix memory corruption issue
multipathd: add deferred_remove support
multipathd: don't buffer output with systemd
libmutipath: allow blanks in device blacklist
multipathd: read-only bindings
multipath: blacklist virtio-blk devices
multipath: enable configuration directory
libmultipath: cleanup parser code
multipathd: Add delayed path reintegration
Fix doublee free of alias after map add failure
libmultipath: autodetect ALUA CLARiiON configurations
libmultipath/Makefile | 6 +
libmultipath/blacklist.c | 18 ++-
libmultipath/checkers.c | 1 +
libmultipath/checkers.h | 9 ++
libmultipath/config.c | 69 ++++++++++-
libmultipath/config.h | 12 ++
libmultipath/configure.c | 3 +
libmultipath/defaults.h | 3 +
libmultipath/devmapper.c | 284 +++++++++++++++++++++++++++++----------------
libmultipath/devmapper.h | 11 +-
libmultipath/dict.c | 126 +++++++++++++++++---
libmultipath/dict.h | 1 +
libmultipath/hwtable.c | 2 +
libmultipath/parser.c | 173 ++++++++-------------------
libmultipath/parser.h | 9 +-
libmultipath/print.c | 2 +
libmultipath/propsel.c | 58 +++++++++
libmultipath/propsel.h | 3 +
libmultipath/structs.h | 17 +++
libmultipath/structs_vec.c | 3 +-
libmultipath/sysfs.c | 2 +-
libmultipath/util.c | 3 +-
multipath.conf.annotated | 80 +++++++++++++
multipath.conf.defaults | 7 +-
multipath/multipath.conf.5 | 54 +++++++++
multipathd/main.c | 86 ++++++++++----
multipathd/multipathd.8 | 5 +
27 files changed, 761 insertions(+), 286 deletions(-)
--
1.8.3.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/15] correctly set partition delimiter on rename
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 02/15] libmultipath: fix sysfs_get_size bug Benjamin Marzinski
` (14 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
When multipath renames a device and the name switches from ending in a
number to ending in a letter or vice versa, it currently just keeps any
existing delimiter between the device name and partition number.
However the default behaviour in kpartx is to only use the 'p' delimiter
when the name ends in a number. Unfortunately, without adding a
kpartx.conf that kpartx uses to set the delimiter behavior, there's no
way for multipath to know how kpartx was run for certain device names
(ones ending in a number with a 'p' delimiter).
The patch adds a new multipath.conf defaults parameter,
"partition_delimiter". If this value is not set, when multipath renames
a device, it will act just like the kpartx default does, only adding a
'p' to names ending in a number. If this parameter is set, multipath
will act like kpartx does with the -p option is used, and always add
delimiter.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 3 +++
libmultipath/config.h | 1 +
libmultipath/devmapper.c | 14 ++++++++++++--
libmultipath/dict.c | 4 ++++
4 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 7f7bd5a..cbc8e4b 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -502,6 +502,8 @@ free_config (struct config * conf)
if (conf->alias_prefix)
FREE(conf->alias_prefix);
+ if (conf->partition_delim)
+ FREE(conf->partition_delim);
if (conf->prio_args)
FREE(conf->prio_args);
@@ -563,6 +565,7 @@ load_config (char * file, struct udev *udev)
conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
conf->detect_prio = DEFAULT_DETECT_PRIO;
conf->force_sync = 0;
+ conf->partition_delim = NULL;
/*
* preload default hwtable
diff --git a/libmultipath/config.h b/libmultipath/config.h
index ef1d7c3..b942a27 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -140,6 +140,7 @@ struct config {
char * prio_args;
char * checker_name;
char * alias_prefix;
+ char * partition_delim;
unsigned char * reservation_key;
vector keywords;
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 3d4c111..9e585f9 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1142,6 +1142,8 @@ dm_rename_partmaps (char * old, char * new)
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;
@@ -1162,6 +1164,13 @@ dm_rename_partmaps (char * old, char * new)
if (dm_dev_t(old, &dev_t[0], 32))
goto out;
+ if (conf->partition_delim)
+ delim = conf->partition_delim;
+ if (isdigit(new[strlen(new)-1]))
+ delim = "p";
+ else
+ delim = "";
+
do {
if (
/*
@@ -1189,8 +1198,9 @@ dm_rename_partmaps (char * old, char * new)
* then it's a kpartx generated partition.
* Rename it.
*/
- snprintf(buff, PARAMS_SIZE, "%s%s",
- new, names->name + strlen(old));
+ 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);
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 737c9b0..ab313f3 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -230,6 +230,9 @@ declare_def_snprint(reassign_maps, print_yes_no)
declare_def_handler(multipath_dir, set_str)
declare_def_snprint(multipath_dir, print_str)
+declare_def_handler(partition_delim, set_str)
+declare_def_snprint(partition_delim, print_str)
+
declare_def_handler(selector, set_str)
declare_def_snprint_defstr(selector, print_str, DEFAULT_SELECTOR)
declare_hw_handler(selector, set_str)
@@ -1242,6 +1245,7 @@ init_keywords(void)
install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler);
install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio);
install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
+ install_keyword("partition_delimiter", &def_partition_delim_handler, &snprint_def_partition_delim);
__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);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 02/15] libmultipath: fix sysfs_get_size bug
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 01/15] correctly set partition delimiter on rename Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 03/15] Revert "libmultipath: fixup strlcpy" Benjamin Marzinski
` (13 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
sysfs_get_size wasn't checking for a negative return value from
sysfs_attr_get_value.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/sysfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
index f42cda8..0e05316 100644
--- a/libmultipath/sysfs.c
+++ b/libmultipath/sysfs.c
@@ -158,7 +158,7 @@ sysfs_get_size (struct path *pp, unsigned long long * size)
return 1;
attr[0] = '\0';
- if (sysfs_attr_get_value(pp->udev, "size", attr, 255) == 0) {
+ if (sysfs_attr_get_value(pp->udev, "size", attr, 255) <= 0) {
condlog(3, "%s: No size attribute in sysfs", pp->dev);
return 1;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 03/15] Revert "libmultipath: fixup strlcpy"
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 01/15] correctly set partition delimiter on rename Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 02/15] libmultipath: fix sysfs_get_size bug Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 04/15] libmultipath: refactor partmaps code Benjamin Marzinski
` (12 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
This reverts commit 3a64d6491a1e83adcaf5f97edd18b7898dce241d.
strlcpy already had a check to make sure that as long as the size passed in
wasn't zero, it would leave enough space to write the final null. So, the
only check that was necessary was to see if strlcpy was called with
size = 0.
strlcpy returns the number of bytes that it took, or would take, to write
the entire string. There is no reason why bytes would usually end up
equalling size, so this commit caused strlcpy to stop null terminating many
strings.
Cc: "Hannes Reinecke <hare@suse.de>"
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/util.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libmultipath/util.c b/libmultipath/util.c
index b8487ac..ac0d1b2 100644
--- a/libmultipath/util.c
+++ b/libmultipath/util.c
@@ -112,7 +112,8 @@ size_t strlcpy(char *dst, const char *src, size_t size)
bytes++;
}
- if (bytes == size)
+ /* If size == 0 there is no space for a final null... */
+ if (size)
*q = '\0';
return bytes;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 04/15] libmultipath: refactor partmaps code
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (2 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 03/15] Revert "libmultipath: fixup strlcpy" Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 05/15] multipathd: fix memory corruption issue Benjamin Marzinski
` (11 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
There was a lot of code duplication between dm_remove_partmaps and
dm_rename_partmaps. This patch factors that out into
do_foreach_partmaps.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 156 +++++++++++++++++++----------------------------
1 file changed, 62 insertions(+), 94 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 9e585f9..cddb9de 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -998,8 +998,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;
@@ -1051,26 +1052,8 @@ dm_remove_partmaps (const char * mapname, int need_sync)
*/
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;
@@ -1083,6 +1066,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)
{
@@ -1132,88 +1144,44 @@ 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;
+ struct rename_data *rd = (struct rename_data *)data;
- if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
- return 1;
-
- dm_task_no_open_count(dmt);
-
- if (!dm_task_run(dmt))
- goto out;
-
- if (!(names = dm_task_get_names(dmt)))
- 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 (!names->dev) {
- r = 0; /* this is perfectly valid */
- goto out;
- }
+int
+dm_rename_partmaps (char * old, char * new)
+{
+ struct rename_data rd;
- if (dm_dev_t(old, &dev_t[0], 32))
- goto out;
+ rd.old = old;
+ rd.new = new;
if (conf->partition_delim)
- delim = conf->partition_delim;
+ rd.delim = conf->partition_delim;
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
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 05/15] multipathd: fix memory corruption issue
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (3 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 04/15] libmultipath: refactor partmaps code Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 06/15] multipathd: add deferred_remove support Benjamin Marzinski
` (10 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
setup_multipath already removes the mpp if it fails, so we shouldn't be
accessing the mpp at all if it fails, and especially not freeing it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 3afed62..a194c80 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -657,9 +657,8 @@ ev_remove_path (struct path *pp, struct vectors * vecs)
/*
* 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",
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 06/15] multipathd: add deferred_remove support
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (4 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 05/15] multipathd: fix memory corruption issue Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 07/15] multipathd: don't buffer output with systemd Benjamin Marzinski
` (9 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
This patch adds a new configuration option "deferrer_remove" If this is
set to "yes", when the last path of a multipath device is removed,
multipathd will do a deferred remove on it. This means that if the
device cannot immediately be removed, device mapper will automatically
remove it when the last user closes it. If a path is added to the
device before then, the deferred remove will be cancelled.
Without this enabled, multipath will continue to work like before, where
it will attempt a regular remove when the last path is removed. If
that fails because the device is in use, then the multipath device will
remain, even after the last user closes it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/Makefile | 6 ++
libmultipath/config.c | 2 +
libmultipath/config.h | 3 +
libmultipath/configure.c | 1 +
libmultipath/defaults.h | 1 +
libmultipath/devmapper.c | 142 ++++++++++++++++++++++++++++++++++++++++-----
libmultipath/devmapper.h | 11 ++--
libmultipath/dict.c | 13 +++++
libmultipath/propsel.c | 26 +++++++++
libmultipath/propsel.h | 1 +
libmultipath/structs.h | 8 +++
libmultipath/structs_vec.c | 3 +-
multipath/multipath.conf.5 | 16 +++++
multipathd/main.c | 23 ++++++--
14 files changed, 230 insertions(+), 26 deletions(-)
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index 4b4f707..fc0f3d6 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -46,6 +46,12 @@ ifdef SYSTEMD
CFLAGS += -DUSE_SYSTEMD=$(SYSTEMD)
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)
$(LIBS): $(OBJS)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index cbc8e4b..d4a5e10 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -340,6 +340,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
merge_num(user_friendly_names);
merge_num(retain_hwhandler);
merge_num(detect_prio);
+ merge_num(deferred_remove);
/*
* Make sure features is consistent with
@@ -412,6 +413,7 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
hwe->user_friendly_names = dhwe->user_friendly_names;
hwe->retain_hwhandler = dhwe->retain_hwhandler;
hwe->detect_prio = dhwe->detect_prio;
+ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE;
if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
goto out;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index b942a27..bc3fe53 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -59,6 +59,7 @@ struct hwentry {
int user_friendly_names;
int retain_hwhandler;
int detect_prio;
+ int deferred_remove;
char * bl_product;
};
@@ -82,6 +83,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;
@@ -124,6 +126,7 @@ struct config {
int retain_hwhandler;
int detect_prio;
int force_sync;
+ int deferred_remove;
unsigned int version[3];
char * dev;
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 1068a0a..a22d16a 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -289,6 +289,7 @@ setup_map (struct multipath * mpp, char * params, int params_size)
select_dev_loss(mpp);
select_reservation_key(mpp);
select_retain_hwhandler(mpp);
+ select_deferred_remove(mpp);
sysfs_set_scsi_tmo(mpp);
/*
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index 99cf4b1..ccf1ebe 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -16,6 +16,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)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index cddb9de..69491a3 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -32,6 +32,8 @@
#define UUID_PREFIX "mpath-"
#define UUID_PREFIX_LEN 6
+static int dm_cancel_remove_partmaps(const char * mapname);
+
#ifndef LIBDM_API_COOKIE
static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a)
{
@@ -105,7 +107,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};
@@ -203,8 +207,10 @@ dm_prereq (void)
return dm_drv_prereq();
}
+#define do_deferred(x) ((x) == DEFERRED_REMOVE_ON || (x) == DEFERRED_REMOVE_IN_PROGRESS)
+
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));
@@ -222,7 +228,10 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t
if (no_flush)
dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */
#endif
-
+#ifdef LIBDM_API_DEFERRED
+ if (do_deferred(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);
@@ -234,12 +243,18 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t
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);
+}
+
+static 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
@@ -655,7 +670,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;
@@ -665,23 +680,46 @@ _dm_flush_map (const char * mapname, int need_sync)
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 (!do_deferred(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 (do_deferred(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)
{
@@ -1068,6 +1106,7 @@ out:
struct remove_data {
int need_sync;
+ int deferred_remove;
};
static int
@@ -1076,25 +1115,98 @@ 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 (!do_deferred(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_get_opencount(name))
+ dm_cancel_remove_partmaps(name);
+ 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;
+}
+
+static int
+dm_cancel_remove_partmaps(const char * mapname) {
+ return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
+}
+
+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;
+
+ dm_cancel_remove_partmaps(mpp->alias);
+ 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)
{
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 6ea816c..5c8c50d 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -23,9 +23,11 @@ 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);
@@ -39,7 +41,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);
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index ab313f3..0f0ac05 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -374,6 +374,15 @@ declare_hw_snprint(detect_prio, print_yes_no_undef)
declare_def_handler(force_sync, set_yes_no)
declare_def_snprint(force_sync, print_yes_no)
+declare_def_handler(deferred_remove, set_yes_no_undef)
+declare_def_snprint_defint(deferred_remove, print_yes_no_undef, YNU_NO)
+declare_ovr_handler(deferred_remove, set_yes_no_undef)
+declare_ovr_snprint(deferred_remove, print_yes_no_undef)
+declare_hw_handler(deferred_remove, set_yes_no_undef)
+declare_hw_snprint(deferred_remove, print_yes_no_undef)
+declare_mp_handler(deferred_remove, set_yes_no_undef)
+declare_mp_snprint(deferred_remove, print_yes_no_undef)
+
#define declare_def_attr_handler(option, function) \
static int \
def_ ## option ## _handler (vector strvec) \
@@ -1245,6 +1254,7 @@ init_keywords(void)
install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler);
install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio);
install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
+ install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
install_keyword("partition_delimiter", &def_partition_delim_handler, &snprint_def_partition_delim);
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
@@ -1313,6 +1323,7 @@ init_keywords(void)
install_keyword("user_friendly_names", &hw_user_friendly_names_handler, &snprint_hw_user_friendly_names);
install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler);
install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_hw_detect_prio);
+ install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove);
install_sublevel_end();
install_keyword_root("overrides", &overrides_handler);
@@ -1337,6 +1348,7 @@ init_keywords(void)
install_keyword("user_friendly_names", &ovr_user_friendly_names_handler, &snprint_ovr_user_friendly_names);
install_keyword("retain_attached_hw_handler", &ovr_retain_hwhandler_handler, &snprint_ovr_retain_hwhandler);
install_keyword("detect_prio", &ovr_detect_prio_handler, &snprint_ovr_detect_prio);
+ install_keyword("deferred_remove", &ovr_deferred_remove_handler, &snprint_ovr_deferred_remove);
install_keyword_root("multipaths", &multipaths_handler);
install_keyword_multi("multipath", &multipath_handler, NULL);
@@ -1360,5 +1372,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_user_friendly_names_handler, &snprint_mp_user_friendly_names);
+ install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove);
install_sublevel_end();
}
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 440802c..f5c158b 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -590,3 +590,29 @@ out:
(pp->detect_prio == DETECT_PRIO_ON)? "yes" : "no", origin);
return 0;
}
+
+extern int
+select_deferred_remove (struct multipath *mp)
+{
+ char *origin;
+
+#ifndef LIBDM_API_DEFERRED
+ mp->deferred_remove = DEFERRED_REMOVE_OFF;
+ origin = "(not compiled with support)";
+ goto out;
+#endif
+ if (mp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) {
+ condlog(3, "%s: deferred remove in progress", mp->alias);
+ return 0;
+ }
+ mp_set_mpe(deferred_remove);
+ mp_set_ovr(deferred_remove);
+ mp_set_hwe(deferred_remove);
+ mp_set_conf(deferred_remove);
+ mp_set_default(deferred_remove, DEFAULT_DEFERRED_REMOVE);
+out:
+ condlog(3, "%s: deferred_remove = %s %s", mp->alias,
+ (mp->deferred_remove == DEFERRED_REMOVE_ON)? "yes" : "no",
+ origin);
+ return 0;
+}
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
index 05c6a4e..ffb58a5 100644
--- a/libmultipath/propsel.h
+++ b/libmultipath/propsel.h
@@ -19,3 +19,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);
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 15e7e19..b6cfff8 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -120,6 +120,13 @@ enum detect_prio_states {
DETECT_PRIO_ON = YNU_YES,
};
+enum deferred_remove_states {
+ DEFERRED_REMOVE_UNDEF = YNU_UNDEF,
+ DEFERRED_REMOVE_OFF = YNU_NO,
+ DEFERRED_REMOVE_ON = YNU_YES,
+ DEFERRED_REMOVE_IN_PROGRESS,
+};
+
enum scsi_protocol {
SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
@@ -213,6 +220,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;
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 23f5bbb..a15e3c0 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -392,6 +392,8 @@ __setup_multipath (struct vectors * vecs, struct multipath * mpp, int reset)
select_pgfailback(mpp);
set_no_path_retry(mpp);
select_flush_on_last_del(mpp);
+ if (VECTOR_SIZE(mpp->paths) != 0)
+ dm_cancel_deferred_remove(mpp);
}
return 0;
@@ -564,7 +566,6 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
}
}
}
-
return 0;
}
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index b823990..b9858a1 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -422,6 +422,16 @@ only one checker will run at a time. This is useful in the case where many
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
@@ -540,6 +550,8 @@ section:
.B features
.TP
.B reservation_key
+.TP
+.B deferred_remove
.RE
.PD
.LP
@@ -630,6 +642,8 @@ section:
.B retain_attached_hw_handler
.TP
.B detect_prio
+.TP
+.B deferred_remove
.RE
.PD
.LP
@@ -683,6 +697,8 @@ sections:
.B retain_attached_hw_handler
.TP
.B detect_prio
+.TP
+.B deferred_remove
.RE
.PD
.LP
diff --git a/multipathd/main.c b/multipathd/main.c
index a194c80..f9e3f33 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -218,19 +218,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();
@@ -376,7 +387,7 @@ ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs)
mpp->alias, mpp->dmi->minor, minor);
return 0;
}
- return flush_map(mpp, vecs);
+ return flush_map(mpp, vecs, 0);
}
static int
@@ -627,7 +638,7 @@ ev_remove_path (struct path *pp, struct vectors * vecs)
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);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 07/15] multipathd: don't buffer output with systemd
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (5 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 06/15] multipathd: add deferred_remove support Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 08/15] libmutipath: allow blanks in device blacklist Benjamin Marzinski
` (8 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
When stdout isn't hooked up to a tty (like it isn't when you start
multipathd through systemd) the stream is buffered, so messages only
come out in big chunks, or when the program quits. Instead, we should
send the messages out to systemd as we generate them, so that users
know what's happening, and in the event of a crash, they get the most
recent messages.
I realize that there is a performance impact to this. If people are
against this approach, we could change condlog to print messages above a
certain priority to stderr and messages below that priority to stdout.
If we included a configuration option to change the priority level, then
we could always change it up if we needed to do debugging. However, the
standard level messages are very helpful in quickly diagnosing a number
of problems, so you could make a good argument that we always want
priority 2 messages printed immediately. And if we intentionally bumped
up the debugging level, we would usually want those messages printed
immediately. This is exactly what we get with just unbuffering stdout.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index f9e3f33..bc21d04 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2011,9 +2011,11 @@ main (int argc, char *argv[])
exit(0);
}
- if (logsink < 1)
+ if (logsink < 1) {
+ if (!isatty(fileno(stdout)))
+ setbuf(stdout, NULL);
err = 0;
- else
+ } else
err = daemonize();
if (err < 0)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 08/15] libmutipath: allow blanks in device blacklist
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (6 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 07/15] multipathd: don't buffer output with systemd Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 09/15] multipathd: read-only bindings Benjamin Marzinski
` (7 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
As Brian De Wolf noticed, multipath crashes if you don't have both
vendor and product specified in a device blacklist entry. This patch
makes device blacklists work when either the vendor or the product is
blank. If both are missing, the entry is ignored.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 3f9e80b..05f1697 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -135,8 +135,12 @@ _blacklist_exceptions_device(vector elist, char * vendor, char * product)
struct blentry_device * ble;
vector_foreach_slot (elist, ble, i) {
- if (!regexec(&ble->vendor_reg, vendor, 0, NULL, 0) &&
- !regexec(&ble->product_reg, product, 0, NULL, 0))
+ if (!ble->vendor && !ble->product)
+ continue;
+ if ((!ble->vendor ||
+ !regexec(&ble->vendor_reg, vendor, 0, NULL, 0)) &&
+ (!ble->product ||
+ !regexec(&ble->product_reg, product, 0, NULL, 0)))
return 1;
}
return 0;
@@ -149,8 +153,12 @@ _blacklist_device (vector blist, char * vendor, char * product)
struct blentry_device * ble;
vector_foreach_slot (blist, ble, i) {
- if (!regexec(&ble->vendor_reg, vendor, 0, NULL, 0) &&
- !regexec(&ble->product_reg, product, 0, NULL, 0))
+ if (!ble->vendor && !ble->product)
+ continue;
+ if ((!ble->vendor ||
+ !regexec(&ble->vendor_reg, vendor, 0, NULL, 0)) &&
+ (!ble->product ||
+ !regexec(&ble->product_reg, product, 0, NULL, 0)))
return 1;
}
return 0;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 09/15] multipathd: read-only bindings
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (7 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 08/15] libmutipath: allow blanks in device blacklist Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 10/15] multipath: blacklist virtio-blk devices Benjamin Marzinski
` (6 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
Multipath already uses -B to run in a mode where it won't write the the
bindings file (which can be useful in the initramfs). Its simple to make
multipathd able to work this way as well.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 5 ++++-
multipathd/multipathd.8 | 5 +++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index bc21d04..7429f66 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1971,7 +1971,7 @@ main (int argc, char *argv[])
if (!conf)
exit(1);
- while ((arg = getopt(argc, argv, ":dsv:k::")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":dsv:k::B")) != EOF ) {
switch(arg) {
case 'd':
logsink = 0;
@@ -1990,6 +1990,9 @@ main (int argc, char *argv[])
case 'k':
uxclnt(optarg);
exit(0);
+ case 'B':
+ conf->bindings_read_only = 1;
+ break;
default:
;
}
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 358141d..7fe6597 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -28,6 +28,11 @@ Suppress timestamps. Do not prefix logging messages with a timestamp.
.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
+.B -B
+Read-only bindings file. Multipathd will not write to the user_friendly_names
+bindings file. If a user_friendly_name doesn't already exist for a device, it
+will use its WWID as its alias.
+.TP
.B -k
multipathd will enter interactive mode. From this mode, the available commands can be viewed by entering "help". When you are finished entering commands, press CTRL-D to quit.
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 10/15] multipath: blacklist virtio-blk devices
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (8 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 09/15] multipathd: read-only bindings Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 11/15] multipath: enable configuration directory Benjamin Marzinski
` (5 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
virtio-blk devices don't report anything to use as a WWID, so
multipath shouldn't waste it's time checking them.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 2 +-
multipath.conf.defaults | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 05f1697..cea128c 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -178,7 +178,7 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
return 1;
- str = STRDUP("^(td|hd)[a-z]");
+ str = STRDUP("^(td|hd|vd)[a-z]");
if (!str)
return 1;
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
diff --git a/multipath.conf.defaults b/multipath.conf.defaults
index cf8cfdb..5e46fd8 100644
--- a/multipath.conf.defaults
+++ b/multipath.conf.defaults
@@ -29,7 +29,7 @@
#}
#blacklist {
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
-# devnode "^hd[a-z]"
+# devnode "^(td|hd|vd)[a-z]"
# devnode "^dcssblk[0-9]*"
# devnode "^nvme.*"
# device {
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 11/15] multipath: enable configuration directory
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (9 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 10/15] multipath: blacklist virtio-blk devices Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 22:27 ` Sebastian Herbszt
2015-03-08 3:31 ` [PATCH 12/15] libmultipath: cleanup parser code Benjamin Marzinski
` (4 subsequent siblings)
15 siblings, 1 reply; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
Users who setup multipath on many machines sometimes want a core
configuration file that stays the same on all machines, and also secondary
configuration files that are unique to each machine to set blacklists and
aliases. This patch enables this by adding a new configuration option,
"config_dir", which defaults to "/etc/multipath/conf.d". If this is set,
multipath will check this directory for files ending in .conf, and apply
them on top of the initial configuration file in alphabetical order.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 62 +++++++++++++++++++++++++++++++++---
libmultipath/config.h | 2 ++
libmultipath/defaults.h | 1 +
libmultipath/dict.c | 49 ++++++++++++++++++++---------
libmultipath/parser.c | 78 ++++++++++++++++++++++++----------------------
libmultipath/parser.h | 3 +-
multipath.conf.annotated | 10 ++++++
multipath.conf.defaults | 1 +
multipath/multipath.conf.5 | 7 +++++
9 files changed, 155 insertions(+), 58 deletions(-)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index d4a5e10..c36e9db 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -6,6 +6,9 @@
#include <stdio.h>
#include <string.h>
#include <libudev.h>
+#include <dirent.h>
+#include <limits.h>
+#include <errno.h>
#include "checkers.h"
#include "memory.h"
@@ -499,6 +502,7 @@ free_config (struct config * conf)
if (conf->wwids_file)
FREE(conf->wwids_file);
+
if (conf->prio_name)
FREE(conf->prio_name);
@@ -512,6 +516,10 @@ free_config (struct config * conf)
if (conf->checker_name)
FREE(conf->checker_name);
+
+ if (conf->config_dir)
+ FREE(conf->config_dir);
+
if (conf->reservation_key)
FREE(conf->reservation_key);
@@ -532,6 +540,43 @@ free_config (struct config * conf)
FREE(conf);
}
+/* if multipath fails to process the config directory, it should continue,
+ * with just a warning message */
+static void
+process_config_dir(vector keywords, char *dir)
+{
+ struct dirent **namelist;
+ int i, n;
+ char path[LINE_MAX];
+ int old_hwtable_size;
+
+ if (dir[0] != '/') {
+ condlog(1, "config_dir '%s' must be a fully qualified path",
+ dir);
+ return;
+ }
+ n = scandir(dir, &namelist, NULL, alphasort);
+ if (n < 0) {
+ if (errno == ENOENT)
+ condlog(3, "No configuration dir '%s'", dir);
+ else
+ condlog(0, "couldn't open configuration dir '%s': %s",
+ dir, strerror(errno));
+ return;
+ }
+ for (i = 0; i < n; i++) {
+ if (!strstr(namelist[i]->d_name, ".conf"))
+ continue;
+ old_hwtable_size = VECTOR_SIZE(conf->hwtable);
+ snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name);
+ path[LINE_MAX-1] = '\0';
+ process_file(path);
+ if (VECTOR_SIZE(conf->hwtable) > old_hwtable_size)
+ factorize_hwtable(conf->hwtable, old_hwtable_size);
+
+ }
+}
+
int
load_config (char * file, struct udev *udev)
{
@@ -568,6 +613,7 @@ load_config (char * file, struct udev *udev)
conf->detect_prio = DEFAULT_DETECT_PRIO;
conf->force_sync = 0;
conf->partition_delim = NULL;
+ conf->processed_main_config = 0;
/*
* preload default hwtable
@@ -586,11 +632,12 @@ load_config (char * file, struct udev *udev)
*/
set_current_keywords(&conf->keywords);
alloc_keywords();
+ init_keywords();
if (filepresent(file)) {
int builtin_hwtable_size;
builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
- if (init_data(file, init_keywords)) {
+ if (process_file(file)) {
condlog(0, "error parsing config file");
goto out;
}
@@ -602,14 +649,19 @@ load_config (char * file, struct udev *udev)
factorize_hwtable(conf->hwtable, builtin_hwtable_size);
}
- } else {
- init_keywords();
}
- if (conf->max_checkint == 0)
- conf->max_checkint = MAX_CHECKINT(conf->checkint);
+
+ conf->processed_main_config = 1;
+ if (conf->config_dir == NULL)
+ conf->config_dir = set_default(DEFAULT_CONFIG_DIR);
+ if (conf->config_dir && conf->config_dir[0] != '\0')
+ process_config_dir(conf->keywords, conf->config_dir);
+
/*
* fill the voids left in the config file
*/
+ if (conf->max_checkint == 0)
+ conf->max_checkint = MAX_CHECKINT(conf->checkint);
if (conf->blist_devnode == NULL) {
conf->blist_devnode = vector_alloc();
diff --git a/libmultipath/config.h b/libmultipath/config.h
index bc3fe53..cb3be62 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -127,6 +127,7 @@ struct config {
int detect_prio;
int force_sync;
int deferred_remove;
+ int processed_main_config;
unsigned int version[3];
char * dev;
@@ -144,6 +145,7 @@ struct config {
char * checker_name;
char * alias_prefix;
char * partition_delim;
+ char * config_dir;
unsigned char * reservation_key;
vector keywords;
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index ccf1ebe..a7f1c11 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -27,5 +27,6 @@
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
+#define DEFAULT_CONFIG_DIR "/etc/multipath/conf.d"
char * set_default (char * str);
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 0f0ac05..7350231 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -38,6 +38,9 @@ static int
set_str(vector strvec, void *ptr)
{
char **str_ptr = (char **)ptr;
+
+ if (*str_ptr)
+ FREE(*str_ptr);
*str_ptr = set_value(strvec);
if (!*str_ptr)
@@ -383,6 +386,16 @@ declare_hw_snprint(deferred_remove, print_yes_no_undef)
declare_mp_handler(deferred_remove, set_yes_no_undef)
declare_mp_snprint(deferred_remove, print_yes_no_undef)
+static int
+def_config_dir_handler(vector strvec)
+{
+ /* this is only valid in the main config file */
+ if (conf->processed_main_config)
+ return 0;
+ return set_str(strvec, &conf->config_dir);
+}
+declare_def_snprint(config_dir, print_str)
+
#define declare_def_attr_handler(option, function) \
static int \
def_ ## option ## _handler (vector strvec) \
@@ -972,10 +985,14 @@ declare_mp_snprint(reservation_key, print_reservation_key)
static int
blacklist_handler(vector strvec)
{
- conf->blist_devnode = vector_alloc();
- conf->blist_wwid = vector_alloc();
- conf->blist_device = vector_alloc();
- conf->blist_property = vector_alloc();
+ if (!conf->blist_devnode)
+ conf->blist_devnode = vector_alloc();
+ if (!conf->blist_wwid)
+ conf->blist_wwid = vector_alloc();
+ if (!conf->blist_device)
+ conf->blist_device = vector_alloc();
+ if (!conf->blist_property)
+ conf->blist_property = vector_alloc();
if (!conf->blist_devnode || !conf->blist_wwid ||
!conf->blist_device || !conf->blist_property)
@@ -987,10 +1004,14 @@ blacklist_handler(vector strvec)
static int
blacklist_exceptions_handler(vector strvec)
{
- conf->elist_devnode = vector_alloc();
- conf->elist_wwid = vector_alloc();
- conf->elist_device = vector_alloc();
- conf->elist_property = vector_alloc();
+ if (!conf->elist_devnode)
+ conf->elist_devnode = vector_alloc();
+ if (!conf->elist_wwid)
+ conf->elist_wwid = vector_alloc();
+ if (!conf->elist_device)
+ conf->elist_device = vector_alloc();
+ if (!conf->elist_property)
+ conf->elist_property = vector_alloc();
if (!conf->elist_devnode || !conf->elist_wwid ||
!conf->elist_device || !conf->elist_property)
@@ -1134,14 +1155,12 @@ declare_hw_snprint(hwhandler, print_str)
static int
overrides_handler(vector strvec)
{
- struct hwentry * overrides;
+ if (!conf->overrides)
+ conf->overrides = alloc_hwe();
- overrides = alloc_hwe();
-
- if (!overrides)
+ if (!conf->overrides)
return 1;
- conf->overrides = overrides;
return 0;
}
@@ -1153,7 +1172,8 @@ overrides_handler(vector strvec)
static int
multipaths_handler(vector strvec)
{
- conf->mptable = vector_alloc();
+ if (!conf->mptable)
+ conf->mptable = vector_alloc();
if (!conf->mptable)
return 1;
@@ -1256,6 +1276,7 @@ init_keywords(void)
install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
install_keyword("partition_delimiter", &def_partition_delim_handler, &snprint_def_partition_delim);
+ install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir);
__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);
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index 00cbef8..d351ab2 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -18,6 +18,7 @@
*/
#include <syslog.h>
+#include <errno.h>
#include "parser.h"
#include "memory.h"
@@ -445,14 +446,15 @@ set_value(vector strvec)
/* non-recursive configuration stream handler */
static int kw_level = 0;
-int warn_on_duplicates(vector uniques, char *str)
+int warn_on_duplicates(vector uniques, char *str, char *file)
{
char *tmp;
int i;
vector_foreach_slot(uniques, tmp, i) {
if (!strcmp(str, tmp)) {
- condlog(1, "multipath.conf line %d, duplicate keyword: %s", line_nr, str);
+ condlog(1, "%s line %d, duplicate keyword: %s",
+ file, line_nr, str);
return 0;
}
}
@@ -488,65 +490,70 @@ is_sublevel_keyword(char *str)
}
int
-validate_config_strvec(vector strvec)
+validate_config_strvec(vector strvec, char *file)
{
char *str;
int i;
str = VECTOR_SLOT(strvec, 0);
if (str == NULL) {
- condlog(0, "can't parse option on line %d of config file",
- line_nr);
+ condlog(0, "can't parse option on line %d of %s",
+ line_nr, file);
return -1;
}
if (*str == '}') {
if (VECTOR_SIZE(strvec) > 1)
- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr);
+ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 1), line_nr, file);
return 0;
}
if (*str == '{') {
- condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr);
+ condlog(0, "invalid keyword '%s' on line %d of %s",
+ str, line_nr, file);
return -1;
}
if (is_sublevel_keyword(str)) {
str = VECTOR_SLOT(strvec, 1);
if (str == NULL)
- condlog(0, "missing '{' on line %d of config file", line_nr);
+ condlog(0, "missing '{' on line %d of %s",
+ line_nr, file);
else if (*str != '{')
- condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str);
+ condlog(0, "expecting '{' on line %d of %s. found '%s'",
+ line_nr, file, str);
else if (VECTOR_SIZE(strvec) > 2)
- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
+ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file);
return 0;
}
str = VECTOR_SLOT(strvec, 1);
if (str == NULL) {
- condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr);
+ condlog(0, "missing value for option '%s' on line %d of %s",
+ (char *)VECTOR_SLOT(strvec, 0), line_nr, file);
return -1;
}
if (*str != '"') {
if (VECTOR_SIZE(strvec) > 2)
- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
+ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file);
return 0;
}
for (i = 2; i < VECTOR_SIZE(strvec); i++) {
str = VECTOR_SLOT(strvec, i);
if (str == NULL) {
- condlog(0, "can't parse value on line %d of config file", line_nr);
+ condlog(0, "can't parse value on line %d of %s",
+ line_nr, file);
return -1;
}
if (*str == '"') {
if (VECTOR_SIZE(strvec) > i + 1)
- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr);
+ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr, file);
return 0;
}
}
- condlog(0, "missing closing quotes on line %d of config file",
- line_nr);
+ condlog(0, "missing closing quotes on line %d of %s",
+ line_nr, file);
return 0;
}
-int
-process_stream(vector keywords)
+static int
+process_stream(vector keywords, char *file)
{
int i;
int r = 0, t;
@@ -573,7 +580,7 @@ process_stream(vector keywords)
if (!strvec)
continue;
- if (validate_config_strvec(strvec) != 0) {
+ if (validate_config_strvec(strvec, file) != 0) {
free_strvec(strvec);
continue;
}
@@ -585,8 +592,8 @@ process_stream(vector keywords)
free_strvec(strvec);
break;
}
- condlog(0, "unmatched '%s' at line %d of config file",
- EOB, line_nr);
+ condlog(0, "unmatched '%s' at line %d of %s",
+ EOB, line_nr, file);
}
for (i = 0; i < VECTOR_SIZE(keywords); i++) {
@@ -594,7 +601,7 @@ process_stream(vector keywords)
if (!strcmp(keyword->string, str)) {
if (keyword->unique &&
- warn_on_duplicates(uniques, str)) {
+ warn_on_duplicates(uniques, str, file)) {
r = 1;
free_strvec(strvec);
goto out;
@@ -609,15 +616,15 @@ process_stream(vector keywords)
if (keyword->sub) {
kw_level++;
- r += process_stream(keyword->sub);
+ r += process_stream(keyword->sub, file);
kw_level--;
}
break;
}
}
if (i >= VECTOR_SIZE(keywords))
- condlog(1, "multipath.conf +%d, invalid keyword: %s",
- line_nr, str);
+ condlog(1, "%s line %d, invalid keyword: %s",
+ file, line_nr, str);
free_strvec(strvec);
}
@@ -641,27 +648,24 @@ int alloc_keywords(void)
/* Data initialization */
int
-init_data(char *conf_file, void (*init_keywords) (void))
+process_file(char *file)
{
int r;
- stream = fopen(conf_file, "r");
+ if (!keywords) {
+ condlog(0, "No keywords alocated");
+ return 1;
+ }
+ stream = fopen(file, "r");
if (!stream) {
- syslog(LOG_WARNING, "Configuration file open problem");
+ condlog(0, "couldn't open configuration file '%s': %s",
+ file, strerror(errno));
return 1;
}
- /* Init Keywords structure */
- (*init_keywords) ();
-
-/* Dump configuration *
- vector_dump(keywords);
- dump_keywords(keywords, 0);
-*/
-
/* Stream handling */
line_nr = 0;
- r = process_stream(keywords);
+ r = process_stream(keywords, file);
fclose(stream);
//free_keywords(keywords);
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
index 8bf1c76..bfbb3ae 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -76,9 +76,8 @@ extern int read_line(char *buf, int size);
extern vector read_value_block(void);
extern int alloc_value_block(vector strvec, void (*alloc_func) (vector));
extern void *set_value(vector strvec);
-extern int process_stream(vector keywords);
extern int alloc_keywords(void);
-extern int init_data(char *conf_file, void (*init_keywords) (void));
+extern int process_file(char *conf_file);
extern struct keyword * find_keyword(vector v, char * name);
void set_current_keywords (vector *k);
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
diff --git a/multipath.conf.annotated b/multipath.conf.annotated
index 71afc0a..2b148ac 100644
--- a/multipath.conf.annotated
+++ b/multipath.conf.annotated
@@ -304,6 +304,16 @@
# # values : yes|no
# # default : no
# force_sync yes
+#
+# #
+# # name : config_dir
+# # scope : multipath & multipathd
+# # desc : If not set to an empty string, multipath will search
+# # this directory alphabetically for files ending in ".conf"
+# # and it will read configuration information from these
+# # files, just as if it was in /etc/multipath.conf
+# # values : "" or a fully qualified pathname
+# # default : "/etc/multipath/conf.d"
#}
#
##
diff --git a/multipath.conf.defaults b/multipath.conf.defaults
index 5e46fd8..9244f71 100644
--- a/multipath.conf.defaults
+++ b/multipath.conf.defaults
@@ -26,6 +26,7 @@
# log_checker_err always
# retain_attached_hw_handler no
# detect_prio no
+# config_dir "/etc/multipath/conf.d"
#}
#blacklist {
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index b9858a1..4eb238d 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -432,6 +432,13 @@ 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
+.TP
+.B config_dir
+If set to anything other than "", multipath will search this directory
+alphabetically for file ending in ".conf" and it will read configuration
+information from them, just as if it was in /etc/multipath.conf. config_dir
+must either be "" or a fully qualified directory name. Default is
+.I "/etc/multipath/conf.d"
.
.SH "blacklist section"
The
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 12/15] libmultipath: cleanup parser code
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (10 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 11/15] multipath: enable configuration directory Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 13/15] multipathd: Add delayed path reintegration Benjamin Marzinski
` (3 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
read_value_block() and alloc_value_block() are completely unused, and can
go away. Also, all of the config file parsing is done it parse.c, so
there's no reason to make "stream" a global variable.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/parser.c | 101 ++++----------------------------------------------
libmultipath/parser.h | 6 ---
2 files changed, 8 insertions(+), 99 deletions(-)
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index d351ab2..e4296ee 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -280,8 +280,8 @@ out:
return NULL;
}
-int
-read_line(char *buf, int size)
+static int
+read_line(FILE *stream, char *buf, int size)
{
char *p;
@@ -291,93 +291,6 @@ read_line(char *buf, int size)
return 1;
}
-vector
-read_value_block(void)
-{
- char *buf;
- int i;
- char *str = NULL;
- char *dup;
- vector vec = NULL;
- vector elements = vector_alloc();
-
- if (!elements)
- return NULL;
-
- buf = (char *) MALLOC(MAXBUF);
-
- if (!buf) {
- vector_free(elements);
- return NULL;
- }
-
- while (read_line(buf, MAXBUF)) {
- vec = alloc_strvec(buf);
- if (vec) {
- str = VECTOR_SLOT(vec, 0);
- if (!strcmp(str, EOB)) {
- free_strvec(vec);
- break;
- }
-
- for (i = 0; i < VECTOR_SIZE(vec); i++) {
- str = VECTOR_SLOT(vec, i);
- dup = (char *) MALLOC(strlen(str) + 1);
- if (!dup)
- goto out;
- memcpy(dup, str, strlen(str));
-
- if (!vector_alloc_slot(elements)) {
- free_strvec(vec);
- goto out1;
- }
-
- vector_set_slot(elements, dup);
- }
- free_strvec(vec);
- }
- }
- FREE(buf);
- return elements;
-out1:
- FREE(dup);
-out:
- FREE(buf);
- vector_free(elements);
- return NULL;
-}
-
-int
-alloc_value_block(vector strvec, void (*alloc_func) (vector))
-{
- char *buf;
- char *str = NULL;
- vector vec = NULL;
-
- buf = (char *) MALLOC(MAXBUF);
-
- if (!buf)
- return 1;
-
- while (read_line(buf, MAXBUF)) {
- vec = alloc_strvec(buf);
- if (vec) {
- str = VECTOR_SLOT(vec, 0);
- if (!strcmp(str, EOB)) {
- free_strvec(vec);
- break;
- }
-
- if (VECTOR_SIZE(vec))
- (*alloc_func) (vec);
-
- free_strvec(vec);
- }
- }
- FREE(buf);
- return 0;
-}
-
void *
set_value(vector strvec)
{
@@ -553,7 +466,7 @@ validate_config_strvec(vector strvec, char *file)
}
static int
-process_stream(vector keywords, char *file)
+process_stream(FILE *stream, vector keywords, char *file)
{
int i;
int r = 0, t;
@@ -574,7 +487,7 @@ process_stream(vector keywords, char *file)
return 1;
}
- while (read_line(buf, MAXBUF)) {
+ while (read_line(stream, buf, MAXBUF)) {
line_nr++;
strvec = alloc_strvec(buf);
if (!strvec)
@@ -616,7 +529,8 @@ process_stream(vector keywords, char *file)
if (keyword->sub) {
kw_level++;
- r += process_stream(keyword->sub, file);
+ r += process_stream(stream,
+ keyword->sub, file);
kw_level--;
}
break;
@@ -651,6 +565,7 @@ int
process_file(char *file)
{
int r;
+ FILE *stream;
if (!keywords) {
condlog(0, "No keywords alocated");
@@ -665,7 +580,7 @@ process_file(char *file)
/* Stream handling */
line_nr = 0;
- r = process_stream(keywords, file);
+ r = process_stream(stream, keywords, file);
fclose(stream);
//free_keywords(keywords);
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
index bfbb3ae..ba6859e 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -47,9 +47,6 @@ struct keyword {
int unique;
};
-/* global var exported */
-FILE *stream;
-
/* Reloading helpers */
#define SET_RELOAD (reload = 1)
#define UNSET_RELOAD (reload = 0)
@@ -72,9 +69,6 @@ extern int _install_keyword(char *string, int (*handler) (vector),
extern void dump_keywords(vector keydump, int level);
extern void free_keywords(vector keywords);
extern vector alloc_strvec(char *string);
-extern int read_line(char *buf, int size);
-extern vector read_value_block(void);
-extern int alloc_value_block(vector strvec, void (*alloc_func) (vector));
extern void *set_value(vector strvec);
extern int alloc_keywords(void);
extern int process_file(char *conf_file);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 13/15] multipathd: Add delayed path reintegration
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (11 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 12/15] libmultipath: cleanup parser code Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 14/15] Fix doublee free of alias after map add failure Benjamin Marzinski
` (2 subsequent siblings)
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
This patch adds two configuration parameters, "delay_watch_checks" and
"delay_wait_checks". delay_watch_checks sets the number of checks that
a path will be watched for, after coming back from a failure. If the
path fails again within this number of checks, when it comes back up
the next time, it will not be used until it has remained up for
delay_wait_checks checks, assuming that there are other paths to the
device. If it is the only available path, it will immediately be
reintegrated.
This helps setups were a path either won't stay up, or takes some time
to stabilize before it should be used.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/checkers.c | 1 +
libmultipath/checkers.h | 9 ++++++
libmultipath/config.c | 2 ++
libmultipath/config.h | 6 ++++
libmultipath/configure.c | 2 ++
libmultipath/defaults.h | 1 +
libmultipath/dict.c | 60 +++++++++++++++++++++++++++++++++++++++
libmultipath/dict.h | 1 +
libmultipath/print.c | 2 ++
libmultipath/propsel.c | 32 +++++++++++++++++++++
libmultipath/propsel.h | 2 ++
libmultipath/structs.h | 9 ++++++
multipath.conf.annotated | 70 ++++++++++++++++++++++++++++++++++++++++++++++
multipath.conf.defaults | 2 ++
multipath/multipath.conf.5 | 31 ++++++++++++++++++++
multipathd/main.c | 34 ++++++++++++++++++----
16 files changed, 258 insertions(+), 6 deletions(-)
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index 4a4cd7c..1dd5525 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -19,6 +19,7 @@ char *checker_state_names[] = {
"pending",
"timeout",
"removed",
+ "delayed",
};
static LIST_HEAD(checkers);
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index e62b52f..a935b3f 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -54,6 +54,14 @@
* PATH REMOVED:
* - Use: All checkers
* - Description: Device has been removed from the system
+ *
+ * PATH_DELAYED:
+ * - Use: None of the checkers (returned if the path is being delayed before
+ * reintegration.
+ * - Description: If a path fails after being up for less than
+ * delay_watch_checks checks, when it comes back up again, it will not
+ * be marked as up until it has been up for delay_wait_checks checks.
+ * During this time, it is marked as "delayed"
*/
enum path_check_state {
PATH_WILD,
@@ -65,6 +73,7 @@ enum path_check_state {
PATH_PENDING,
PATH_TIMEOUT,
PATH_REMOVED,
+ PATH_DELAYED,
PATH_MAX_STATE
};
diff --git a/libmultipath/config.c b/libmultipath/config.c
index c36e9db..e88bae0 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -344,6 +344,8 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
merge_num(retain_hwhandler);
merge_num(detect_prio);
merge_num(deferred_remove);
+ merge_num(delay_watch_checks);
+ merge_num(delay_wait_checks);
/*
* Make sure features is consistent with
diff --git a/libmultipath/config.h b/libmultipath/config.h
index cb3be62..9b1d9a1 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -60,6 +60,8 @@ struct hwentry {
int retain_hwhandler;
int detect_prio;
int deferred_remove;
+ int delay_watch_checks;
+ int delay_wait_checks;
char * bl_product;
};
@@ -84,6 +86,8 @@ struct mpentry {
int attribute_flags;
int user_friendly_names;
int deferred_remove;
+ int delay_watch_checks;
+ int delay_wait_checks;
uid_t uid;
gid_t gid;
mode_t mode;
@@ -128,6 +132,8 @@ struct config {
int force_sync;
int deferred_remove;
int processed_main_config;
+ int delay_watch_checks;
+ int delay_wait_checks;
unsigned int version[3];
char * dev;
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index a22d16a..6c96633 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -290,6 +290,8 @@ setup_map (struct multipath * mpp, char * params, int params_size)
select_reservation_key(mpp);
select_retain_hwhandler(mpp);
select_deferred_remove(mpp);
+ select_delay_watch_checks(mpp);
+ select_delay_wait_checks(mpp);
sysfs_set_scsi_tmo(mpp);
/*
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index a7f1c11..23a0871 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -17,6 +17,7 @@
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
#define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF
#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF
+#define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF
#define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 7350231..4a79445 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -979,6 +979,58 @@ declare_def_snprint(reservation_key, print_reservation_key)
declare_mp_handler(reservation_key, set_reservation_key)
declare_mp_snprint(reservation_key, print_reservation_key)
+static int
+set_delay_checks(vector strvec, void *ptr)
+{
+ int *int_ptr = (int *)ptr;
+ char * buff;
+
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+
+ if (!strcmp(buff, "no") || !strcmp(buff, "0"))
+ *int_ptr = DELAY_CHECKS_OFF;
+ else if ((*int_ptr = atoi(buff)) < 1)
+ *int_ptr = DELAY_CHECKS_UNDEF;
+
+ FREE(buff);
+ return 0;
+}
+
+int
+print_delay_checks(char * buff, int len, void *ptr)
+{
+ int *int_ptr = (int *)ptr;
+
+ switch(*int_ptr) {
+ case DELAY_CHECKS_UNDEF:
+ return 0;
+ case DELAY_CHECKS_OFF:
+ return snprintf(buff, len, "\"off\"");
+ default:
+ return snprintf(buff, len, "%i", *int_ptr);
+ }
+}
+
+declare_def_handler(delay_watch_checks, set_delay_checks)
+declare_def_snprint(delay_watch_checks, print_delay_checks)
+declare_ovr_handler(delay_watch_checks, set_delay_checks)
+declare_ovr_snprint(delay_watch_checks, print_delay_checks)
+declare_hw_handler(delay_watch_checks, set_delay_checks)
+declare_hw_snprint(delay_watch_checks, print_delay_checks)
+declare_mp_handler(delay_watch_checks, set_delay_checks)
+declare_mp_snprint(delay_watch_checks, print_delay_checks)
+
+declare_def_handler(delay_wait_checks, set_delay_checks)
+declare_def_snprint(delay_wait_checks, print_delay_checks)
+declare_ovr_handler(delay_wait_checks, set_delay_checks)
+declare_ovr_snprint(delay_wait_checks, print_delay_checks)
+declare_hw_handler(delay_wait_checks, set_delay_checks)
+declare_hw_snprint(delay_wait_checks, print_delay_checks)
+declare_mp_handler(delay_wait_checks, set_delay_checks)
+declare_mp_snprint(delay_wait_checks, print_delay_checks)
+
/*
* blacklist block handlers
*/
@@ -1277,6 +1329,8 @@ init_keywords(void)
install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
install_keyword("partition_delimiter", &def_partition_delim_handler, &snprint_def_partition_delim);
install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir);
+ install_keyword("delay_watch_checks", &def_delay_watch_checks_handler, &snprint_def_delay_watch_checks);
+ install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks);
__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);
@@ -1345,6 +1399,8 @@ init_keywords(void)
install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler);
install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_hw_detect_prio);
install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove);
+ install_keyword("delay_watch_checks", &hw_delay_watch_checks_handler, &snprint_hw_delay_watch_checks);
+ install_keyword("delay_wait_checks", &hw_delay_wait_checks_handler, &snprint_hw_delay_wait_checks);
install_sublevel_end();
install_keyword_root("overrides", &overrides_handler);
@@ -1370,6 +1426,8 @@ init_keywords(void)
install_keyword("retain_attached_hw_handler", &ovr_retain_hwhandler_handler, &snprint_ovr_retain_hwhandler);
install_keyword("detect_prio", &ovr_detect_prio_handler, &snprint_ovr_detect_prio);
install_keyword("deferred_remove", &ovr_deferred_remove_handler, &snprint_ovr_deferred_remove);
+ install_keyword("delay_watch_checks", &ovr_delay_watch_checks_handler, &snprint_ovr_delay_watch_checks);
+ install_keyword("delay_wait_checks", &ovr_delay_wait_checks_handler, &snprint_ovr_delay_wait_checks);
install_keyword_root("multipaths", &multipaths_handler);
install_keyword_multi("multipath", &multipath_handler, NULL);
@@ -1394,5 +1452,7 @@ init_keywords(void)
install_keyword("reservation_key", &mp_reservation_key_handler, &snprint_mp_reservation_key);
install_keyword("user_friendly_names", &mp_user_friendly_names_handler, &snprint_mp_user_friendly_names);
install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove);
+ install_keyword("delay_watch_checks", &mp_delay_watch_checks_handler, &snprint_mp_delay_watch_checks);
+ install_keyword("delay_wait_checks", &mp_delay_wait_checks_handler, &snprint_mp_delay_wait_checks);
install_sublevel_end();
}
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
index 84b6180..4fdd576 100644
--- a/libmultipath/dict.h
+++ b/libmultipath/dict.h
@@ -14,5 +14,6 @@ int print_no_path_retry(char * buff, int len, void *ptr);
int print_fast_io_fail(char * buff, int len, void *ptr);
int print_dev_loss(char * buff, int len, void *ptr);
int print_reservation_key(char * buff, int len, void * ptr);
+int print_delay_checks(char * buff, int len, void *ptr);
#endif /* _DICT_H */
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 9762f1c..130a9af 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -340,6 +340,8 @@ snprint_chk_state (char * buff, size_t len, struct path * pp)
return snprintf(buff, len, "i/o pending");
case PATH_TIMEOUT:
return snprintf(buff, len, "i/o timeout");
+ case PATH_DELAYED:
+ return snprintf(buff, len, "delayed");
default:
return snprintf(buff, len, "undef");
}
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index f5c158b..46f8f63 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -616,3 +616,35 @@ out:
origin);
return 0;
}
+
+extern int
+select_delay_watch_checks(struct multipath *mp)
+{
+ char *origin, buff[12];
+
+ mp_set_mpe(delay_watch_checks);
+ mp_set_ovr(delay_watch_checks);
+ mp_set_hwe(delay_watch_checks);
+ mp_set_conf(delay_watch_checks);
+ mp_set_default(delay_watch_checks, DEFAULT_DELAY_CHECKS);
+out:
+ print_delay_checks(buff, 12, &mp->delay_watch_checks);
+ condlog(3, "%s: delay_watch_checks = %s %s", mp->alias, buff, origin);
+ return 0;
+}
+
+extern int
+select_delay_wait_checks(struct multipath *mp)
+{
+ char *origin, buff[12];
+
+ mp_set_mpe(delay_wait_checks);
+ mp_set_ovr(delay_wait_checks);
+ mp_set_hwe(delay_wait_checks);
+ mp_set_conf(delay_wait_checks);
+ mp_set_default(delay_wait_checks, DEFAULT_DELAY_CHECKS);
+out:
+ print_delay_checks(buff, 12, &mp->delay_wait_checks);
+ condlog(3, "%s: delay_wait_checks = %s %s", mp->alias, buff, origin);
+ return 0;
+}
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
index ffb58a5..f9598e7 100644
--- a/libmultipath/propsel.h
+++ b/libmultipath/propsel.h
@@ -20,3 +20,5 @@ 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);
+int select_delay_watch_checks (struct multipath * mp);
+int select_delay_wait_checks (struct multipath * mp);
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index b6cfff8..c02c76d 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -140,6 +140,11 @@ enum scsi_protocol {
SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */
};
+enum delay_checks_states {
+ DELAY_CHECKS_OFF = -1,
+ DELAY_CHECKS_UNDEF = 0,
+};
+
struct sg_id {
int host_no;
int channel;
@@ -186,6 +191,8 @@ struct path {
int priority;
int pgindex;
int detect_prio;
+ int watch_checks;
+ int wait_checks;
char * uid_attribute;
char * getuid;
struct prio prio;
@@ -221,6 +228,8 @@ struct multipath {
int fast_io_fail;
int retain_hwhandler;
int deferred_remove;
+ int delay_watch_checks;
+ int delay_wait_checks;
unsigned int dev_loss;
uid_t uid;
gid_t gid;
diff --git a/multipath.conf.annotated b/multipath.conf.annotated
index 2b148ac..0be034d 100644
--- a/multipath.conf.annotated
+++ b/multipath.conf.annotated
@@ -314,6 +314,30 @@
# # files, just as if it was in /etc/multipath.conf
# # values : "" or a fully qualified pathname
# # default : "/etc/multipath/conf.d"
+#
+# #
+# # name : delay_watch_checks
+# # scope : multipathd
+# # desc : If set to a value greater than 0, multipathd will watch
+# # paths that have recently become valid for this many
+# # checks. If they fail again while they are being watched,
+# # when they next become valid, they will not be used until
+# # they have stayed up for delay_wait_checks checks.
+# # values : no|<n> > 0
+# # default : no
+# delay_watch_checks 12
+#
+# #
+# # name : delay_wait_checks
+# # scope : multipathd
+# # desc : If set to a value greater than 0, when a device that has
+# # recently come back online fails again within
+# # delay_watch_checks checks, the next time it comes back
+# # online, it will marked and delayed, and not used until
+# # it has passed delay_wait_checks checks.
+# # values : no|<n> > 0
+# # default : no
+# delay_wait_checks 12
#}
#
##
@@ -482,6 +506,28 @@
# # default : determined by the process
# gid 0
#
+# #
+# # name : delay_watch_checks
+# # scope : multipathd
+# # desc : If set to a value greater than 0, multipathd will
+# # watch paths that have recently become valid for
+# # this many checks. If they fail again while they
+# # are being watched, when they next become valid,
+# # they will not be used until they have stayed up for
+# # delay_wait_checks checks.
+# # values : no|<n> > 0
+# delay_watch_checks 12
+#
+# #
+# # name : delay_wait_checks
+# # scope : multipathd
+# # desc : If set to a value greater than 0, when a device
+# # that has recently come back online fails again
+# # within delay_watch_checks checks, the next time it
+# # comes online, it will marked and delayed, and not
+# # used until it has passed delay_wait_checks checks.
+# # values : no|<n> > 0
+# delay_wait_checks 12
# }
# multipath {
# wwid 1DEC_____321816758474
@@ -653,6 +699,30 @@
# # before removing it from the system.
# # values : n > 0
# dev_loss_tmo 600
+#
+# #
+# # name : delay_watch_checks
+# # scope : multipathd
+# # desc : If set to a value greater than 0, multipathd will
+# # watch paths that have recently become valid for
+# # this many checks. If they fail again while they
+# # are being watched, when they next become valid,
+# # they will not be used until they have stayed up for
+# # delay_wait_checks checks.
+# # values : no|<n> > 0
+# delay_watch_checks 12
+#
+# #
+# # name : delay_wait_checks
+# # scope : multipathd
+# # desc : If set to a value greater than 0, when a device
+# # that has recently come back online fails again
+# # within delay_watch_checks checks, the next time it
+# # comes online, it will marked and delayed, and not
+# # used until it has passed delay_wait_checks checks.
+# # values : no|<n> > 0
+# delay_wait_checks 12
+#
# }
# device {
# vendor "COMPAQ "
diff --git a/multipath.conf.defaults b/multipath.conf.defaults
index 9244f71..5f43c57 100644
--- a/multipath.conf.defaults
+++ b/multipath.conf.defaults
@@ -27,6 +27,8 @@
# retain_attached_hw_handler no
# detect_prio no
# config_dir "/etc/multipath/conf.d"
+# delay_watch_checks no
+# delay_wait_checks no
#}
#blacklist {
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 4eb238d..3fe56bc 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -439,6 +439,25 @@ alphabetically for file ending in ".conf" and it will read configuration
information from them, just as if it was in /etc/multipath.conf. config_dir
must either be "" or a fully qualified directory name. Default is
.I "/etc/multipath/conf.d"
+.TP
+.B delay_watch_checks
+If set to a value greater than 0, multipathd will watch paths that have
+recently become valid for this many checks. If they fail again while they are
+being watched, when they next become valid, they will not be used until they
+have stayed up for
+.I delay_wait_checks
+checks. Default is
+.I no
+.TP
+.B delay_wait_checks
+If set to a value greater than 0, when a device that has recently come back
+online fails again within
+.I delay_watch_checks
+checks, the next time it comes back online, it will marked and delayed, and not
+used until it has passed
+.I delay_wait_checks
+checks. Default is
+.I no
.
.SH "blacklist section"
The
@@ -559,6 +578,10 @@ section:
.B reservation_key
.TP
.B deferred_remove
+.TP
+.B delay_watch_checks
+.TP
+.B delay_wait_checks
.RE
.PD
.LP
@@ -651,6 +674,10 @@ section:
.B detect_prio
.TP
.B deferred_remove
+.TP
+.B delay_watch_checks
+.TP
+.B delay_wait_checks
.RE
.PD
.LP
@@ -706,6 +733,10 @@ sections:
.B detect_prio
.TP
.B deferred_remove
+.TP
+.B delay_watch_checks
+.TP
+.B delay_wait_checks
.RE
.PD
.LP
diff --git a/multipathd/main.c b/multipathd/main.c
index 7429f66..aac8a19 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -192,7 +192,8 @@ sync_map_state(struct multipath *mpp)
vector_foreach_slot (mpp->pg, pgp, i){
vector_foreach_slot (pgp->paths, pp, j){
if (pp->state == PATH_UNCHECKED ||
- pp->state == PATH_WILD)
+ pp->state == PATH_WILD ||
+ pp->state == PATH_DELAYED)
continue;
if ((pp->dmstate == PSTATE_FAILED ||
pp->dmstate == PSTATE_UNDEF) &&
@@ -1184,6 +1185,16 @@ check_path (struct vectors * vecs, struct path * pp)
if (!pp->mpp)
return 0;
+ if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
+ pp->wait_checks > 0) {
+ if (pp->mpp && pp->mpp->nr_active > 0) {
+ pp->state = PATH_DELAYED;
+ pp->wait_checks--;
+ return 1;
+ } else
+ pp->wait_checks = 0;
+ }
+
pp->chkrstate = newstate;
if (newstate != pp->state) {
int oldstate = pp->state;
@@ -1203,9 +1214,14 @@ check_path (struct vectors * vecs, struct path * pp)
* proactively fail path in the DM
*/
if (oldstate == PATH_UP ||
- oldstate == PATH_GHOST)
+ oldstate == PATH_GHOST) {
fail_path(pp, 1);
- else
+ if (pp->mpp->delay_wait_checks > 0 &&
+ pp->watch_checks > 0) {
+ pp->wait_checks = pp->mpp->delay_wait_checks;
+ pp->watch_checks = 0;
+ }
+ }else
fail_path(pp, 0);
/*
@@ -1232,11 +1248,15 @@ check_path (struct vectors * vecs, struct path * pp)
* reinstate this path
*/
if (oldstate != PATH_UP &&
- oldstate != PATH_GHOST)
+ oldstate != PATH_GHOST) {
+ if (pp->mpp->delay_watch_checks > 0)
+ pp->watch_checks = pp->mpp->delay_watch_checks;
reinstate_path(pp, 1);
- else
+ } else {
+ if (pp->watch_checks > 0)
+ pp->watch_checks--;
reinstate_path(pp, 0);
-
+ }
new_path_up = 1;
if (oldchkrstate != PATH_UP && oldchkrstate != PATH_GHOST)
@@ -1269,6 +1289,8 @@ check_path (struct vectors * vecs, struct path * pp)
condlog(4, "%s: delay next check %is",
pp->dev_t, pp->checkint);
}
+ if (pp->watch_checks > 0)
+ pp->watch_checks--;
pp->tick = pp->checkint;
}
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 14/15] Fix doublee free of alias after map add failure
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (12 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 13/15] multipathd: Add delayed path reintegration Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 15/15] libmultipath: autodetect ALUA CLARiiON configurations Benjamin Marzinski
2015-03-08 10:04 ` [PATCH 00/15] Multipath patch resync Christophe Varoqui
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
In ev_add_map(), if add_map_without_path() fails, the alias will have
been freed by free_multipath(), so you can't access it anymore. Also,
if the multipath device already exists, but you fail to register it,
there's no point in trying to create the device. It will fail.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index aac8a19..62339ae 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -314,10 +314,15 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
/*
* now we can register the map
*/
- if (map_present && (mpp = add_map_without_path(vecs, alias))) {
- sync_map_state(mpp);
- condlog(2, "%s: devmap %s registered", alias, dev);
- return 0;
+ if (map_present) {
+ if ((mpp = add_map_without_path(vecs, alias))) {
+ sync_map_state(mpp);
+ condlog(2, "%s: devmap %s registered", alias, dev);
+ return 0;
+ } else {
+ condlog(2, "%s: uev_add_map failed", dev);
+ return 1;
+ }
}
r = get_refwwid(dev, DEV_DEVMAP, vecs->pathvec, &refwwid);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 15/15] libmultipath: autodetect ALUA CLARiiON configurations
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (13 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 14/15] Fix doublee free of alias after map add failure Benjamin Marzinski
@ 2015-03-08 3:31 ` Benjamin Marzinski
2015-03-08 10:04 ` [PATCH 00/15] Multipath patch resync Christophe Varoqui
15 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-08 3:31 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
This patch enables ALUA autodetection on EMC CLARiiON devices. EMC has
tested the change.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 2 ++
multipath.conf.defaults | 2 ++
2 files changed, 4 insertions(+)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index bf2c2ca..d51dcb8 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -272,6 +272,8 @@ static struct hwentry default_hw[] = {
.checker_name = EMC_CLARIION,
.prio_name = PRIO_EMC,
.prio_args = NULL,
+ .retain_hwhandler = RETAIN_HWHANDLER_ON,
+ .detect_prio = DETECT_PRIO_ON,
},
{
.vendor = "EMC",
diff --git a/multipath.conf.defaults b/multipath.conf.defaults
index 5f43c57..a12a4f4 100644
--- a/multipath.conf.defaults
+++ b/multipath.conf.defaults
@@ -263,6 +263,8 @@
# failback "immediate"
# rr_weight "uniform"
# no_path_retry 60
+# retain_attached_hw_handler yes
+# detect_prio yes
# }
# device {
# vendor "EMC"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 00/15] Multipath patch resync
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
` (14 preceding siblings ...)
2015-03-08 3:31 ` [PATCH 15/15] libmultipath: autodetect ALUA CLARiiON configurations Benjamin Marzinski
@ 2015-03-08 10:04 ` Christophe Varoqui
2015-03-11 1:35 ` Benjamin Marzinski
15 siblings, 1 reply; 21+ messages in thread
From: Christophe Varoqui @ 2015-03-08 10:04 UTC (permalink / raw)
To: Benjamin Marzinski; +Cc: device-mapper development
[-- Attachment #1.1: Type: text/plain, Size: 4514 bytes --]
All good and applied. Thanks.
One minor glitch : building without LIBDM_API_DEFERRED defined leaves the
dm_cancel_remove_partmaps() function without use, which emits the following
build warning
devmapper.c:35:12: warning: ‘dm_cancel_remove_partmaps’ declared ‘static’
but never defined [-Wunused-function]
static int dm_cancel_remove_partmaps(const char * mapname);
Would moving the function declaration in the #ifdef be fine with you ?
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 69491a3..458841f 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -32,8 +32,6 @@
#define UUID_PREFIX "mpath-"
#define UUID_PREFIX_LEN 6
-static int dm_cancel_remove_partmaps(const char * mapname);
-
#ifndef LIBDM_API_COOKIE
static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int
a)
{
@@ -1134,9 +1132,15 @@ dm_remove_partmaps (const char * mapname, int
need_sync, int deferred_remove)
return do_foreach_partmaps(mapname, remove_partmap, &rd);
}
+
#ifdef LIBDM_API_DEFERRED
static int
+dm_cancel_remove_partmaps(const char * mapname) {
+ return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
+}
+
+static int
cancel_remove_partmap (char *name, void *unused)
{
if (dm_get_opencount(name))
@@ -1172,11 +1176,6 @@ out:
return r;
}
-static int
-dm_cancel_remove_partmaps(const char * mapname) {
- return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
-}
-
int
dm_cancel_deferred_remove (struct multipath *mpp)
{
Best regards,
Christophe Varoqui
OpenSVC
On Sun, Mar 8, 2015 at 4:31 AM, Benjamin Marzinski <bmarzins@redhat.com>
wrote:
> The first eight of these patches are resends of earlier patches, just
> rebased with minor changes. The next two are minor changes, adding
> multipath's -B option to mutipathd, and blacklisting vd.* devices.
> The two after that allow multipath to read additional configuration
> files in a configuration directory /etc/multipath/conf.d by default,
> and then do some cleanup of the parser code that I noticed while
> adding the configuration directories. The next patch adds two new
> configuration parameters that allow multipathd to delay the
> reintegration of paths that are failing repeatedly. The next one
> fixes a hard to hit memory corruption bug, and the last one
> updates the EMC builtin configuration to autodetect ALUA setups.
>
> Benjamin Marzinski (15):
> correctly set partition delimiter on rename
> libmultipath: fix sysfs_get_size bug
> Revert "libmultipath: fixup strlcpy"
> libmultipath: refactor partmaps code
> multipathd: fix memory corruption issue
> multipathd: add deferred_remove support
> multipathd: don't buffer output with systemd
> libmutipath: allow blanks in device blacklist
> multipathd: read-only bindings
> multipath: blacklist virtio-blk devices
> multipath: enable configuration directory
> libmultipath: cleanup parser code
> multipathd: Add delayed path reintegration
> Fix doublee free of alias after map add failure
> libmultipath: autodetect ALUA CLARiiON configurations
>
> libmultipath/Makefile | 6 +
> libmultipath/blacklist.c | 18 ++-
> libmultipath/checkers.c | 1 +
> libmultipath/checkers.h | 9 ++
> libmultipath/config.c | 69 ++++++++++-
> libmultipath/config.h | 12 ++
> libmultipath/configure.c | 3 +
> libmultipath/defaults.h | 3 +
> libmultipath/devmapper.c | 284
> +++++++++++++++++++++++++++++----------------
> libmultipath/devmapper.h | 11 +-
> libmultipath/dict.c | 126 +++++++++++++++++---
> libmultipath/dict.h | 1 +
> libmultipath/hwtable.c | 2 +
> libmultipath/parser.c | 173 ++++++++-------------------
> libmultipath/parser.h | 9 +-
> libmultipath/print.c | 2 +
> libmultipath/propsel.c | 58 +++++++++
> libmultipath/propsel.h | 3 +
> libmultipath/structs.h | 17 +++
> libmultipath/structs_vec.c | 3 +-
> libmultipath/sysfs.c | 2 +-
> libmultipath/util.c | 3 +-
> multipath.conf.annotated | 80 +++++++++++++
> multipath.conf.defaults | 7 +-
> multipath/multipath.conf.5 | 54 +++++++++
> multipathd/main.c | 86 ++++++++++----
> multipathd/multipathd.8 | 5 +
> 27 files changed, 761 insertions(+), 286 deletions(-)
>
> --
> 1.8.3.1
>
>
[-- Attachment #1.2: Type: text/html, Size: 5747 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 11/15] multipath: enable configuration directory
2015-03-08 3:31 ` [PATCH 11/15] multipath: enable configuration directory Benjamin Marzinski
@ 2015-03-08 22:27 ` Sebastian Herbszt
2015-03-08 23:29 ` Christophe Varoqui
0 siblings, 1 reply; 21+ messages in thread
From: Sebastian Herbszt @ 2015-03-08 22:27 UTC (permalink / raw)
To: device-mapper development; +Cc: Sebastian Herbszt, Christophe Varoqui
Benjamin Marzinski wrote:
> Users who setup multipath on many machines sometimes want a core
> configuration file that stays the same on all machines, and also secondary
> configuration files that are unique to each machine to set blacklists and
> aliases. This patch enables this by adding a new configuration option,
> "config_dir", which defaults to "/etc/multipath/conf.d". If this is set,
> multipath will check this directory for files ending in .conf, and apply
> them on top of the initial configuration file in alphabetical order.
How about using "/etc/multipath.conf.d" instead of "/etc/multipath/conf.d" ?
Sebastian
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 11/15] multipath: enable configuration directory
2015-03-08 22:27 ` Sebastian Herbszt
@ 2015-03-08 23:29 ` Christophe Varoqui
2015-03-09 0:42 ` Sebastian Herbszt
0 siblings, 1 reply; 21+ messages in thread
From: Christophe Varoqui @ 2015-03-08 23:29 UTC (permalink / raw)
To: Sebastian Herbszt; +Cc: device-mapper development
[-- Attachment #1.1: Type: text/plain, Size: 1157 bytes --]
I had the same thought reading the patch, but I couldn't see any
consistency in existing "*.d" directory locations in modern distros I
couldn't decently object to Ben's proposal :
Following Ben's proposal :
/etc/udev/*.d
/etc/mysql/conf.d
/etc/apm/*.d
Following your proposal :
/etc/rsyslog.d
/etc/sysctl.d
/etc/profile.d
Does somebody know if the LSB FHS gives guidelines for this ?
Best regards,
Christophe Varoqui
On Sun, Mar 8, 2015 at 11:27 PM, Sebastian Herbszt <herbszt@gmx.de> wrote:
> Benjamin Marzinski wrote:
> > Users who setup multipath on many machines sometimes want a core
> > configuration file that stays the same on all machines, and also
> secondary
> > configuration files that are unique to each machine to set blacklists and
> > aliases. This patch enables this by adding a new configuration option,
> > "config_dir", which defaults to "/etc/multipath/conf.d". If this is set,
> > multipath will check this directory for files ending in .conf, and apply
> > them on top of the initial configuration file in alphabetical order.
>
> How about using "/etc/multipath.conf.d" instead of "/etc/multipath/conf.d"
> ?
>
> Sebastian
>
[-- Attachment #1.2: Type: text/html, Size: 1825 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 11/15] multipath: enable configuration directory
2015-03-08 23:29 ` Christophe Varoqui
@ 2015-03-09 0:42 ` Sebastian Herbszt
0 siblings, 0 replies; 21+ messages in thread
From: Sebastian Herbszt @ 2015-03-09 0:42 UTC (permalink / raw)
To: Christophe Varoqui; +Cc: device-mapper development, Sebastian Herbszt
Christophe Varoqui wrote:
> I had the same thought reading the patch, but I couldn't see any
> consistency in existing "*.d" directory locations in modern distros I
> couldn't decently object to Ben's proposal :
On my fairly recent openSUSE I (also) have
> Following Ben's proposal :
> /etc/udev/*.d
> /etc/mysql/conf.d
> /etc/apm/*.d
/etc/X11/xorg.conf.d
/etc/fonts/conf.d
> Following your proposal :
> /etc/rsyslog.d
> /etc/sysctl.d
> /etc/profile.d
/etc/auto.master.d
/etc/ld.so.conf.d
/etc/sudoers.d
/etc/permissions.d
/etc/aliases.d
/etc/gdbinit.d
> Does somebody know if the LSB FHS gives guidelines for this ?
>
> Best regards,
> Christophe Varoqui
Sebastian
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 00/15] Multipath patch resync
2015-03-08 10:04 ` [PATCH 00/15] Multipath patch resync Christophe Varoqui
@ 2015-03-11 1:35 ` Benjamin Marzinski
0 siblings, 0 replies; 21+ messages in thread
From: Benjamin Marzinski @ 2015-03-11 1:35 UTC (permalink / raw)
To: Christophe Varoqui; +Cc: device-mapper development
On Sun, Mar 08, 2015 at 11:04:19AM +0100, Christophe Varoqui wrote:
> All good and applied. Thanks.
> One minor glitch : building without LIBDM_API_DEFERRED defined leaves the
> dm_cancel_remove_partmaps() function without use, which emits the
> following build warning
> devmapper.c:35:12: warning: ‘dm_cancel_remove_partmaps’ declared ‘static’
> but never defined [-Wunused-function]
> static int dm_cancel_remove_partmaps(const char * mapname);
> Would moving the function declaration in the #ifdef be fine with you ?
Oops. Yeah. This looks fine.
Thanks
-Ben
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 69491a3..458841f 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -32,8 +32,6 @@
> #define UUID_PREFIX "mpath-"
> #define UUID_PREFIX_LEN 6
>
> -static int dm_cancel_remove_partmaps(const char * mapname);
> -
> #ifndef LIBDM_API_COOKIE
> static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c,
> int a)
> {
> @@ -1134,9 +1132,15 @@ dm_remove_partmaps (const char * mapname, int
> need_sync, int deferred_remove)
> return do_foreach_partmaps(mapname, remove_partmap, &rd);
> }
>
> +
> #ifdef LIBDM_API_DEFERRED
>
> static int
> +dm_cancel_remove_partmaps(const char * mapname) {
> + return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
> +}
> +
> +static int
> cancel_remove_partmap (char *name, void *unused)
> {
> if (dm_get_opencount(name))
> @@ -1172,11 +1176,6 @@ out:
> return r;
> }
>
> -static int
> -dm_cancel_remove_partmaps(const char * mapname) {
> - return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
> -}
> -
> int
> dm_cancel_deferred_remove (struct multipath *mpp)
> {
> Best regards,
> Christophe Varoqui
> OpenSVC
> On Sun, Mar 8, 2015 at 4:31 AM, Benjamin Marzinski
> <[1]bmarzins@redhat.com> wrote:
>
> The first eight of these patches are resends of earlier patches, just
> rebased with minor changes. The next two are minor changes, adding
> multipath's -B option to mutipathd, and blacklisting vd.* devices.
> The two after that allow multipath to read additional configuration
> files in a configuration directory /etc/multipath/conf.d by default,
> and then do some cleanup of the parser code that I noticed while
> adding the configuration directories. The next patch adds two new
> configuration parameters that allow multipathd to delay the
> reintegration of paths that are failing repeatedly. The next one
> fixes a hard to hit memory corruption bug, and the last one
> updates the EMC builtin configuration to autodetect ALUA setups.
>
> Benjamin Marzinski (15):
> correctly set partition delimiter on rename
> libmultipath: fix sysfs_get_size bug
> Revert "libmultipath: fixup strlcpy"
> libmultipath: refactor partmaps code
> multipathd: fix memory corruption issue
> multipathd: add deferred_remove support
> multipathd: don't buffer output with systemd
> libmutipath: allow blanks in device blacklist
> multipathd: read-only bindings
> multipath: blacklist virtio-blk devices
> multipath: enable configuration directory
> libmultipath: cleanup parser code
> multipathd: Add delayed path reintegration
> Fix doublee free of alias after map add failure
> libmultipath: autodetect ALUA CLARiiON configurations
>
> libmultipath/Makefile | 6 +
> libmultipath/blacklist.c | 18 ++-
> libmultipath/checkers.c | 1 +
> libmultipath/checkers.h | 9 ++
> libmultipath/config.c | 69 ++++++++++-
> libmultipath/config.h | 12 ++
> libmultipath/configure.c | 3 +
> libmultipath/defaults.h | 3 +
> libmultipath/devmapper.c | 284
> +++++++++++++++++++++++++++++----------------
> libmultipath/devmapper.h | 11 +-
> libmultipath/dict.c | 126 +++++++++++++++++---
> libmultipath/dict.h | 1 +
> libmultipath/hwtable.c | 2 +
> libmultipath/parser.c | 173 ++++++++-------------------
> libmultipath/parser.h | 9 +-
> libmultipath/print.c | 2 +
> libmultipath/propsel.c | 58 +++++++++
> libmultipath/propsel.h | 3 +
> libmultipath/structs.h | 17 +++
> libmultipath/structs_vec.c | 3 +-
> libmultipath/sysfs.c | 2 +-
> libmultipath/util.c | 3 +-
> multipath.conf.annotated | 80 +++++++++++++
> multipath.conf.defaults | 7 +-
> multipath/multipath.conf.5 | 54 +++++++++
> multipathd/main.c | 86 ++++++++++----
> multipathd/multipathd.8 | 5 +
> 27 files changed, 761 insertions(+), 286 deletions(-)
> --
> 1.8.3.1
>
> References
>
> Visible links
> 1. mailto:bmarzins@redhat.com
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2015-03-11 1:35 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-08 3:31 [PATCH 00/15] Multipath patch resync Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 01/15] correctly set partition delimiter on rename Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 02/15] libmultipath: fix sysfs_get_size bug Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 03/15] Revert "libmultipath: fixup strlcpy" Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 04/15] libmultipath: refactor partmaps code Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 05/15] multipathd: fix memory corruption issue Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 06/15] multipathd: add deferred_remove support Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 07/15] multipathd: don't buffer output with systemd Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 08/15] libmutipath: allow blanks in device blacklist Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 09/15] multipathd: read-only bindings Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 10/15] multipath: blacklist virtio-blk devices Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 11/15] multipath: enable configuration directory Benjamin Marzinski
2015-03-08 22:27 ` Sebastian Herbszt
2015-03-08 23:29 ` Christophe Varoqui
2015-03-09 0:42 ` Sebastian Herbszt
2015-03-08 3:31 ` [PATCH 12/15] libmultipath: cleanup parser code Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 13/15] multipathd: Add delayed path reintegration Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 14/15] Fix doublee free of alias after map add failure Benjamin Marzinski
2015-03-08 3:31 ` [PATCH 15/15] libmultipath: autodetect ALUA CLARiiON configurations Benjamin Marzinski
2015-03-08 10:04 ` [PATCH 00/15] Multipath patch resync Christophe Varoqui
2015-03-11 1:35 ` Benjamin Marzinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.