Blob Blame History Raw
---
 libmultipath/config.c    |    5 ++-
 libmultipath/config.h    |    4 +-
 libmultipath/configure.c |    7 +++-
 libmultipath/defaults.h  |    1 
 libmultipath/devmapper.c |   34 +++------------------
 libmultipath/devmapper.h |    8 ++++-
 libmultipath/dict.c      |   74 +++++++++++++++++++++++++++++++++++++++++++++++
 libmultipath/dmparser.c  |    3 +
 libmultipath/propsel.c   |   29 +++++++++++++++++-
 libmultipath/propsel.h   |    1 
 libmultipath/structs.h   |    7 ++++
 11 files changed, 138 insertions(+), 35 deletions(-)

Index: multipath-tools-120821/libmultipath/config.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/config.c
+++ multipath-tools-120821/libmultipath/config.c
@@ -327,6 +327,7 @@ merge_hwe (struct hwentry * dst, struct
 	merge_num(fast_io_fail);
 	merge_num(dev_loss);
 	merge_num(user_friendly_names);
+	merge_num(retain_hwhandler);
 
 	return 0;
 }
@@ -386,6 +387,7 @@ store_hwe (vector hwtable, struct hwentr
 	hwe->fast_io_fail = dhwe->fast_io_fail;
 	hwe->dev_loss = dhwe->dev_loss;
 	hwe->user_friendly_names = dhwe->user_friendly_names;
+	hwe->retain_hwhandler = dhwe->retain_hwhandler;
 
 	if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
 		goto out;
@@ -502,7 +504,7 @@ load_config (char * file)
 		conf->verbosity = DEFAULT_VERBOSITY;
 
 	conf->udev = udev_new();
-	conf->dmrq = dm_drv_get_rq();
+	dm_drv_version(conf->version, TGT_MPATH);
 	conf->dev_type = DEV_NONE;
 	conf->minio = DEFAULT_MINIO;
 	conf->minio_rq = DEFAULT_MINIO_RQ;
@@ -519,6 +521,7 @@ load_config (char * file)
 	conf->max_checkint = MAX_CHECKINT(conf->checkint);
 	conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
 	conf->fast_io_fail = 5;
+	conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
 
 	/*
 	 * preload default hwtable
Index: multipath-tools-120821/libmultipath/config.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/config.h
+++ multipath-tools-120821/libmultipath/config.h
@@ -46,6 +46,7 @@ struct hwentry {
 	int fast_io_fail;
 	unsigned int dev_loss;
 	int user_friendly_names;
+	int retain_hwhandler;
 	char * bl_product;
 };
 
@@ -75,7 +76,6 @@ struct mpentry {
 };
 
 struct config {
-	int dmrq;
 	int verbosity;
 	int dry_run;
 	int list;
@@ -110,6 +110,8 @@ struct config {
 	mode_t mode;
 	uint32_t cookie;
 	int reassign_maps;
+	int retain_hwhandler;
+	unsigned int version[3];
 
 	char * dev;
 	struct udev * udev;
Index: multipath-tools-120821/libmultipath/defaults.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/defaults.h
+++ multipath-tools-120821/libmultipath/defaults.h
@@ -16,6 +16,7 @@
 #define DEFAULT_VERBOSITY	2
 #define DEFAULT_REASSIGN_MAPS	1
 #define DEFAULT_FIND_MULTIPATHS 0
+#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
 
 #define DEFAULT_CHECKINT	5
 #define MAX_CHECKINT(a)		(a << 2)
Index: multipath-tools-120821/libmultipath/dict.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/dict.c
+++ multipath-tools-120821/libmultipath/dict.c
@@ -650,6 +650,29 @@ wwids_file_handler(vector strvec)
 	return 0;
 }
 
+static int
+def_retain_hwhandler_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->retain_hwhandler = RETAIN_HWHANDLER_OFF;
+	else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+		 (strlen(buff) == 1 && !strcmp(buff, "1")))
+		conf->retain_hwhandler = RETAIN_HWHANDLER_ON;
+	else
+		conf->retain_hwhandler = RETAIN_HWHANDLER_UNDEF;
+
+	FREE(buff);
+	return 0;
+}
+
 /*
  * blacklist block handlers
  */
@@ -1271,6 +1294,33 @@ hw_names_handler(vector strvec)
 	return 0;
 }
 
+static int
+hw_retain_hwhandler_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->retain_hwhandler = RETAIN_HWHANDLER_OFF;
+	else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+		 (strlen(buff) == 1 && !strcmp(buff, "1")))
+		hwe->retain_hwhandler = RETAIN_HWHANDLER_ON;
+	else
+		hwe->user_friendly_names = RETAIN_HWHANDLER_UNDEF;
+
+	FREE(buff);
+	return 0;
+}
+
 /*
  * multipaths block handlers
  */
