merge_num(fast_io_fail);
merge_num(dev_loss);
merge_num(user_friendly_names);
+ merge_num(retain_hwhandler);
return 0;
}
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;
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;
conf->checkint = DEFAULT_CHECKINT;
conf->max_checkint = MAX_CHECKINT(conf->checkint);
conf->fast_io_fail = DEFAULT_FAST_IO_FAIL;
+ conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
/*
* preload default hwtable
int fast_io_fail;
unsigned int dev_loss;
int user_friendly_names;
+ int retain_hwhandler;
char * bl_product;
};
};
struct config {
- int dmrq;
int verbosity;
int dry_run;
int list;
mode_t mode;
uint32_t cookie;
int reassign_maps;
+ int retain_hwhandler;
+ unsigned int version[3];
char * dev;
struct udev * udev;
select_fast_io_fail(mpp);
select_dev_loss(mpp);
select_reservation_key(mpp);
+ select_retain_hwhandler(mpp);
sysfs_set_scsi_tmo(mpp);
/*
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);
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 1
#define DEFAULT_FAST_IO_FAIL 5
+#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
#define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2)
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)
{
return 1;
}
-static int
+int
dm_drv_version (unsigned int * version, char * str)
{
int r = 2;
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;
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)
{
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);
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 */
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
*/
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
*/
return snprintf(buff, len, "yes");
}
+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, "%s", conf->reservation_key);
}
+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)
{
install_keyword("wwids_file", &wwids_file_handler, &snprint_def_wwids_file);
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("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);
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);
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;
} 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,
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);
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;
+}
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);
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;
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;