summaryrefslogtreecommitdiffstats
path: root/0104-RHBZ-631009-deferred-remove.patch
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2017-05-25 17:12:56 -0500
committerBenjamin Marzinski <bmarzins@redhat.com>2017-05-25 17:12:56 -0500
commita4bb435b339a71961c09722879c45649dec01057 (patch)
treed395b1874ed4e9fc7f4686e2581db05fab088ed1 /0104-RHBZ-631009-deferred-remove.patch
parent3591e72a603304adc6f8fb72fbe47ddbf8760eeb (diff)
device-mapper-multipath-0.7.1-1.gitf21166a
- Update Source to the latest upstream commit - Add 0001-libmultipath-add-comment-about-resuming.patch * posted upstream - Add 0002-multipath-attempt-at-common-multipath.rules.patch * under discussion upstream - Add 0003-RH-fixup-udev-rules-for-redhat.patch * Redhat uses different udev rules that some other distros, so multipath has run at a different time. Not all upstream distros link /sbin and /usr/sbin either. - Add 0004-RH-Remove-the-property-blacklist-exception-builtin.patch * Allow multipath to be used on devices without multiple paths. NAK'ed upstream, but requested by Red Hat - Add 0005-RH-don-t-start-without-a-config-file.patch * Don't start multipath unless a config file exists. NAK'ed upstream, but requested by Red Hat - Add 0006-RH-use-rpm-optflags-if-present.patch * Make the build system fedora friendly - Add 0007-RH-add-mpathconf.patch * Add tool to help configure multipath with Red Hat defaults. - Add 0008-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch * Make multipath able to claim devices based on the kernel command line NAK'ed upstream but requested by Red Hat - Add 0009-RH-trigger-change-uevent-on-new-device-creation.patch * under discussion upstream
Diffstat (limited to '0104-RHBZ-631009-deferred-remove.patch')
-rw-r--r--0104-RHBZ-631009-deferred-remove.patch793
1 files changed, 0 insertions, 793 deletions
diff --git a/0104-RHBZ-631009-deferred-remove.patch b/0104-RHBZ-631009-deferred-remove.patch
deleted file mode 100644
index 07f734c..0000000
--- a/0104-RHBZ-631009-deferred-remove.patch
+++ /dev/null
@@ -1,793 +0,0 @@
----
- libmultipath/Makefile | 6 +
- libmultipath/config.c | 3
- libmultipath/config.h | 3
- libmultipath/configure.c | 1
- libmultipath/defaults.h | 1
- libmultipath/devmapper.c | 142 ++++++++++++++++++++++++++++++++++++++++-----
- libmultipath/devmapper.h | 11 ++-
- libmultipath/dict.c | 116 ++++++++++++++++++++++++++++++++++++
- libmultipath/propsel.c | 28 ++++++++
- libmultipath/propsel.h | 1
- libmultipath/structs.h | 8 ++
- libmultipath/structs_vec.c | 3
- multipath/multipath.conf.5 | 36 +++++++++++
- multipathd/main.c | 23 +++++--
- 14 files changed, 355 insertions(+), 27 deletions(-)
-
-Index: multipath-tools-130222/libmultipath/config.c
-===================================================================
---- multipath-tools-130222.orig/libmultipath/config.c
-+++ multipath-tools-130222/libmultipath/config.c
-@@ -337,6 +337,7 @@ merge_hwe (struct hwentry * dst, struct
- merge_num(user_friendly_names);
- merge_num(retain_hwhandler);
- merge_num(detect_prio);
-+ merge_num(deferred_remove);
-
- /*
- * Make sure features is consistent with
-@@ -394,6 +395,7 @@ overwrite_hwe (struct hwentry * dst, str
- overwrite_num(user_friendly_names);
- overwrite_num(retain_hwhandler);
- overwrite_num(detect_prio);
-+ overwrite_num(deferred_remove);
-
- /*
- * Make sure features is consistent with
-@@ -617,6 +619,7 @@ load_config (char * file, struct udev *u
- conf->fast_io_fail = DEFAULT_FAST_IO_FAIL;
- conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
- conf->detect_prio = DEFAULT_DETECT_PRIO;
-+ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE;
- conf->hw_strmatch = 0;
- conf->force_sync = 0;
-
-Index: multipath-tools-130222/libmultipath/config.h
-===================================================================
---- multipath-tools-130222.orig/libmultipath/config.h
-+++ multipath-tools-130222/libmultipath/config.h
-@@ -61,6 +61,7 @@ struct hwentry {
- int user_friendly_names;
- int retain_hwhandler;
- int detect_prio;
-+ int deferred_remove;
- char * bl_product;
- };
-
-@@ -84,6 +85,7 @@ struct mpentry {
- int flush_on_last_del;
- int attribute_flags;
- int user_friendly_names;
-+ int deferred_remove;
- uid_t uid;
- gid_t gid;
- mode_t mode;
-@@ -128,6 +130,7 @@ struct config {
- int retain_hwhandler;
- int detect_prio;
- int force_sync;
-+ int deferred_remove;
- unsigned int version[3];
-
- char * dev;
-Index: multipath-tools-130222/libmultipath/configure.c
-===================================================================
---- multipath-tools-130222.orig/libmultipath/configure.c
-+++ multipath-tools-130222/libmultipath/configure.c
-@@ -290,6 +290,7 @@ setup_map (struct multipath * mpp, char
- select_dev_loss(mpp);
- select_reservation_key(mpp);
- select_retain_hwhandler(mpp);
-+ select_deferred_remove(mpp);
-
- sysfs_set_scsi_tmo(mpp);
- /*
-Index: multipath-tools-130222/libmultipath/defaults.h
-===================================================================
---- multipath-tools-130222.orig/libmultipath/defaults.h
-+++ multipath-tools-130222/libmultipath/defaults.h
-@@ -19,6 +19,7 @@
- #define DEFAULT_FAST_IO_FAIL 5
- #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
- #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF
-+#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF
-
- #define DEFAULT_CHECKINT 5
- #define MAX_CHECKINT(a) (a << 2)
-Index: multipath-tools-130222/libmultipath/devmapper.c
-===================================================================
---- multipath-tools-130222.orig/libmultipath/devmapper.c
-+++ multipath-tools-130222/libmultipath/devmapper.c
-@@ -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)
- {
-@@ -103,7 +105,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};
-@@ -201,8 +205,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));
-@@ -220,7 +226,10 @@ dm_simplecmd (int task, const char *name
- if (no_flush)
- dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */
- #endif
--
-+#ifdef LIBDM_API_DEFERRED
-+ if (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);
-@@ -232,12 +241,18 @@ dm_simplecmd (int task, const char *name
-
- extern int
- dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) {
-- return dm_simplecmd(task, name, 0, needsync, udev_flags);
-+ return dm_simplecmd(task, name, 0, needsync, udev_flags, 0);
- }
-
- extern int
- dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) {
-- return dm_simplecmd(task, name, 1, 1, udev_flags);
-+ return dm_simplecmd(task, name, 1, 1, udev_flags, 0);
-+}
-+
-+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
-@@ -653,7 +668,7 @@ out:
- }
-
- extern int
--_dm_flush_map (const char * mapname, int need_sync)
-+_dm_flush_map (const char * mapname, int need_sync, int deferred_remove)
- {
- int r;
-
-@@ -663,23 +678,46 @@ _dm_flush_map (const char * mapname, int
- if (dm_type(mapname, TGT_MPATH) <= 0)
- return 0; /* nothing to do */
-
-- if (dm_remove_partmaps(mapname, need_sync))
-+ if (dm_remove_partmaps(mapname, need_sync, deferred_remove))
- return 1;
-
-- if (dm_get_opencount(mapname)) {
-+ if (!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)
- {
-@@ -1076,6 +1114,7 @@ out:
-
- struct remove_data {
- int need_sync;
-+ int deferred_remove;
- };
-
- static int
-@@ -1084,25 +1123,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)
- {
-Index: multipath-tools-130222/libmultipath/devmapper.h
-===================================================================
---- multipath-tools-130222.orig/libmultipath/devmapper.h
-+++ multipath-tools-130222/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);
-@@ -40,7 +42,8 @@ int dm_geteventnr (char *name);
- int dm_get_major (char *name);
- int dm_get_minor (char *name);
- char * dm_mapname(int major, int minor);
--int dm_remove_partmaps (const char * mapname, int need_sync);
-+int dm_remove_partmaps (const char * mapname, int need_sync,
-+ int deferred_remove);
- int dm_get_uuid(char *name, char *uuid);
- int dm_get_info (char * mapname, struct dm_info ** dmi);
- int dm_rename (char * old, char * new);
-Index: multipath-tools-130222/libmultipath/dict.c
-===================================================================
---- multipath-tools-130222.orig/libmultipath/dict.c
-+++ multipath-tools-130222/libmultipath/dict.c
-@@ -738,6 +738,29 @@ def_force_sync_handler(vector strvec)
- return 0;
- }
-
-+static int
-+def_deferred_remove_handler(vector strvec)
-+{
-+ char * buff;
-+
-+ buff = set_value(strvec);
-+
-+ if (!buff)
-+ return 1;
-+
-+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
-+ (strlen(buff) == 1 && !strcmp(buff, "0")))
-+ conf->deferred_remove = DEFERRED_REMOVE_OFF;
-+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
-+ (strlen(buff) == 1 && !strcmp(buff, "1")))
-+ conf->deferred_remove = DEFERRED_REMOVE_ON;
-+ else
-+ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE;
-+
-+ FREE(buff);
-+ return 0;
-+}
-+
- /*
- * blacklist block handlers
- */
-@@ -1445,6 +1468,33 @@ hw_detect_prio_handler(vector strvec)
- return 0;
- }
-
-+static int
-+hw_deferred_remove_handler(vector strvec)
-+{
-+ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
-+ char * buff;
-+
-+ if (!hwe)
-+ return 1;
-+
-+ buff = set_value(strvec);
-+
-+ if (!buff)
-+ return 1;
-+
-+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
-+ (strlen(buff) == 1 && !strcmp(buff, "0")))
-+ hwe->deferred_remove = DEFERRED_REMOVE_OFF;
-+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
-+ (strlen(buff) == 1 && !strcmp(buff, "1")))
-+ hwe->deferred_remove = DEFERRED_REMOVE_ON;
-+ else
-+ hwe->deferred_remove = DEFERRED_REMOVE_UNDEF;
-+
-+ FREE(buff);
-+ return 0;
-+}
-+
- /*
- * multipaths block handlers
- */
-@@ -1920,6 +1970,32 @@ mp_names_handler(vector strvec)
- return 0;
- }
-
-+static int
-+mp_deferred_remove_handler(vector strvec)
-+{
-+ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
-+ char * buff;
-+
-+ if (!mpe)
-+ return 1;
-+
-+ buff = set_value(strvec);
-+ if (!buff)
-+ return 1;
-+
-+ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) ||
-+ (strlen(buff) == 1 && strcmp(buff, "0") == 0))
-+ mpe->deferred_remove = DEFERRED_REMOVE_OFF;
-+ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) ||
-+ (strlen(buff) == 1 && strcmp(buff, "1") == 0))
-+ mpe->deferred_remove = DEFERRED_REMOVE_ON;
-+ else
-+ mpe->deferred_remove = DEFERRED_REMOVE_UNDEF;
-+
-+ FREE(buff);
-+ return 0;
-+}
-+
- /*
- * config file keywords printing
- */
-@@ -2165,7 +2241,7 @@ snprint_mp_reservation_key (char * buff,
- return snprintf(buff, len, "0x%" PRIx64, prkey);
- }
-
-- static int
-+static int
- snprint_mp_user_friendly_names (char * buff, int len, void * data)
- {
- struct mpentry * mpe = (struct mpentry *)data;
-@@ -2179,6 +2255,19 @@ snprint_mp_user_friendly_names (char * b
- }
-
- static int
-+snprint_mp_deferred_remove (char * buff, int len, void * data)
-+{
-+ struct mpentry * mpe = (struct mpentry *)data;
-+
-+ if (mpe->deferred_remove == DEFERRED_REMOVE_UNDEF)
-+ return 0;
-+ else if (mpe->deferred_remove == DEFERRED_REMOVE_OFF)
-+ return snprintf(buff, len, "no");
-+ else
-+ return snprintf(buff, len, "yes");
-+}
-+
-+static int
- snprint_hw_fast_io_fail(char * buff, int len, void * data)
- {
- struct hwentry * hwe = (struct hwentry *)data;
-@@ -2507,6 +2596,19 @@ snprint_hw_retain_hwhandler_handler(char
- }
-
- static int
-+snprint_hw_deferred_remove(char * buff, int len, void * data)
-+{
-+ struct hwentry * hwe = (struct hwentry *)data;
-+
-+ if (hwe->deferred_remove == DEFERRED_REMOVE_ON)
-+ return snprintf(buff, len, "yes");
-+ else if (hwe->deferred_remove == DEFERRED_REMOVE_OFF)
-+ return snprintf(buff, len, "no");
-+ else
-+ return 0;
-+}
-+
-+static int
- snprint_detect_prio(char * buff, int len, void * data)
- {
- struct hwentry * hwe = (struct hwentry *)data;
-@@ -2900,6 +3002,15 @@ snprint_def_force_sync(char * buff, int
- }
-
- static int
-+snprint_def_deferred_remove(char * buff, int len, void * data)
-+{
-+ if (conf->deferred_remove == DEFERRED_REMOVE_ON)
-+ return snprintf(buff, len, "yes");
-+ else
-+ return snprintf(buff, len, "no");
-+}
-+
-+static int
- snprint_ble_simple (char * buff, int len, void * data)
- {
- struct blentry * ble = (struct blentry *)data;
-@@ -2968,6 +3079,7 @@ init_keywords(void)
- install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio);
- install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch);
- install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
-+ install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
- __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
- __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
- __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
-@@ -3032,6 +3144,7 @@ init_keywords(void)
- install_keyword("user_friendly_names", &hw_names_handler, &snprint_hw_user_friendly_names);
- install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler);
- install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_detect_prio);
-+ install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove);
- install_sublevel_end();
-
- install_keyword_root("multipaths", &multipaths_handler);
-@@ -3056,5 +3169,6 @@ init_keywords(void)
- install_keyword("gid", &mp_gid_handler, &snprint_mp_gid);
- install_keyword("reservation_key", &mp_reservation_key_handler, &snprint_mp_reservation_key);
- install_keyword("user_friendly_names", &mp_names_handler, &snprint_mp_user_friendly_names);
-+ install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove);
- install_sublevel_end();
- }
-Index: multipath-tools-130222/libmultipath/propsel.c
-===================================================================
---- multipath-tools-130222.orig/libmultipath/propsel.c
-+++ multipath-tools-130222/libmultipath/propsel.c
-@@ -744,6 +744,34 @@ select_retain_hwhandler (struct multipat
- }
-
- extern int
-+select_deferred_remove (struct multipath *mp)
-+{
-+ if (mp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) {
-+ condlog(3, "%s: deferred_remove in progress", mp->alias);
-+ return 0;
-+ }
-+ if (mp->mpe && mp->mpe->deferred_remove) {
-+ mp->deferred_remove = mp->mpe->deferred_remove;
-+ condlog(3, "%s: deferred_remove = %i (multipath setting)",
-+ mp->alias, mp->deferred_remove);
-+ return 0;
-+ }
-+ if (mp->hwe && mp->hwe->deferred_remove) {
-+ mp->deferred_remove = mp->hwe->deferred_remove;
-+ condlog(3, "%s: deferred_remove = %d (controller default)", mp->alias, mp->deferred_remove);
-+ return 0;
-+ }
-+ if (conf->deferred_remove) {
-+ mp->deferred_remove = conf->deferred_remove;
-+ condlog(3, "%s: deferred_remove = %d (config file default)", mp->alias, mp->deferred_remove);
-+ return 0;
-+ }
-+ mp->deferred_remove = DEFAULT_DEFERRED_REMOVE;
-+ condlog(3, "%s: deferred_remove = %d (compiled in default)", mp->alias, mp->deferred_remove);
-+ return 0;
-+}
-+
-+extern int
- select_detect_prio (struct path * pp)
- {
- if (pp->hwe && pp->hwe->detect_prio) {
-Index: multipath-tools-130222/libmultipath/propsel.h
-===================================================================
---- multipath-tools-130222.orig/libmultipath/propsel.h
-+++ multipath-tools-130222/libmultipath/propsel.h
-@@ -20,3 +20,4 @@ int select_dev_loss(struct multipath *mp
- int select_reservation_key(struct multipath *mp);
- int select_retain_hwhandler (struct multipath * mp);
- int select_detect_prio(struct path * pp);
-+int select_deferred_remove(struct multipath *mp);
-Index: multipath-tools-130222/libmultipath/structs.h
-===================================================================
---- multipath-tools-130222.orig/libmultipath/structs.h
-+++ multipath-tools-130222/libmultipath/structs.h
-@@ -114,6 +114,13 @@ enum detect_prio_states {
- DETECT_PRIO_ON,
- };
-
-+enum deferred_remove_states {
-+ DEFERRED_REMOVE_UNDEF,
-+ DEFERRED_REMOVE_OFF,
-+ DEFERRED_REMOVE_ON,
-+ DEFERRED_REMOVE_IN_PROGRESS,
-+};
-+
- enum scsi_protocol {
- SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
- SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
-@@ -207,6 +214,7 @@ struct multipath {
- int attribute_flags;
- int fast_io_fail;
- int retain_hwhandler;
-+ int deferred_remove;
- unsigned int dev_loss;
- uid_t uid;
- gid_t gid;
-Index: multipath-tools-130222/multipathd/main.c
-===================================================================
---- multipath-tools-130222.orig/multipathd/main.c
-+++ multipath-tools-130222/multipathd/main.c
-@@ -214,19 +214,30 @@ sync_maps_state(vector mpvec)
- }
-
- static int
--flush_map(struct multipath * mpp, struct vectors * vecs)
-+flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
- {
-+ int r;
-+
-+ if (nopaths)
-+ r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove);
-+ else
-+ r = dm_flush_map(mpp->alias);
- /*
- * clear references to this map before flushing so we can ignore
- * the spurious uevent we may generate with the dm_flush_map call below
- */
-- if (dm_flush_map(mpp->alias)) {
-+ if (r) {
- /*
- * May not really be an error -- if the map was already flushed
- * from the device mapper by dmsetup(8) for instance.
- */
-- condlog(0, "%s: can't flush", mpp->alias);
-- return 1;
-+ if (r == 1)
-+ condlog(0, "%s: can't flush", mpp->alias);
-+ else {
-+ condlog(2, "%s: devmap deferred remove", mpp->alias);
-+ mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS;
-+ }
-+ return r;
- }
- else {
- dm_lib_release();
-@@ -372,7 +383,7 @@ ev_remove_map (char * devname, char * al
- mpp->alias, mpp->dmi->minor, minor);
- return 0;
- }
-- return flush_map(mpp, vecs);
-+ return flush_map(mpp, vecs, 0);
- }
-
- static int
-@@ -628,7 +639,7 @@ ev_remove_path (struct path *pp, struct
- mpp->flush_on_last_del = FLUSH_IN_PROGRESS;
- dm_queue_if_no_path(mpp->alias, 0);
- }
-- if (!flush_map(mpp, vecs)) {
-+ if (!flush_map(mpp, vecs, 1)) {
- condlog(2, "%s: removed map after"
- " removing all paths",
- alias);
-Index: multipath-tools-130222/libmultipath/structs_vec.c
-===================================================================
---- multipath-tools-130222.orig/libmultipath/structs_vec.c
-+++ multipath-tools-130222/libmultipath/structs_vec.c
-@@ -392,6 +392,8 @@ __setup_multipath (struct vectors * vecs
- set_no_path_retry(mpp);
- select_pg_timeout(mpp);
- select_flush_on_last_del(mpp);
-+ if (VECTOR_SIZE(mpp->paths) != 0)
-+ dm_cancel_deferred_remove(mpp);
- }
-
- return 0;
-@@ -565,7 +567,6 @@ int update_multipath (struct vectors *ve
- }
- }
- }
--
- return 0;
- }
-
-Index: multipath-tools-130222/multipath/multipath.conf.5
-===================================================================
---- multipath-tools-130222.orig/multipath/multipath.conf.5
-+++ multipath-tools-130222/multipath/multipath.conf.5
-@@ -84,6 +84,28 @@ directory where the dynamic shared objec
- dependent, commonly
- .I /lib/multipath
- .TP
-+.B find_multipaths
-+If set to
-+.I yes
-+, instead of trying to create a multipath device for every non-blacklisted
-+path, multipath will only create a device if one of three condidions are
-+met.
-+.I 1
-+There are at least two non-blacklisted paths with the same wwid,
-+.I 2
-+the user manually forces the creation, by specifying a device with the multipath
-+command, or
-+.I 3
-+a path has the same WWID as a multipath device that was previously created
-+while find_multipaths was set (even if that multipath device doesn't currently
-+exist).
-+Whenever a multipath device is created with find_multipaths set, multipath will
-+remeber the WWID of the device, so that it will automatically create the
-+device again, as soon as it sees a path with that WWID. This should allow most
-+users to have multipath automatically choose the correct paths to make into
-+multipath devices, without having to edit the blacklist; Default is
-+.I no
-+.TP
- .B verbosity
- default verbosity. Higher values increase the verbosity level. Valid
- levels are between 0 and 6; default is
-@@ -420,6 +442,16 @@ only one checker will run at a time. Th
- multipathd checkers running in parallel causes significant CPU pressure. The
- Default is
- .I no
-+.TP
-+.B deferred_remove
-+If set to
-+.I yes
-+, multipathd will do a deferred remove instead of a regular remove when the
-+last path device has been deleted. This means that if the multipath device is
-+still in use, it will be freed when the last user closes it. If path is added
-+to the multipath device before the last user closes it, the deferred remove
-+will be canceled. Default is
-+.I no
- .
- .SH "blacklist section"
- The
-@@ -521,6 +553,8 @@ section:
- .B features
- .TP
- .B reservation_key
-+.TP
-+.B deferred_remove
- .RE
- .PD
- .LP
-@@ -611,6 +645,8 @@ section:
- .B retain_attached_hw_handler
- .TP
- .B detect_prio
-+.TP
-+.B deferred_remove
- .RE
- .PD
- .LP
-Index: multipath-tools-130222/libmultipath/Makefile
-===================================================================
---- multipath-tools-130222.orig/libmultipath/Makefile
-+++ multipath-tools-130222/libmultipath/Makefile
-@@ -36,6 +36,12 @@ ifneq ($(strip $(LIBUDEV_API_RECVBUF)),0
- CFLAGS += -DLIBUDEV_API_RECVBUF
- endif
-
-+LIBDM_API_DEFERRED = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_deferred_remove' /usr/include/libdevmapper.h)
-+
-+ifneq ($(strip $(LIBDM_API_DEFERRED)),0)
-+ CFLAGS += -DLIBDM_API_DEFERRED
-+endif
-+
-
- all: $(LIBS)
-