@@ -2295,6 +2345,19 @@ snprint_hw_user_friendly_names (char * b
 }
 
 static int
+snprint_hw_retain_hwhandler_handler(char * buff, int len, void * data)
+{
+	struct hwentry * hwe = (struct hwentry *)data;
+
+	if (hwe->retain_hwhandler == RETAIN_HWHANDLER_ON)
+		return snprintf(buff, len, "yes");
+	else if (hwe->retain_hwhandler == RETAIN_HWHANDLER_OFF)
+		return snprintf(buff, len, "no");
+	else
+		return 0;
+}
+
+static int
 snprint_def_polling_interval (char * buff, int len, void * data)
 {
 	return snprintf(buff, len, "%i", conf->checkint);
@@ -2632,6 +2695,15 @@ snprint_def_reservation_key(char * buff,
 }
 
 static int
+snprint_def_retain_hwhandler_handler(char * buff, int len, void * data)
+{
+	if (conf->retain_hwhandler == RETAIN_HWHANDLER_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;
@@ -2696,6 +2768,7 @@ init_keywords(void)
 	install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
 	install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key);
 	install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
+	install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler);
 	__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);
@@ -2757,6 +2830,7 @@ init_keywords(void)
 	install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail);
 	install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss);
 	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_sublevel_end();
 
 	install_keyword_root("multipaths", &multipaths_handler);
Index: multipath-tools-120821/libmultipath/structs.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/structs.h
+++ multipath-tools-120821/libmultipath/structs.h
@@ -99,6 +99,12 @@ enum user_friendly_names_states {
 	USER_FRIENDLY_NAMES_ON,
 };
 
