--- libmultipath/config.c | 3 + libmultipath/config.h | 3 + libmultipath/configure.c | 15 +++-- libmultipath/defaults.h | 1 libmultipath/devmapper.c | 35 +++++++++---- libmultipath/devmapper.h | 8 ++- libmultipath/dict.c | 114 +++++++++++++++++++++++++++++++++++++++++++++ libmultipath/propsel.c | 26 ++++++++++ libmultipath/propsel.h | 1 libmultipath/structs.h | 7 ++ multipath/multipath.conf.5 | 10 +++ multipath/multipath.rules | 1 multipathd/cli_handlers.c | 4 + 13 files changed, 211 insertions(+), 17 deletions(-) Index: multipath-tools-130222/libmultipath/config.c =================================================================== --- multipath-tools-130222.orig/libmultipath/config.c +++ multipath-tools-130222/libmultipath/config.c @@ -343,6 +343,7 @@ merge_hwe (struct hwentry * dst, struct merge_num(deferred_remove); merge_num(delay_watch_checks); merge_num(delay_wait_checks); + merge_num(skip_kpartx); /* * Make sure features is consistent with @@ -403,6 +404,7 @@ overwrite_hwe (struct hwentry * dst, str overwrite_num(deferred_remove); overwrite_num(delay_watch_checks); overwrite_num(delay_wait_checks); + overwrite_num(skip_kpartx); /* * Make sure features is consistent with @@ -677,6 +679,7 @@ load_config (char * file, struct udev *u conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; conf->new_bindings_in_boot = 0; conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT; + conf->skip_kpartx = DEFAULT_SKIP_KPARTX; /* * preload default hwtable Index: multipath-tools-130222/libmultipath/config.h =================================================================== --- multipath-tools-130222.orig/libmultipath/config.h +++ multipath-tools-130222/libmultipath/config.h @@ -64,6 +64,7 @@ struct hwentry { int deferred_remove; int delay_watch_checks; int delay_wait_checks; + int skip_kpartx; char * bl_product; }; @@ -90,6 +91,7 @@ struct mpentry { int deferred_remove; int delay_watch_checks; int delay_wait_checks; + int skip_kpartx; uid_t uid; gid_t gid; mode_t mode; @@ -143,6 +145,7 @@ struct config { int new_bindings_in_boot; int delayed_reconfig; int uev_wait_timeout; + int skip_kpartx; 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 @@ -294,6 +294,7 @@ setup_map (struct multipath * mpp, char select_deferred_remove(mpp); select_delay_watch_checks(mpp); select_delay_wait_checks(mpp); + select_skip_kpartx(mpp); sysfs_set_scsi_tmo(mpp); /* @@ -446,6 +447,7 @@ select_action (struct multipath * mpp, v } mpp->force_udev_reload = !pathcount(mpp, PATH_WILD); if (cmpp->size != mpp->size) { + mpp->force_udev_reload = 1; mpp->action = ACT_RESIZE; condlog(3, "%s: set ACT_RESIZE (size change)", mpp->alias); @@ -609,6 +611,7 @@ extern int domap (struct multipath * mpp, char * params) { int r = 0; + uint16_t udev_flags = ((mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG) | ((mpp->skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); /* * last chance to quit before touching the devmaps @@ -654,25 +657,27 @@ domap (struct multipath * mpp, char * pa case ACT_RELOAD: r = dm_addmap_reload(mpp, params); if (r) - r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG); + r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, + udev_flags); break; case ACT_RESIZE: r = dm_addmap_reload(mpp, params); if (r) - r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, 0); + r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, + udev_flags); break; case ACT_RENAME: - r = dm_rename(mpp->alias_old, mpp->alias); + r = dm_rename(mpp->alias_old, mpp->alias, mpp->skip_kpartx); break; case ACT_RENAME2: - r = dm_rename(mpp->alias_old, mpp->alias); + r = dm_rename(mpp->alias_old, mpp->alias, mpp->skip_kpartx); if (r) { r = dm_addmap_reload(mpp, params); if (r) - r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG); + r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, udev_flags); } break; Index: multipath-tools-130222/libmultipath/defaults.h =================================================================== --- multipath-tools-130222.orig/libmultipath/defaults.h +++ multipath-tools-130222/libmultipath/defaults.h @@ -24,6 +24,7 @@ #define DEFAULT_RETRIGGER_DELAY 10 #define DEFAULT_RETRIGGER_TRIES 3 #define DEFAULT_UEV_WAIT_TIMEOUT 30 +#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_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 @@ -262,13 +262,14 @@ dm_device_remove (const char *name, int deferred_remove); } -extern int +static int dm_addmap (int task, const char *target, struct multipath *mpp, char * params, - int use_uuid, int ro) { + int use_uuid, int ro, int skip_kpartx) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; uint32_t cookie = 0; + uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); if (!(dmt = dm_task_create (task))) return 0; @@ -309,7 +310,7 @@ dm_addmap (int task, const char *target, dm_task_no_open_count(dmt); if (task == DM_DEVICE_CREATE && - !dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) + !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto freeout; r = dm_task_run (dmt); @@ -332,7 +333,8 @@ dm_addmap_create (struct multipath *mpp, for (ro = 0; ro <= 1; ro++) { int err; - if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, 1, ro)) + if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, + mpp, params, 1, ro, mpp->skip_kpartx)) return 1; /* * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD. @@ -354,11 +356,11 @@ dm_addmap_create (struct multipath *mpp, extern int dm_addmap_reload (struct multipath *mpp, char *params) { - if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW)) + if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW, SKIP_KPARTX_OFF)) return 1; if (errno != EROFS) return 0; - return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO); + return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO, SKIP_KPARTX_OFF); } extern int @@ -720,6 +722,12 @@ out: } static int +has_partmap(const char *name, void *data) +{ + return 1; +} + +static int partmap_in_use(const char *name, void *data) { int part_count, *ret_count = (int *)data; @@ -798,10 +806,16 @@ dm_suspend_and_flush_map (const char * m int s = 0, queue_if_no_path = 0; unsigned long long mapsize; char params[PARAMS_SIZE] = {0}; + int udev_flags = 0; if (!dm_is_mpath(mapname)) return 0; /* nothing to do */ + /* if the device currently has no partitions, do not + run kpartx on it if you fail to delete it */ + if (do_foreach_partmaps(mapname, has_partmap, NULL) == 0) + udev_flags |= MPATH_UDEV_NO_KPARTX_FLAG; + if (!dm_get_map(mapname, &mapsize, params)) { if (strstr(params, "queue_if_no_path")) queue_if_no_path = 1; @@ -820,7 +834,7 @@ dm_suspend_and_flush_map (const char * m return 0; } condlog(2, "failed to remove multipath map %s", mapname); - dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0); + dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, udev_flags); if (queue_if_no_path) s = dm_queue_if_no_path((char *)mapname, 1); return 1; @@ -1349,7 +1363,7 @@ rename_partmap (const char *name, void * 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); + dm_rename(name, buff, SKIP_KPARTX_OFF); condlog(4, "partition map %s renamed", name); return 0; } @@ -1369,11 +1383,12 @@ dm_rename_partmaps (const char * old, ch } int -dm_rename (const char * old, char * new) +dm_rename (const char * old, char * new, int skip_kpartx) { int r = 0; struct dm_task *dmt; uint32_t cookie; + uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); if (dm_rename_partmaps(old, new)) return r; @@ -1389,7 +1404,7 @@ dm_rename (const char * old, char * new) dm_task_no_open_count(dmt); - if (!dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) + if (!dm_task_set_cookie(dmt, &cookie, udev_flags)) goto out; r = dm_task_run(dmt); Index: multipath-tools-130222/libmultipath/devmapper.h =================================================================== --- multipath-tools-130222.orig/libmultipath/devmapper.h +++ multipath-tools-130222/libmultipath/devmapper.h @@ -12,6 +12,12 @@ #define MPATH_UDEV_RELOAD_FLAG 0 #endif +#ifdef DM_SUBSYSTEM_UDEV_FLAG1 +#define MPATH_UDEV_NO_KPARTX_FLAG DM_SUBSYSTEM_UDEV_FLAG1 +#else +#define MPATH_UDEV_NO_KPARTX_FLAG 0 +#endif + void dm_init(void); int dm_prereq (void); int dm_drv_version (unsigned int * version, char * str); @@ -47,7 +53,7 @@ int dm_remove_partmaps (const char * map int deferred_remove); int dm_get_uuid(char *name, char *uuid); int dm_get_info (char * mapname, struct dm_info ** dmi); -int dm_rename (const char * old, char * new); +int dm_rename (const char * old, char * new, int skip_kpartx); int dm_reassign(const char * mapname); int dm_reassign_table(const char *name, char *old, char *new); int dm_setgeometry(struct multipath *mpp); Index: multipath-tools-130222/libmultipath/dict.c =================================================================== --- multipath-tools-130222.orig/libmultipath/dict.c +++ multipath-tools-130222/libmultipath/dict.c @@ -779,6 +779,29 @@ def_deferred_remove_handler(vector strve } static int +def_skip_kpartx_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->skip_kpartx = SKIP_KPARTX_OFF; + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || + (strlen(buff) == 1 && !strcmp(buff, "1"))) + conf->skip_kpartx = SKIP_KPARTX_ON; + else + conf->skip_kpartx = DEFAULT_SKIP_KPARTX; + + FREE(buff); + return 0; +} + +static int def_ignore_new_boot_devs_handler(vector strvec) { char * buff; @@ -1629,6 +1652,33 @@ hw_deferred_remove_handler(vector strvec } static int +hw_skip_kpartx_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->skip_kpartx = SKIP_KPARTX_OFF; + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || + (strlen(buff) == 1 && !strcmp(buff, "1"))) + hwe->skip_kpartx = SKIP_KPARTX_ON; + else + hwe->skip_kpartx = SKIP_KPARTX_UNDEF; + + FREE(buff); + return 0; +} + +static int hw_delay_watch_checks_handler(vector strvec) { struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); @@ -2154,6 +2204,32 @@ mp_deferred_remove_handler(vector strvec } static int +mp_skip_kpartx_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->skip_kpartx = SKIP_KPARTX_OFF; + else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) || + (strlen(buff) == 1 && strcmp(buff, "1") == 0)) + mpe->skip_kpartx = SKIP_KPARTX_ON; + else + mpe->skip_kpartx = SKIP_KPARTX_UNDEF; + + FREE(buff); + return 0; +} + +static int mp_delay_watch_checks_handler(vector strvec) { struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); @@ -2461,6 +2537,19 @@ snprint_mp_deferred_remove (char * buff, } static int +snprint_mp_skip_kpartx (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (mpe->skip_kpartx == SKIP_KPARTX_UNDEF) + return 0; + else if (mpe->skip_kpartx == SKIP_KPARTX_OFF) + return snprintf(buff, len, "no"); + else + return snprintf(buff, len, "yes"); +} + +static int snprint_mp_delay_watch_checks(char * buff, int len, void * data) { struct mpentry * mpe = (struct mpentry *)data; @@ -2813,6 +2902,19 @@ snprint_hw_deferred_remove(char * buff, } static int +snprint_hw_skip_kpartx(char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (hwe->skip_kpartx == SKIP_KPARTX_ON) + return snprintf(buff, len, "yes"); + else if (hwe->skip_kpartx == SKIP_KPARTX_OFF) + return snprintf(buff, len, "no"); + else + return 0; +} + +static int snprint_hw_delay_watch_checks(char * buff, int len, void * data) { struct hwentry * hwe = (struct hwentry *)data; @@ -3231,6 +3333,15 @@ snprint_def_deferred_remove(char * buff, } static int +snprint_def_skip_kpartx(char * buff, int len, void * data) +{ + if (conf->skip_kpartx == SKIP_KPARTX_ON) + return snprintf(buff, len, "yes"); + else + return snprintf(buff, len, "no"); +} + +static int snprint_def_ignore_new_boot_devs(char * buff, int len, void * data) { if (conf->ignore_new_boot_devs == 1) @@ -3364,6 +3475,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("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs); + install_keyword("skip_kpartx", &def_skip_kpartx_handler, &snprint_def_skip_kpartx); 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); @@ -3438,6 +3550,7 @@ init_keywords(void) 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_keyword("skip_kpartx", &hw_skip_kpartx_handler, &snprint_hw_skip_kpartx); install_sublevel_end(); install_keyword_root("multipaths", &multipaths_handler); @@ -3465,5 +3578,6 @@ init_keywords(void) 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_keyword("skip_kpartx", &mp_skip_kpartx_handler, &snprint_mp_skip_kpartx); install_sublevel_end(); } Index: multipath-tools-130222/libmultipath/propsel.c =================================================================== --- multipath-tools-130222.orig/libmultipath/propsel.c +++ multipath-tools-130222/libmultipath/propsel.c @@ -854,3 +854,29 @@ select_delay_wait_checks (struct multipa condlog(3, "delay_wait_checks = DISABLED (internal default)"); return 0; } + +extern int +select_skip_kpartx (struct multipath * mp) +{ + if (mp->mpe && mp->mpe->skip_kpartx != SKIP_KPARTX_UNDEF) { + mp->skip_kpartx = mp->mpe->skip_kpartx; + condlog(3, "skip_kpartx = %i (multipath setting)", + mp->skip_kpartx); + return 0; + } + if (mp->hwe && mp->hwe->skip_kpartx != SKIP_KPARTX_UNDEF) { + mp->skip_kpartx = mp->hwe->skip_kpartx; + condlog(3, "skip_kpartx = %i (controler setting)", + mp->skip_kpartx); + return 0; + } + if (conf->skip_kpartx != SKIP_KPARTX_UNDEF) { + mp->skip_kpartx = conf->skip_kpartx; + condlog(3, "skip_kpartx = %i (config file default)", + mp->skip_kpartx); + return 0; + } + mp->skip_kpartx = DEFAULT_SKIP_KPARTX; + condlog(3, "skip_kpartx = DISABLED (internal default)"); + return 0; +} Index: multipath-tools-130222/libmultipath/propsel.h =================================================================== --- multipath-tools-130222.orig/libmultipath/propsel.h +++ multipath-tools-130222/libmultipath/propsel.h @@ -23,3 +23,4 @@ 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); +int select_skip_kpartx (struct multipath * mp); Index: multipath-tools-130222/libmultipath/structs.h =================================================================== --- multipath-tools-130222.orig/libmultipath/structs.h +++ multipath-tools-130222/libmultipath/structs.h @@ -121,6 +121,12 @@ enum deferred_remove_states { DEFERRED_REMOVE_IN_PROGRESS, }; +enum skip_kpartx_states { + SKIP_KPARTX_UNDEF, + SKIP_KPARTX_OFF, + SKIP_KPARTX_ON, +}; + enum scsi_protocol { SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ @@ -236,6 +242,7 @@ struct multipath { int delay_watch_checks; int delay_wait_checks; int force_udev_reload; + int skip_kpartx; unsigned int dev_loss; uid_t uid; gid_t gid; Index: multipath-tools-130222/multipath/multipath.rules =================================================================== --- multipath-tools-130222.orig/multipath/multipath.rules +++ multipath-tools-130222/multipath/multipath.rules @@ -44,6 +44,7 @@ KERNEL!="dm-*", GOTO="end_mpath" ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10" ACTION!="change", GOTO="end_mpath" ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath" +ENV{DM_SUBSYSTEM_UDEV_FLAG1}=="1", GOTO="end_mpath" ENV{DM_ACTIVATION}=="1", ENV{DM_MULTIPATH_NEED_KPARTX}="1" ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" Index: multipath-tools-130222/multipathd/cli_handlers.c =================================================================== --- multipath-tools-130222.orig/multipathd/cli_handlers.c +++ multipath-tools-130222/multipathd/cli_handlers.c @@ -825,19 +825,21 @@ cli_resume(void * v, char ** reply, int char * param = get_keyparam(v, MAP); int r; struct multipath * mpp; + uint16_t udev_flags; param = convert_dev(param, 0); mpp = find_mp_by_alias(vecs->mpvec, param); if (!mpp) return 1; + udev_flags = (mpp->skip_kpartx)? MPATH_UDEV_NO_KPARTX_FLAG : 0; if (mpp->wait_for_udev) { condlog(2, "%s: device not fully created, failing resume", mpp->alias); return 1; } - r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); + r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, udev_flags); condlog(2, "%s: resume (operator)", param); Index: multipath-tools-130222/multipath/multipath.conf.5 =================================================================== --- multipath-tools-130222.orig/multipath/multipath.conf.5 +++ multipath-tools-130222/multipath/multipath.conf.5 @@ -505,6 +505,12 @@ automatically enabling device reloads. U on a device until it receives a change uevent from the initial table load. The default is .I 30 +.TP +.B skip_kpartx +If set to +.I yes +, kpartx will not automatically create partitions on the device. The default is +.I no . .SH "blacklist section" The @@ -612,6 +618,8 @@ section: .B delay_watch_checks .TP .B delay_wait_checks +.TP +.B skip_kpartx .RE .PD .LP @@ -708,6 +716,8 @@ section: .B delay_watch_checks .TP .B delay_wait_checks +.TP +.B skip_kpartx .RE .PD .LP