+enum retain_hwhandler_states {
+	RETAIN_HWHANDLER_UNDEF,
+	RETAIN_HWHANDLER_OFF,
+	RETAIN_HWHANDLER_ON,
+};
+
 struct scsi_idlun {
 	int dev_id;
 	int host_unique_id;
@@ -188,6 +194,7 @@ struct multipath {
 	int flush_on_last_del;
 	int attribute_flags;
 	int fast_io_fail;
+	int retain_hwhandler;
 	unsigned int dev_loss;
 	uid_t uid;
 	gid_t gid;
Index: multipath-tools-120821/libmultipath/configure.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/configure.c
+++ multipath-tools-120821/libmultipath/configure.c
@@ -76,6 +76,7 @@ setup_map (struct multipath * mpp, char
 	select_fast_io_fail(mpp);
 	select_dev_loss(mpp);
 	select_reservation_key(mpp);
+	select_retain_hwhandler(mpp);
 
 	sysfs_set_scsi_tmo(mpp);
 	/*
@@ -217,8 +218,10 @@ select_action (struct multipath * mpp, v
 			mpp->alias);
 		return;
 	}
-	if (!cmpp->selector || strncmp(cmpp->hwhandler, mpp->hwhandler,
-		    strlen(mpp->hwhandler))) {
+	if (mpp->retain_hwhandler != RETAIN_HWHANDLER_ON &&
+            (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
+	     strncmp(cmpp->hwhandler, mpp->hwhandler,
+		    strlen(mpp->hwhandler)))) {
 		mpp->action = ACT_RELOAD;
 		condlog(3, "%s: set ACT_RELOAD (hwhandler change)",
 			mpp->alias);
Index: multipath-tools-120821/libmultipath/dmparser.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/dmparser.c
+++ multipath-tools-120821/libmultipath/dmparser.c
@@ -56,6 +56,7 @@ assemble_map (struct multipath * mp, cha
 	int nr_priority_groups, initial_pg_nr;
 	char * p, * f;
 	char no_path_retry[] = "queue_if_no_path";
+	char retain_hwhandler[] = "retain_attached_hw_handler";
 	struct pathgroup * pgp;
 	struct path * pp;
 
@@ -81,6 +82,8 @@ assemble_map (struct multipath * mp, cha
 	} else {
 		add_feature(&f, no_path_retry);
 	}
+	if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON)
+		add_feature(&f, retain_hwhandler);
 
 	shift = snprintf(p, freechar, "%s %s %i %i",
 			 f, mp->hwhandler,
Index: multipath-tools-120821/libmultipath/propsel.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/propsel.c
+++ multipath-tools-120821/libmultipath/propsel.c
@@ -513,7 +513,9 @@ select_minio_bio (struct multipath * mp)
 extern int
 select_minio (struct multipath * mp)
 {
-	if (conf->dmrq)
+	unsigned int minv_dmrq[3] = {1, 1, 0};
+
+	if (VERSION_GE(conf->version, minv_dmrq))
 		return select_minio_rq(mp);
 	else
 		return select_minio_bio(mp);
@@ -674,3 +676,28 @@ select_reservation_key (struct multipath
 	return 0;
 }
 
+extern int
+select_retain_hwhandler (struct multipath * mp)
+{
+	unsigned int minv_dm_retain[3] = {1, 5, 0};
+
+	if (!VERSION_GE(conf->version, minv_dm_retain)) {
+		mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
+		condlog(3, "%s: retain_attached_hw_hander disabled (requires kernel version >= 1.5.0)", mp->alias);
+		return 0;
+	}
+
+	if (mp->hwe && mp->hwe->retain_hwhandler) {
+		mp->retain_hwhandler = mp->hwe->retain_hwhandler;
+		condlog(3, "%s: retain_attached_hw_handler = %d (controller default)", mp->alias, mp->retain_hwhandler);
+		return 0;
+	}
+	if (conf->retain_hwhandler) {
+		mp->retain_hwhandler = conf->retain_hwhandler;
+		condlog(3, "%s: retain_attached_hw_handler = %d (config file default)", mp->alias, mp->retain_hwhandler);
+		return 0;
+	}
+	mp->retain_hwhandler = 0;
+	condlog(3, "%s: retain_attached_hw_handler = %d (compiled in default)", mp->alias, mp->retain_hwhandler);
+	return 0;
+}
Index: multipath-tools-120821/libmultipath/propsel.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/propsel.h
+++ multipath-tools-120821/libmultipath/propsel.h
@@ -18,3 +18,4 @@ int select_gid(struct multipath *mp);
 int select_fast_io_fail(struct multipath *mp);
 int select_dev_loss(struct multipath *mp);
 int select_reservation_key(struct multipath *mp);
+int select_retain_hwhandler (struct multipath * mp);
Index: multipath-tools-120821/libmultipath/devmapper.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/devmapper.c
+++ multipath-tools-120821/libmultipath/devmapper.c
@@ -98,12 +98,6 @@ dm_init(void) {
 	dm_log_init_verbose(conf ? conf->verbosity + 3 : 0);
 }
 
-#define VERSION_GE(v, minv) ( \
- (v[0] > minv[0]) || \
- ((v[0] == minv[0]) && (v[1] > minv[1])) || \
- ((v[0] == minv[0]) && (v[1] == minv[1]) && (v[2] >= minv[2])) \
-)
-
 static int
 dm_lib_prereq (void)
 {
@@ -126,7 +120,7 @@ dm_lib_prereq (void)
 	return 1;
 }
 
-static int
+int
 dm_drv_version (unsigned int * version, char * str)
 {
 	int r = 2;
@@ -135,6 +129,10 @@ dm_drv_version (unsigned int * version,
 	struct dm_versions *last_target;
 	unsigned int *v;
 
+	version[0] = 0;
+	version[1] = 0;
+	version[2] = 0;
+
 	if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
 		return 1;
 
@@ -169,28 +167,6 @@ out:
 	return r;
 }
 
-int
-dm_drv_get_rq (void)
-{
-	unsigned int minv_dmrq[3] = {1, 1, 0};
-	unsigned int version[3] = {0, 0, 0};
-        unsigned int * v = version;
-
-	if (dm_drv_version(v, TGT_MPATH)) {
-		/* in doubt return least capable */
-		return 0;
-	}
-
-	/* test request based multipath capability */
-	if VERSION_GE(v, minv_dmrq) {
-		condlog(3, "activate request-based multipathing mode "
-			   "(driver >= v%u.%u.%u)",
-			minv_dmrq[0], minv_dmrq[1], minv_dmrq[2]);
-		return 1;
-	}
-	return 0;
-}
-
 static int
 dm_drv_prereq (void)
 {
Index: multipath-tools-120821/libmultipath/devmapper.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/devmapper.h
+++ multipath-tools-120821/libmultipath/devmapper.h
@@ -8,7 +8,7 @@
 
 void dm_init(void);
 int dm_prereq (void);
-int dm_drv_get_rq (void);
+int dm_drv_version (unsigned int * version, char * str);
 int dm_simplecmd_flush (int, const char *, int);
 int dm_simplecmd_noflush (int, const char *);
 int dm_addmap_create (struct multipath *mpp, char *params);
@@ -46,4 +46,10 @@ int dm_setgeometry(struct multipath *mpp
 void udev_wait(unsigned int c);
 void udev_set_sync_support(int c);
 
+#define VERSION_GE(v, minv) ( \
+ (v[0] > minv[0]) || \
+ ((v[0] == minv[0]) && (v[1] > minv[1])) || \
+ ((v[0] == minv[0]) && (v[1] == minv[1]) && (v[2] >= minv[2])) \
+)
+
 #endif /* _DEVMAPPER_H */