device-mapper-multipath-0.4.9-86

Modify 0136-RHBZ-1304687-wait-for-map-add.patch
  * switch to missing_uev_wait_timeout to stop waiting for uev
Refresh 0137-RHBZ-1280524-clear-chkr-msg.patch
Refresh 0150-RHBZ-1253913-fix-startup-msg.patch
Refresh 0154-UPBZ-1291406-disable-reinstate.patch
Refresh 0156-UPBZ-1313324-dont-fail-discovery.patch
Refresh 0161-RHBZ-1311659-no-kpartx.patch
Refresh 0167-RHBZ-1335176-fix-show-cmds.patch
Add 0173-RH-update-man-page.patch
Add 0174-RHBZ-1362396-modprobe.patch
  * make starting the multipathd service modprobe dm-multipath in the
    sysvinit scripts
Add 0175-RHBZ-1357382-ordering.patch
  * force multipathd.service to start after systemd-udev-trigger.service
Add 0176-RHBZ-1363830-fix-rename.patch
  * initialized a variable to make dm_rename not fail randomly
Add 0177-libmultipath-correctly-initialize-pp-sg_id.patch
  * This and all the following patches add the rbd patch checker
Add 0178-libmultipath-add-rbd-discovery.patch
Add 0179-multipath-tools-add-checker-callout-to-repair-path.patch
Add 0180-multipath-tools-Add-rbd-checker.patch
Add 0181-multipath-tools-Add-rbd-to-the-hwtable.patch
Add 0182-multipath-tools-check-for-initialized-checker-before.patch
Add 0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch
Add 0184-rbd-fix-sync-repair-support.patch
Add 0185-rbd-check-for-nonshared-clients.patch
Add 0186-rbd-check-for-exclusive-lock-enabled.patch
Add 0187-rbd-fixup-log-messages.patch
Add 0188-RHBZ-1368501-dont-exit.patch
  * make multipathd not exit if it encounters recoverable errors on startup
Add 0189-RHBZ-1368211-remove-retries.patch
  * add "remove_retries" multipath.conf parameter to make multiple attempts
    to remove a multipath device if it is busy.
Add 0190-RHBZ-1380602-rbd-lock-on-read.patch
  * pass lock_on_read when remapping image
Add 0191-RHBZ-1169168-disable-changed-paths.patch
  * add "disabled_changed_wwids" multipath.conf parameter to disable
    paths whose wwid changes
Add 0192-RHBZ-1362409-infinibox-config.patch
Add 0194-RHBZ-1351964-kpartx-recurse.patch
  * fix recursion on corrupt dos partitions
Add 0195-RHBZ-1359510-no-daemon-msg.patch
  * print a messages when multipathd isn't running
Add 0196-RHBZ-1239173-dont-set-flag.patch
  * don't set reload flag on reloads when you gain your first
    valid path
Add 0197-RHBZ-1394059-max-sectors-kb.patch
  * add "max_sectors_kb" multipath.conf parameter to set max_sectors_kb
    on a multipath device and all its path devices
Add 0198-RHBZ-1372032-detect-path-checker.patch
  * add "detect_checker" multipath.conf parameter to detect ALUA arrays
    and set the path checker to TUR
Add 0199-RHBZ-1279355-3pardata-config.patch
Add 0200-RHBZ-1402092-orphan-status.patch
  * clear status on orphan paths
Add 0201-RHBZ-1403552-silence-warning.patch
Add 0202-RHBZ-1362120-skip-prio.patch
  * don't run prio on failed paths
Add 0203-RHBZ-1363718-add-msgs.patch
Add 0204-RHBZ-1406226-nimble-config.patch
Add 0205-RHBZ-1416569-reset-stats.patch
  * add "reset maps stats" and "reset map <map> stats" multipathd
    interactive commands to reset the stats tracked by multipathd
Add 0206-RHBZ-1239173-pt2-no-paths.patch
  * make multipath correctly disable scanning and rules running when
    it gets a uevent and there are not valid paths.
Add 0207-UP-add-libmpathcmd.patch
  * New shared library, libmpathcmd, that sends and receives messages from
    multipathd. device-mapper-multipath now uses this library internally.
Add 0208-UPBZ-1430097-multipathd-IPC-changes.patch
  * validation that modifying commands are coming from root.
Add 0209-UPBZ-1430097-multipath-C-API.patch
  * New shared library. libdmmp, that presents the information from multipathd
    in a structured manner to make it easier for callers to use
Add 0210-RH-fix-uninstall.patch
  * Minor compilation fixes
Add 0211-RH-strlen-fix.patch
  * checks that variables are not NULL before passing them to strlen
Add 0212-RHBZ-1431562-for-read-only.patch
Make 3 new subpackages
  * device-mapper-multipath-devel, libdmmp, and libdmmp-devel. libmpathcmd
    and libmpathprio are in device-mapper-multipath-libs and
    device-mapper-multipath-devel. libdmmp is in its own subpackages
Move libmpathprio devel files to device-mapper-multipath-devel
Added BuildRequires on librados2-devel
This commit is contained in:
Benjamin Marzinski 2017-04-10 18:57:22 -04:00
parent 8e9e3b7467
commit f9dfbb37ac
49 changed files with 11253 additions and 75 deletions

View File

@ -3,14 +3,14 @@
libmultipath/config.h | 2 libmultipath/config.h | 2
libmultipath/configure.c | 4 + libmultipath/configure.c | 4 +
libmultipath/defaults.h | 1 libmultipath/defaults.h | 1
libmultipath/dict.c | 25 +++++++++ libmultipath/dict.c | 25 ++++++++
libmultipath/structs.h | 2 libmultipath/structs.h | 2
multipath.conf.defaults | 1 multipath.conf.defaults | 1
multipath/multipath.conf.5 | 8 +++ multipath/multipath.conf.5 | 8 ++
multipathd/cli_handlers.c | 65 ++++++++++++++++++++---- multipathd/cli_handlers.c | 65 ++++++++++++++++++----
multipathd/main.c | 119 +++++++++++++++++++++++++++++++++++++++++++-- multipathd/main.c | 132 +++++++++++++++++++++++++++++++++++++++++++--
multipathd/main.h | 1 multipathd/main.h | 1
11 files changed, 216 insertions(+), 13 deletions(-) 11 files changed, 229 insertions(+), 13 deletions(-)
Index: multipath-tools-130222/libmultipath/configure.c Index: multipath-tools-130222/libmultipath/configure.c
=================================================================== ===================================================================
@ -22,7 +22,7 @@ Index: multipath-tools-130222/libmultipath/configure.c
mpp->action = ACT_NOTHING; mpp->action = ACT_NOTHING;
+ else { + else {
+ mpp->wait_for_udev = 1; + mpp->wait_for_udev = 1;
+ mpp->uev_msg_tick = conf->uev_msg_delay; + mpp->uev_wait_tick = conf->uev_wait_timeout;
+ } + }
} }
dm_setgeometry(mpp); dm_setgeometry(mpp);
@ -36,7 +36,7 @@ Index: multipath-tools-130222/libmultipath/structs.h
int queuedio; int queuedio;
int action; int action;
+ int wait_for_udev; + int wait_for_udev;
+ int uev_msg_tick; + int uev_wait_tick;
int pgfailback; int pgfailback;
int failback_tick; int failback_tick;
int rr_weight; int rr_weight;
@ -175,7 +175,7 @@ Index: multipath-tools-130222/libmultipath/config.h
int retrigger_delay; int retrigger_delay;
int new_bindings_in_boot; int new_bindings_in_boot;
+ int delayed_reconfig; + int delayed_reconfig;
+ int uev_msg_delay; + int uev_wait_timeout;
unsigned int version[3]; unsigned int version[3];
char * dev; char * dev;
@ -293,20 +293,33 @@ Index: multipath-tools-130222/multipathd/main.c
retval = reload_map(vecs, pp->mpp, 0); retval = reload_map(vecs, pp->mpp, 0);
condlog(2, "%s: map %s reloaded (retval %d)", condlog(2, "%s: map %s reloaded (retval %d)",
@@ -1063,6 +1136,20 @@ followover_should_failback(struct path * @@ -1063,6 +1136,33 @@ followover_should_failback(struct path *
} }
static void static void
+missing_uev_message_tick(vector mpvec) +missing_uev_wait_tick(struct vectors *vecs)
+{ +{
+ struct multipath * mpp; + struct multipath * mpp;
+ unsigned int i; + unsigned int i;
+ int timed_out = 0;
+ +
+ vector_foreach_slot (mpvec, mpp, i) { + vector_foreach_slot (vecs->mpvec, mpp, i) {
+ if (mpp->wait_for_udev && --mpp->uev_msg_tick <= 0) { + if (mpp->wait_for_udev && --mpp->uev_wait_tick <= 0) {
+ condlog(0, "%s: startup incomplete. Still waiting on udev", mpp->alias); + timed_out = 1;
+ mpp->uev_msg_tick = conf->uev_msg_delay; + condlog(0, "%s: timeout waiting on creation uevent. enabling reloads", mpp->alias);
+ if (mpp->wait_for_udev > 1 && update_map(mpp, vecs)) {
+ /* update_map removed map */
+ i--;
+ continue;
+ } + }
+ mpp->wait_for_udev = 0;
+ }
+ }
+
+ if (timed_out && conf->delayed_reconfig &&
+ !need_to_delay_reconfig(vecs)) {
+ condlog(2, "reconfigure (delayed)");
+ reconfigure(vecs);
+ } + }
+} +}
+ +
@ -314,7 +327,7 @@ Index: multipath-tools-130222/multipathd/main.c
defered_failback_tick (vector mpvec) defered_failback_tick (vector mpvec)
{ {
struct multipath * mpp; struct multipath * mpp;
@@ -1316,6 +1403,9 @@ check_path (struct vectors * vecs, struc @@ -1316,6 +1416,9 @@ check_path (struct vectors * vecs, struc
pp->state = newstate; pp->state = newstate;
@ -324,15 +337,15 @@ Index: multipath-tools-130222/multipathd/main.c
/* /*
* path prio refreshing * path prio refreshing
*/ */
@@ -1369,6 +1459,7 @@ checkerloop (void *ap) @@ -1369,6 +1472,7 @@ checkerloop (void *ap)
if (vecs->mpvec) { if (vecs->mpvec) {
defered_failback_tick(vecs->mpvec); defered_failback_tick(vecs->mpvec);
retry_count_tick(vecs->mpvec); retry_count_tick(vecs->mpvec);
+ missing_uev_message_tick(vecs->mpvec); + missing_uev_wait_tick(vecs);
} }
if (count) if (count)
count--; count--;
@@ -1465,6 +1556,22 @@ configure (struct vectors * vecs, int st @@ -1465,6 +1569,22 @@ configure (struct vectors * vecs, int st
} }
int int
@ -355,7 +368,7 @@ Index: multipath-tools-130222/multipathd/main.c
reconfigure (struct vectors * vecs) reconfigure (struct vectors * vecs)
{ {
struct config * old = conf; struct config * old = conf;
@@ -1544,12 +1651,18 @@ void @@ -1544,12 +1664,18 @@ void
handle_signals(void) handle_signals(void)
{ {
if (reconfig_sig && running_state == DAEMON_RUNNING) { if (reconfig_sig && running_state == DAEMON_RUNNING) {
@ -396,7 +409,7 @@ Index: multipath-tools-130222/libmultipath/config.c
conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES;
conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
conf->new_bindings_in_boot = 0; conf->new_bindings_in_boot = 0;
+ conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY; + conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
/* /*
* preload default hwtable * preload default hwtable
@ -408,7 +421,7 @@ Index: multipath-tools-130222/libmultipath/defaults.h
#define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF #define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF
#define DEFAULT_RETRIGGER_DELAY 10 #define DEFAULT_RETRIGGER_DELAY 10
#define DEFAULT_RETRIGGER_TRIES 3 #define DEFAULT_RETRIGGER_TRIES 3
+#define DEFAULT_UEV_MSG_DELAY 30 +#define DEFAULT_UEV_WAIT_TIMEOUT 30
#define DEFAULT_CHECKINT 5 #define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2) #define MAX_CHECKINT(a) (a << 2)
@ -420,7 +433,7 @@ Index: multipath-tools-130222/libmultipath/dict.c
} }
static int static int
+def_uev_msg_delay_handler(vector strvec) +def_uev_wait_timeout_handler(vector strvec)
+{ +{
+ char *buff; + char *buff;
+ +
@ -429,9 +442,9 @@ Index: multipath-tools-130222/libmultipath/dict.c
+ if (!buff) + if (!buff)
+ return 1; + return 1;
+ +
+ conf->uev_msg_delay = atoi(buff); + conf->uev_wait_timeout = atoi(buff);
+ if (conf->uev_msg_delay <= 0) + if (conf->uev_wait_timeout <= 0)
+ conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY; + conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
+ FREE(buff); + FREE(buff);
+ +
+ return 0; + return 0;
@ -445,9 +458,9 @@ Index: multipath-tools-130222/libmultipath/dict.c
} }
static int static int
+snprint_def_uev_msg_delay (char * buff, int len, void * data) +snprint_def_uev_wait_timeout (char * buff, int len, void * data)
+{ +{
+ return snprintf(buff, len, "%i", conf->uev_msg_delay); + return snprintf(buff, len, "%i", conf->uev_wait_timeout);
+} +}
+ +
+static int +static int
@ -458,7 +471,7 @@ Index: multipath-tools-130222/libmultipath/dict.c
install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks);
install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries); install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries);
install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay); install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay);
+ install_keyword("missing_uev_msg_delay", &def_uev_msg_delay_handler, &snprint_def_uev_msg_delay); + install_keyword("missing_uev_wait_timeout", &def_uev_wait_timeout_handler, &snprint_def_uev_wait_timeout);
install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot); install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot);
__deprecated install_keyword("default_selector", &def_selector_handler, NULL); __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
@ -470,7 +483,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# config_dir "/etc/multipath/conf.d" # config_dir "/etc/multipath/conf.d"
# delay_watch_checks no # delay_watch_checks no
# delay_wait_checks no # delay_wait_checks no
+# missing_uev_msg_delay 30 +# missing_uev_wait_timeout 30
#} #}
#blacklist { #blacklist {
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
@ -483,12 +496,12 @@ Index: multipath-tools-130222/multipath/multipath.conf.5
checks. Default is checks. Default is
.I no .I no
+.TP +.TP
+.B missing_uev_msg_delay +.B missing_uev_wait_timeout
+Controls how long multipathd will wait, after a new multipath device is created, +Controls how many seconds multipathd will wait, after a new multipath device
+to receive a change event from udev for the device, before printing a warning +is created, to receive a change event from udev for the device, before
+message. This warning message will print every +automatically enabling device reloads. Usually multipathd will delay reloads
+.I missing_uev_msg_delay +on a device until it receives a change uevent from the initial table load. The
+seconds until the uevent is received. the default is +default is
+.I 30 +.I 30
. .
.SH "blacklist section" .SH "blacklist section"

View File

@ -6,7 +6,7 @@ Index: multipath-tools-130222/multipathd/main.c
=================================================================== ===================================================================
--- multipath-tools-130222.orig/multipathd/main.c --- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c +++ multipath-tools-130222/multipathd/main.c
@@ -1257,6 +1257,8 @@ check_path (struct vectors * vecs, struc @@ -1270,6 +1270,8 @@ check_path (struct vectors * vecs, struc
newstate = path_offline(pp); newstate = path_offline(pp);
if (newstate == PATH_UP) if (newstate == PATH_UP)
newstate = get_state(pp, 1); newstate = get_state(pp, 1);

View File

@ -1,7 +1,7 @@
--- ---
multipath.conf.defaults | 57 +++++++++++++++++++++++++++++++++++++-------- multipath.conf.defaults | 56 +++++++++++++++++++++++++++++++++++++--------
multipath/multipath.conf.5 | 2 - multipath/multipath.conf.5 | 2 -
2 files changed, 48 insertions(+), 11 deletions(-) 2 files changed, 48 insertions(+), 10 deletions(-)
Index: multipath-tools-130222/multipath/multipath.conf.5 Index: multipath-tools-130222/multipath/multipath.conf.5
=================================================================== ===================================================================
@ -34,7 +34,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# path_selector "service-time 0" # path_selector "service-time 0"
# path_grouping_policy "failover" # path_grouping_policy "failover"
# uid_attribute "ID_SERIAL" # uid_attribute "ID_SERIAL"
@@ -12,28 +15,35 @@ @@ -12,28 +15,36 @@
# features "0" # features "0"
# path_checker "directio" # path_checker "directio"
# alias_prefix "mpath" # alias_prefix "mpath"
@ -62,9 +62,9 @@ Index: multipath-tools-130222/multipath.conf.defaults
# config_dir "/etc/multipath/conf.d" # config_dir "/etc/multipath/conf.d"
# delay_watch_checks no # delay_watch_checks no
# delay_wait_checks no # delay_wait_checks no
-# missing_uev_msg_delay 30
+# retrigger_tries 3 +# retrigger_tries 3
+# retrigger_delay 10 +# retrigger_delay 10
# missing_uev_wait_timeout 30
+# new_bindings_in_boot no +# new_bindings_in_boot no
#} #}
#blacklist { #blacklist {
@ -74,7 +74,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# devnode "^dcssblk[0-9]*" # devnode "^dcssblk[0-9]*"
# device { # device {
# vendor "DGC" # vendor "DGC"
@@ -68,7 +78,7 @@ @@ -68,7 +79,7 @@
# product "Universal Xport" # product "Universal Xport"
# } # }
# device { # device {
@ -83,7 +83,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# product "Universal Xport" # product "Universal Xport"
# } # }
#} #}
@@ -666,7 +676,7 @@ @@ -666,7 +677,7 @@
# features "2 pg_init_retries 50" # features "2 pg_init_retries 50"
# hardware_handler "1 rdac" # hardware_handler "1 rdac"
# prio "rdac" # prio "rdac"
@ -92,7 +92,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# rr_weight "uniform" # rr_weight "uniform"
# no_path_retry 15 # no_path_retry 15
# } # }
@@ -679,7 +689,7 @@ @@ -679,7 +690,7 @@
# features "2 pg_init_retries 50" # features "2 pg_init_retries 50"
# hardware_handler "1 rdac" # hardware_handler "1 rdac"
# prio "rdac" # prio "rdac"
@ -101,7 +101,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# rr_weight "uniform" # rr_weight "uniform"
# no_path_retry 15 # no_path_retry 15
# } # }
@@ -696,6 +706,7 @@ @@ -696,6 +707,7 @@
# rr_min_io 128 # rr_min_io 128
# flush_on_last_del "yes" # flush_on_last_del "yes"
# dev_loss_tmo "infinity" # dev_loss_tmo "infinity"
@ -109,7 +109,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# retain_attached_hw_handler yes # retain_attached_hw_handler yes
# detect_prio yes # detect_prio yes
# } # }
@@ -876,7 +887,7 @@ @@ -876,7 +888,7 @@
# rr_min_io_rq 1 # rr_min_io_rq 1
# } # }
# device { # device {
@ -118,7 +118,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# product "INF-01-00" # product "INF-01-00"
# product_blacklist "Universal Xport" # product_blacklist "Universal Xport"
# path_grouping_policy "group_by_prio" # path_grouping_policy "group_by_prio"
@@ -886,7 +897,9 @@ @@ -886,7 +898,9 @@
# prio "rdac" # prio "rdac"
# failback immediate # failback immediate
# rr_weight "uniform" # rr_weight "uniform"
@ -129,7 +129,7 @@ Index: multipath-tools-130222/multipath.conf.defaults
# } # }
# device { # device {
# vendor "STK" # vendor "STK"
@@ -925,6 +938,30 @@ @@ -925,6 +939,30 @@
# rr_weight "uniform" # rr_weight "uniform"
# no_path_retry "queue" # no_path_retry "queue"
# } # }

View File

@ -14,7 +14,7 @@ Index: multipath-tools-130222/multipathd/main.c
static sem_t exit_sem; static sem_t exit_sem;
/* /*
@@ -1705,6 +1706,12 @@ sigusr2 (int sig) @@ -1718,6 +1719,12 @@ sigusr2 (int sig)
} }
static void static void
@ -27,7 +27,7 @@ Index: multipath-tools-130222/multipathd/main.c
signal_init(void) signal_init(void)
{ {
sigset_t set; sigset_t set;
@@ -1807,6 +1814,9 @@ child (void * param) @@ -1820,6 +1827,9 @@ child (void * param)
} }
running_state = DAEMON_START; running_state = DAEMON_START;
@ -37,7 +37,7 @@ Index: multipath-tools-130222/multipathd/main.c
condlog(2, "--------start up--------"); condlog(2, "--------start up--------");
condlog(2, "read " DEFAULT_CONFIGFILE); condlog(2, "read " DEFAULT_CONFIGFILE);
@@ -1898,8 +1908,6 @@ child (void * param) @@ -1911,8 +1921,6 @@ child (void * param)
} }
pthread_attr_destroy(&misc_attr); pthread_attr_destroy(&misc_attr);
@ -46,7 +46,7 @@ Index: multipath-tools-130222/multipathd/main.c
update_timestamp(1); update_timestamp(1);
/* Ignore errors, we can live without */ /* Ignore errors, we can live without */
@@ -1979,7 +1987,10 @@ daemonize(void) @@ -1992,7 +2000,10 @@ daemonize(void)
{ {
int pid; int pid;
int dev_null_fd; int dev_null_fd;
@ -57,7 +57,7 @@ Index: multipath-tools-130222/multipathd/main.c
if( (pid = fork()) < 0){ if( (pid = fork()) < 0){
fprintf(stderr, "Failed first fork : %s\n", strerror(errno)); fprintf(stderr, "Failed first fork : %s\n", strerror(errno));
return -1; return -1;
@@ -1987,10 +1998,13 @@ daemonize(void) @@ -2000,10 +2011,13 @@ daemonize(void)
else if (pid != 0) else if (pid != 0)
return pid; return pid;
@ -72,7 +72,7 @@ Index: multipath-tools-130222/multipathd/main.c
else if (pid != 0) else if (pid != 0)
_exit(0); _exit(0);
@@ -2001,30 +2015,34 @@ daemonize(void) @@ -2014,30 +2028,34 @@ daemonize(void)
if (dev_null_fd < 0){ if (dev_null_fd < 0){
fprintf(stderr, "cannot open /dev/null for input & output : %s\n", fprintf(stderr, "cannot open /dev/null for input & output : %s\n",
strerror(errno)); strerror(errno));
@ -111,7 +111,7 @@ Index: multipath-tools-130222/multipathd/main.c
} }
int int
@@ -2103,10 +2121,12 @@ main (int argc, char *argv[]) @@ -2116,10 +2134,12 @@ main (int argc, char *argv[])
if (err < 0) if (err < 0)
/* error */ /* error */
exit(1); exit(1);

View File

@ -88,7 +88,7 @@ Index: multipath-tools-130222/multipathd/main.c
/* /*
* libcheckers * libcheckers
@@ -1235,6 +1236,7 @@ check_path (struct vectors * vecs, struc @@ -1248,6 +1249,7 @@ check_path (struct vectors * vecs, struc
int newstate; int newstate;
int new_path_up = 0; int new_path_up = 0;
int chkr_new_path_up = 0; int chkr_new_path_up = 0;
@ -96,7 +96,7 @@ Index: multipath-tools-130222/multipathd/main.c
int oldchkrstate = pp->chkrstate; int oldchkrstate = pp->chkrstate;
if (!pp->mpp && (pp->missing_udev_info != INFO_MISSING || if (!pp->mpp && (pp->missing_udev_info != INFO_MISSING ||
@@ -1299,6 +1301,16 @@ check_path (struct vectors * vecs, struc @@ -1312,6 +1314,16 @@ check_path (struct vectors * vecs, struc
pp->wait_checks = 0; pp->wait_checks = 0;
} }
@ -113,7 +113,7 @@ Index: multipath-tools-130222/multipathd/main.c
pp->chkrstate = newstate; pp->chkrstate = newstate;
if (newstate != pp->state) { if (newstate != pp->state) {
int oldstate = pp->state; int oldstate = pp->state;
@@ -1354,15 +1366,17 @@ check_path (struct vectors * vecs, struc @@ -1367,15 +1379,17 @@ check_path (struct vectors * vecs, struc
/* /*
* reinstate this path * reinstate this path
*/ */
@ -140,7 +140,7 @@ Index: multipath-tools-130222/multipathd/main.c
} }
new_path_up = 1; new_path_up = 1;
@@ -1377,8 +1391,9 @@ check_path (struct vectors * vecs, struc @@ -1390,8 +1404,9 @@ check_path (struct vectors * vecs, struc
enable_group(pp); enable_group(pp);
} }
else if (newstate == PATH_UP || newstate == PATH_GHOST) { else if (newstate == PATH_UP || newstate == PATH_GHOST) {

View File

@ -214,7 +214,7 @@ Index: multipath-tools-130222/multipathd/main.c
=================================================================== ===================================================================
--- multipath-tools-130222.orig/multipathd/main.c --- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c +++ multipath-tools-130222/multipathd/main.c
@@ -1502,7 +1502,7 @@ configure (struct vectors * vecs, int st @@ -1515,7 +1515,7 @@ configure (struct vectors * vecs, int st
struct multipath * mpp; struct multipath * mpp;
struct path * pp; struct path * pp;
vector mpvec; vector mpvec;
@ -223,7 +223,7 @@ Index: multipath-tools-130222/multipathd/main.c
if (!vecs->pathvec && !(vecs->pathvec = vector_alloc())) if (!vecs->pathvec && !(vecs->pathvec = vector_alloc()))
return 1; return 1;
@@ -1516,7 +1516,9 @@ configure (struct vectors * vecs, int st @@ -1529,7 +1529,9 @@ configure (struct vectors * vecs, int st
/* /*
* probe for current path (from sysfs) and map (from dm) sets * probe for current path (from sysfs) and map (from dm) sets
*/ */

View File

@ -37,7 +37,7 @@ Index: multipath-tools-130222/libmultipath/config.c
@@ -677,6 +679,7 @@ load_config (char * file, struct udev *u @@ -677,6 +679,7 @@ load_config (char * file, struct udev *u
conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
conf->new_bindings_in_boot = 0; conf->new_bindings_in_boot = 0;
conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY; conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
+ conf->skip_kpartx = DEFAULT_SKIP_KPARTX; + conf->skip_kpartx = DEFAULT_SKIP_KPARTX;
/* /*
@ -65,7 +65,7 @@ Index: multipath-tools-130222/libmultipath/config.h
@@ -143,6 +145,7 @@ struct config { @@ -143,6 +145,7 @@ struct config {
int new_bindings_in_boot; int new_bindings_in_boot;
int delayed_reconfig; int delayed_reconfig;
int uev_msg_delay; int uev_wait_timeout;
+ int skip_kpartx; + int skip_kpartx;
unsigned int version[3]; unsigned int version[3];
@ -138,7 +138,7 @@ Index: multipath-tools-130222/libmultipath/defaults.h
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
#define DEFAULT_RETRIGGER_DELAY 10 #define DEFAULT_RETRIGGER_DELAY 10
#define DEFAULT_RETRIGGER_TRIES 3 #define DEFAULT_RETRIGGER_TRIES 3
#define DEFAULT_UEV_MSG_DELAY 30 #define DEFAULT_UEV_WAIT_TIMEOUT 30
+#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF +#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF
#define DEFAULT_CHECKINT 5 #define DEFAULT_CHECKINT 5
@ -585,9 +585,9 @@ Index: multipath-tools-130222/multipath/multipath.conf.5
=================================================================== ===================================================================
--- multipath-tools-130222.orig/multipath/multipath.conf.5 --- multipath-tools-130222.orig/multipath/multipath.conf.5
+++ multipath-tools-130222/multipath/multipath.conf.5 +++ multipath-tools-130222/multipath/multipath.conf.5
@@ -505,6 +505,12 @@ message. This warning message will print @@ -505,6 +505,12 @@ automatically enabling device reloads. U
.I missing_uev_msg_delay on a device until it receives a change uevent from the initial table load. The
seconds until the uevent is received. the default is default is
.I 30 .I 30
+.TP +.TP
+.B skip_kpartx +.B skip_kpartx

View File

@ -128,7 +128,7 @@ Index: multipath-tools-130222/multipathd/main.c
dm_queue_if_no_path(mpp->alias, 0); dm_queue_if_no_path(mpp->alias, 0);
} }
if (!flush_map(mpp, vecs, 1)) { if (!flush_map(mpp, vecs, 1)) {
@@ -1184,6 +1185,7 @@ retry_count_tick(vector mpvec) @@ -1197,6 +1198,7 @@ retry_count_tick(vector mpvec)
mpp->stat_total_queueing_time++; mpp->stat_total_queueing_time++;
condlog(4, "%s: Retrying.. No active path", mpp->alias); condlog(4, "%s: Retrying.. No active path", mpp->alias);
if(--mpp->retry_tick == 0) { if(--mpp->retry_tick == 0) {

View File

@ -0,0 +1,99 @@
---
multipath/multipath.conf.5 | 56 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 51 insertions(+), 5 deletions(-)
Index: multipath-tools-130222/multipath/multipath.conf.5
===================================================================
--- multipath-tools-130222.orig/multipath/multipath.conf.5
+++ multipath-tools-130222/multipath/multipath.conf.5
@@ -240,18 +240,21 @@ Specify any device-mapper features to be
.I num list
where
.I num
-is the number of features in
+is the number, between 0 and 6, of features in
.I list.
-Possible values for the feature list are
+Possible values for the feature list are:
.RS
.TP 12
-.B queue_if_no_path
+.I queue_if_no_path
Queue IO if no path is active; identical to the
.I no_path_retry
keyword.
.TP
-.B no_partitions
-Disable automatic partitions generation via kpartx.
+.I pg_init_retries
+Number of times to retry pg_init, it must be between 1 and 50.
+.TP
+.I pg_init_delay_msecs
+Number of msecs before pg_init retry, it must be between 0 and 60000.
.RE
.TP
.B path_checker
@@ -511,6 +514,45 @@ If set to
.I yes
, kpartx will not automatically create partitions on the device. The default is
.I no
+.TP
+.B ignore_new_boot_devs
+If set to
+.I yes
+, multipath will never attempt to create a multipath device whose wwid is not
+listed in /etc/multipath/wwids, while running in the initramfs. This keeps
+multipath from adding new devices during the initramfs portion of bootup. The
+default is
+.I no
+.TP
+.B retrigger_tries
+This sets how many times multipathd will reissue change uevents on block
+devices that are not blacklisted, but have no wwid set by udev. Multipath
+assumes that any devices that should not report a wwid are blacklisted. This
+means that if a non-blacklisted device has no wwid, it is likely that udev
+timed out while processing it. Multipathd will wait for a while, and then
+reissue a change uevent to give udev another chance to set the wwid. The
+default is
+.I 3
+.TP
+.B retrigger_delay
+This sets how long multipathd should wait, after receiving a uevent for a
+non-blacklisted device without a wwid set by udev, before reissuing a
+change uevent. The goal of this delay is to give udev a chance to finish
+processing its current batch of uevents before sending more, to hopefully
+avoid it timing out. The default is
+.I 10
+.TP
+.B new_bindings_in_boot
+If set to
+.I yes
+, multipath will allow new user_friendly_names bindings to be created while
+running in the initramfs. Otherwise, multipath will not create
+user_friendly_names bindings while running in the initramfs. Instead, it will
+use the WWID for the name of a device that was configured to use
+user_friendly_names. When multipathd is restarted later in boot on the
+regular filesystem, the device will be renamed to a user_friendly_name. The
+default is
+.I no
.
.SH "blacklist section"
The
@@ -603,6 +645,8 @@ section:
.TP
.B flush_on_last_del
.TP
+.B user_friendly_names
+.TP
.B no_path_retry
.TP
.B rr_min_io
@@ -697,6 +741,8 @@ section:
.TP
.B no_path_retry
.TP
+.B user_friendly_names
+.TP
.B rr_min_io
.TP
.B rr_min_io_rq

View File

@ -0,0 +1,38 @@
---
libmultipath/configure.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
Index: multipath-tools-130222/libmultipath/configure.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/configure.c
+++ multipath-tools-130222/libmultipath/configure.c
@@ -257,7 +257,7 @@ extern int
setup_map (struct multipath * mpp, char * params, int params_size)
{
struct pathgroup * pgp;
- int i;
+ int i, old_nr_active;
/*
* don't bother if devmap size is unknown
@@ -311,8 +311,12 @@ setup_map (struct multipath * mpp, char
if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
return 1;
+ old_nr_active = mpp->nr_active;
mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
+ if (mpp->nr_active && !old_nr_active)
+ mpp->force_udev_reload = 1;
+
/*
* ponders each path group and determine highest prio pg
* to switch over (default to first)
@@ -445,7 +449,6 @@ select_action (struct multipath * mpp, v
mpp->alias);
return;
}
- mpp->force_udev_reload = !pathcount(mpp, PATH_WILD);
if (cmpp->size != mpp->size) {
mpp->force_udev_reload = 1;
mpp->action = ACT_RESIZE;

View File

@ -0,0 +1,16 @@
---
multipathd/multipathd.init.redhat | 1 +
1 file changed, 1 insertion(+)
Index: multipath-tools-130222/multipathd/multipathd.init.redhat
===================================================================
--- multipath-tools-130222.orig/multipathd/multipathd.init.redhat
+++ multipath-tools-130222/multipathd/multipathd.init.redhat
@@ -67,6 +67,7 @@ popd > /dev/null
start() {
test -x $DAEMON || exit 5
echo -n $"Starting $prog daemon: "
+ modprobe dm-multipath >/dev/null 2>&1
daemon $DAEMON
RETVAL=$?
[ $RETVAL -eq 0 ] && touch $lockdir/$prog

View File

@ -0,0 +1,17 @@
---
multipathd/multipathd.service | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: multipath-tools-130222/multipathd/multipathd.service
===================================================================
--- multipath-tools-130222.orig/multipathd/multipathd.service
+++ multipath-tools-130222/multipathd/multipathd.service
@@ -2,7 +2,7 @@
Description=Device-Mapper Multipath Device Controller
Wants=blk-availability.service
Before=iscsi.service iscsid.service lvm2-activation-early.service
-After=syslog.target
+After=syslog.target systemd-udev-trigger.service
ConditionPathExists=/etc/multipath.conf
ConditionKernelCommandLine=!nompath
DefaultDependencies=no

View File

@ -0,0 +1,17 @@
---
libmultipath/devmapper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: multipath-tools-130222/libmultipath/devmapper.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/devmapper.c
+++ multipath-tools-130222/libmultipath/devmapper.c
@@ -1387,7 +1387,7 @@ dm_rename (const char * old, char * new,
{
int r = 0;
struct dm_task *dmt;
- uint32_t cookie;
+ 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 (dm_rename_partmaps(old, new))

View File

@ -0,0 +1,38 @@
From e2b87038125c79089e0bd4c6fd905667c5108740 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Tue, 9 Aug 2016 13:36:04 -0500
Subject: [PATCH 01/11] libmultipath: correctly initialize pp->sg_id
For BZ 1348372 from upstream:
commit b4d9ca8dc8bbfbd3782bf4cf2cb1a440685ccd07
Author: Hannes Reinecke <hare@suse.de>
Date: Wed Nov 11 13:38:57 2015 +0100
libmultipath: correctly initialize pp->sg_id
The default SCSI protocol is 'SCSI_PROTOCOL_UNSPEC';
'0' is SCSI_PROTOCOL_FCP.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/structs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 30d247d..26a6a3b 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -94,6 +94,7 @@ alloc_path (void)
pp->sg_id.channel = -1;
pp->sg_id.scsi_id = -1;
pp->sg_id.lun = -1;
+ pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
pp->fd = -1;
pp->priority = PRIO_UNDEF;
}
--
1.8.3.1

View File

@ -0,0 +1,219 @@
From 2fc494b81157059e0be66022f6a2110f1ce179c3 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Tue, 9 Aug 2016 13:44:10 -0500
Subject: [PATCH 02/11] libmultipath: add rbd discovery
For BZ 1348372 from upstream commit:
Commit 152f3f803ee922075e8b25027eb9dc5699f1aefa
Author: Mike Christie <mchristi@redhat.com>
Date: Mon Aug 8 07:01:47 2016 -0500
libmultipath: add rbd discovery
rbd is a block device interface for Ceph. It does not support
any SCSI commands, so this patch adds bus detection and virtual
vendor/product pathinfo.
--------
Porting notes:
get_uid() chunk does not match upstream due to rhel not having
the get uid callout code and sysfs uid detection code.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers.h | 1 +
libmultipath/discovery.c | 116 ++++++++++++++++++++++++++++++++++++++++-------
libmultipath/structs.h | 1 +
3 files changed, 101 insertions(+), 17 deletions(-)
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index f6fe326..735bb25 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -75,6 +75,7 @@ enum path_check_state {
#define EMC_CLARIION "emc_clariion"
#define READSECTOR0 "readsector0"
#define CCISS_TUR "cciss_tur"
+#define RBD "rbd"
#define DEFAULT_CHECKER DIRECTIO
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 7a8282b..1b9f390 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -781,6 +781,21 @@ scsi_sysfs_pathinfo (struct path * pp)
}
static int
+rbd_sysfs_pathinfo (struct path * pp)
+{
+ sprintf(pp->vendor_id, "Ceph");
+ sprintf(pp->product_id, "RBD");
+
+ condlog(3, "%s: vendor = %s product = %s", pp->dev, pp->vendor_id,
+ pp->product_id);
+ /*
+ * set the hwe configlet pointer
+ */
+ pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL);
+ return 0;
+}
+
+static int
ccw_sysfs_pathinfo (struct path * pp)
{
struct udev_device *parent;
@@ -974,6 +989,8 @@ sysfs_pathinfo(struct path * pp)
pp->bus = SYSFS_BUS_CCW;
if (!strncmp(pp->dev,"sd", 2))
pp->bus = SYSFS_BUS_SCSI;
+ if (!strncmp(pp->dev,"rbd", 3))
+ pp->bus = SYSFS_BUS_RBD;
if (pp->bus == SYSFS_BUS_UNDEF)
return 0;
@@ -986,6 +1003,9 @@ sysfs_pathinfo(struct path * pp)
} else if (pp->bus == SYSFS_BUS_CCISS) {
if (cciss_sysfs_pathinfo(pp))
return 1;
+ } else if (pp->bus == SYSFS_BUS_RBD) {
+ if (rbd_sysfs_pathinfo(pp))
+ return 1;
}
return 0;
}
@@ -1087,10 +1107,60 @@ get_prio (struct path * pp)
}
static int
+get_rbd_uid(struct path * pp)
+{
+ struct udev_device *rbd_bus_dev;
+ int ret, rbd_bus_id;
+ const char *pool, *image, *snap;
+ char sysfs_path[PATH_SIZE];
+ uint64_t snap_id, max_snap_id = -3;
+
+ ret = sscanf(pp->dev, "rbd%d", &rbd_bus_id);
+ if (ret != 1)
+ return -EINVAL;
+
+ snprintf(sysfs_path, sizeof(sysfs_path), "/sys/bus/rbd/devices/%d",
+ rbd_bus_id);
+ rbd_bus_dev = udev_device_new_from_syspath(conf->udev, sysfs_path);
+ if (!rbd_bus_dev)
+ return -ENODEV;
+
+ ret = -EINVAL;
+ pool = udev_device_get_sysattr_value(rbd_bus_dev, "pool_id");
+ if (!pool)
+ goto free_dev;
+
+ image = udev_device_get_sysattr_value(rbd_bus_dev, "image_id");
+ if (!image)
+ goto free_dev;
+
+ snap = udev_device_get_sysattr_value(rbd_bus_dev, "snap_id");
+ if (!snap)
+ goto free_dev;
+ snap_id = strtoull(snap, NULL, 19);
+ if (snap_id >= max_snap_id)
+ ret = snprintf(pp->wwid, WWID_SIZE, "%s-%s", pool, image);
+ else
+ ret = snprintf(pp->wwid, WWID_SIZE, "%s-%s-%s", pool,
+ image, snap);
+ if (ret < WWID_SIZE) {
+ ret = 0;
+ } else {
+ condlog(0, "%s: wwid overflow", pp->dev);
+ ret = -EOVERFLOW;
+ }
+
+free_dev:
+ udev_device_unref(rbd_bus_dev);
+ return ret;
+}
+
+static int
get_uid (struct path * pp)
{
char *c;
const char *value;
+ int ret;
if (!pp->uid_attribute)
select_getuid(pp);
@@ -1101,25 +1171,37 @@ get_uid (struct path * pp)
}
memset(pp->wwid, 0, WWID_SIZE);
- value = udev_device_get_property_value(pp->udev, pp->uid_attribute);
- if ((!value || strlen(value) == 0) && conf->cmd == CMD_VALID_PATH)
- value = getenv(pp->uid_attribute);
- if (value && strlen(value)) {
- size_t len = WWID_SIZE;
-
- if (strlen(value) + 1 > WWID_SIZE) {
- condlog(0, "%s: wwid overflow", pp->dev);
- } else {
- len = strlen(value);
+ if (pp->bus == SYSFS_BUS_RBD) {
+ ret = get_rbd_uid(pp);
+ if (ret) {
+ condlog(1, "%s: failed to get sysfs uid: %s",
+ pp->dev, strerror(-ret));
+ pp->missing_udev_info = INFO_MISSING;
+ pp->tick = conf->retrigger_delay;
}
- strncpy(pp->wwid, value, len);
- pp->missing_udev_info = INFO_OK;
- pp->tick = 0;
} else {
- condlog(3, "%s: no %s attribute", pp->dev,
- pp->uid_attribute);
- pp->missing_udev_info = INFO_MISSING;
- pp->tick = conf->retrigger_delay;
+ value = udev_device_get_property_value(pp->udev,
+ pp->uid_attribute);
+ if ((!value || strlen(value) == 0) &&
+ conf->cmd == CMD_VALID_PATH)
+ value = getenv(pp->uid_attribute);
+ if (value && strlen(value)) {
+ size_t len = WWID_SIZE;
+
+ if (strlen(value) + 1 > WWID_SIZE) {
+ condlog(0, "%s: wwid overflow", pp->dev);
+ } else {
+ len = strlen(value);
+ }
+ strncpy(pp->wwid, value, len);
+ pp->missing_udev_info = INFO_OK;
+ pp->tick = 0;
+ } else {
+ condlog(3, "%s: no %s attribute", pp->dev,
+ pp->uid_attribute);
+ pp->missing_udev_info = INFO_MISSING;
+ pp->tick = conf->retrigger_delay;
+ }
}
/* Strip any trailing blanks */
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index b5b4567..e566462 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -52,6 +52,7 @@ enum sysfs_buses {
SYSFS_BUS_IDE,
SYSFS_BUS_CCW,
SYSFS_BUS_CCISS,
+ SYSFS_BUS_RBD,
};
enum pathstates {
--
1.8.3.1

View File

@ -0,0 +1,250 @@
From 1073621a7a63ca4e9a00baedd8edc51e5381eb95 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Tue, 9 Aug 2016 13:46:11 -0500
Subject: [PATCH 03/11] multipath-tools: add checker callout to repair path
For BZ 1348372 from upstream commit:
commit 015f87b16a7797a17afd514aec46e65c2a1a2f73
Author: Mike Christie <mchristi@redhat.com>
Date: Mon Aug 8 07:01:48 2016 -0500
multipath-tools: add checker callout to repair path
This patch adds a callback which can be used to repair a path
if check() has determined it is in the PATH_DOWN state.
The next patch that adds rbd checker support which will use this to
handle the case where a rbd device is blacklisted.
--------
Porting notes:
checkerloop difference due to different path tracking.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers.c | 23 +++++++++++++++++++++++
libmultipath/checkers.h | 4 ++++
libmultipath/checkers/cciss_tur.c | 5 +++++
libmultipath/checkers/directio.c | 5 +++++
libmultipath/checkers/emc_clariion.c | 5 +++++
libmultipath/checkers/hp_sw.c | 5 +++++
libmultipath/checkers/rdac.c | 5 +++++
libmultipath/checkers/readsector0.c | 5 +++++
libmultipath/checkers/tur.c | 5 +++++
multipathd/main.c | 9 +++++++++
10 files changed, 71 insertions(+)
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index 7f9db2d..fa7d8b7 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -137,6 +137,14 @@ struct checker * add_checker (char * name)
if (!c->free)
goto out;
+ c->repair = (void (*)(struct checker *)) dlsym(c->handle,
+ "libcheck_repair");
+ errstr = dlerror();
+ if (errstr != NULL)
+ condlog(0, "A dynamic linking error occurred: (%s)", errstr);
+ if (!c->repair)
+ goto out;
+
c->fd = 0;
c->sync = 1;
list_add(&c->node, &checkers);
@@ -202,6 +210,20 @@ void checker_put (struct checker * dst)
free_checker(src);
}
+void checker_repair (struct checker * c)
+{
+ if (!c)
+ return;
+
+ c->message[0] = '\0';
+ if (c->disable) {
+ MSG(c, "checker disabled");
+ return;
+ }
+
+ c->repair(c);
+}
+
int checker_check (struct checker * c)
{
int r;
@@ -266,6 +288,7 @@ void checker_get (struct checker * dst, char * name)
dst->sync = src->sync;
strncpy(dst->name, src->name, CHECKER_NAME_LEN);
strncpy(dst->message, src->message, CHECKER_MSG_LEN);
+ dst->repair = src->repair;
dst->check = src->check;
dst->init = src->init;
dst->free = src->free;
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index 735bb25..ad3b9e4 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -106,6 +106,9 @@ struct checker {
multipath-wide. Use MALLOC if
you want to stuff data in. */
int (*check)(struct checker *);
+ void (*repair)(struct checker *); /* called if check returns
+ PATH_DOWN to bring path into
+ usable state */
int (*init)(struct checker *); /* to allocate the context */
void (*free)(struct checker *); /* to free the context */
};
@@ -125,6 +128,7 @@ void checker_set_async (struct checker *);
void checker_set_fd (struct checker *, int);
void checker_enable (struct checker *);
void checker_disable (struct checker *);
+void checker_repair (struct checker *);
int checker_check (struct checker *);
int checker_selected (struct checker *);
char * checker_name (struct checker *);
diff --git a/libmultipath/checkers/cciss_tur.c b/libmultipath/checkers/cciss_tur.c
index 4c26901..7e4eb81 100644
--- a/libmultipath/checkers/cciss_tur.c
+++ b/libmultipath/checkers/cciss_tur.c
@@ -63,6 +63,11 @@ void libcheck_free (struct checker * c)
return;
}
+void libcheck_repair (struct checker * c)
+{
+ return;
+}
+
extern int
libcheck_check (struct checker * c)
{
diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c
index 46fe6a7..1a997ed 100644
--- a/libmultipath/checkers/directio.c
+++ b/libmultipath/checkers/directio.c
@@ -116,6 +116,11 @@ void libcheck_free (struct checker * c)
free(ct);
}
+void libcheck_repair (struct checker * c)
+{
+ return;
+}
+
static int
check_state(int fd, struct directio_context *ct, int sync, int timeout_secs)
{
diff --git a/libmultipath/checkers/emc_clariion.c b/libmultipath/checkers/emc_clariion.c
index b42d267..43b5025 100644
--- a/libmultipath/checkers/emc_clariion.c
+++ b/libmultipath/checkers/emc_clariion.c
@@ -90,6 +90,11 @@ void libcheck_free (struct checker * c)
free(c->context);
}
+void libcheck_repair (struct checker * c)
+{
+ return;
+}
+
int libcheck_check (struct checker * c)
{
unsigned char sense_buffer[128] = { 0, };
diff --git a/libmultipath/checkers/hp_sw.c b/libmultipath/checkers/hp_sw.c
index b50ac0c..857ac5e 100644
--- a/libmultipath/checkers/hp_sw.c
+++ b/libmultipath/checkers/hp_sw.c
@@ -44,6 +44,11 @@ void libcheck_free (struct checker * c)
return;
}
+void libcheck_repair (struct checker * c)
+{
+ return;
+}
+
static int
do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
void *resp, int mx_resp_len, int noisy, unsigned int timeout)
diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c
index f0e0af3..5469e61 100644
--- a/libmultipath/checkers/rdac.c
+++ b/libmultipath/checkers/rdac.c
@@ -139,6 +139,11 @@ void libcheck_free (struct checker * c)
return;
}
+void libcheck_repair (struct checker * c)
+{
+ return;
+}
+
static int
do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len,
unsigned int timeout)
diff --git a/libmultipath/checkers/readsector0.c b/libmultipath/checkers/readsector0.c
index 0550fb6..b3ed1f3 100644
--- a/libmultipath/checkers/readsector0.c
+++ b/libmultipath/checkers/readsector0.c
@@ -23,6 +23,11 @@ void libcheck_free (struct checker * c)
return;
}
+void libcheck_repair (struct checker * c)
+{
+ return;
+}
+
int libcheck_check (struct checker * c)
{
unsigned char buf[4096];
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
index 1e5b039..91f1458 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -187,6 +187,11 @@ void libcheck_free (struct checker * c)
return;
}
+void libcheck_repair (struct checker * c)
+{
+ return;
+}
+
#define TUR_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args);
int
diff --git a/multipathd/main.c b/multipathd/main.c
index 8808c88..d26fd22 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1455,6 +1455,14 @@ check_path (struct vectors * vecs, struct path * pp)
}
}
+void repair_path(struct vectors * vecs, struct path * pp)
+{
+ if (pp->state != PATH_DOWN)
+ return;
+
+ checker_repair(&pp->checker);
+}
+
static void *
checkerloop (void *ap)
{
@@ -1483,6 +1491,7 @@ checkerloop (void *ap)
if (vecs->pathvec) {
vector_foreach_slot (vecs->pathvec, pp, i) {
check_path(vecs, pp);
+ repair_path(vecs, pp);
}
}
if (vecs->mpvec) {
--
1.8.3.1

View File

@ -0,0 +1,746 @@
From e28c340ed961409700d46a1cb9a820a8b7a4d016 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Thu, 11 Aug 2016 02:12:12 -0500
Subject: [PATCH 04/11] multipath-tools: Add rbd checker.
For BZ 1348372 from upstream commit:
commit d1cad5649b6fcf9027d43ca0405c900080133e32
Author: Mike Christie <mchristi@redhat.com>
Date: Mon Aug 8 07:01:49 2016 -0500
multipath-tools: Add rbd checker.
This checker currently only handles the case where a path is failed
due to it being blacklisted by the ceph cluster. The specific use
case for me is when LIO exports rbd images through multiple LIO
instances.
The problem it handles is when rbd instance1 has the exclusive lock,
but becomes unreachable another host in the cluster will take over
and blacklist the instance1. This prevents it from sending stale IO
and corrupting data.
Later, when the host is reachable, we will want to failback to it.
To this, the checker will detect we were blacklisted, unmap the old
image which will make sure old IO is failed, and then remap the
image
and unblacklist the host. multipathd will then handle this like a
path being removed and re-added.
--------
Porting notes:
Added rbd to multipath.conf.annotated.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers/Makefile | 7
libmultipath/checkers/rbd.c | 639 +++++++++++++++++++++++++++++++++++++++++
multipath.conf.annotated | 4
multipath/multipath.conf.5 | 3
4 files changed, 651 insertions(+), 2 deletions(-)
create mode 100644 libmultipath/checkers/rbd.c
Index: multipath-tools-130222/libmultipath/checkers/Makefile
===================================================================
--- multipath-tools-130222.orig/libmultipath/checkers/Makefile
+++ multipath-tools-130222/libmultipath/checkers/Makefile
@@ -14,10 +14,17 @@ LIBS= \
libcheckhp_sw.so \
libcheckrdac.so
+ifeq ($(shell test -r /usr/include/rados/librados.h && echo 1),1)
+LIBS += libcheckrbd.so
+endif
+
CFLAGS += -fPIC -I..
all: $(LIBS)
+libcheckrbd.so: rbd.o
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -lrados -ludev
+
libcheckdirectio.so: libsg.o directio.o
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -laio
Index: multipath-tools-130222/libmultipath/checkers/rbd.c
===================================================================
--- /dev/null
+++ multipath-tools-130222/libmultipath/checkers/rbd.c
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2016 Red Hat
+ * Copyright (c) 2004 Christophe Varoqui
+ *
+ * Code based off of tur.c and ceph's krbd.cc
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <libudev.h>
+#include <ifaddrs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include "rados/librados.h"
+
+#include "structs.h"
+#include "checkers.h"
+
+#include "../libmultipath/debug.h"
+#include "../libmultipath/uevent.h"
+
+struct rbd_checker_context;
+typedef int (thread_fn)(struct rbd_checker_context *ct, char *msg);
+
+#define RBD_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args);
+
+struct rbd_checker_context {
+ int rbd_bus_id;
+ char *client_addr;
+ char *config_info;
+ char *snap;
+ char *pool;
+ char *image;
+ char *username;
+ int remapped;
+ int blacklisted;
+
+ rados_t cluster;
+
+ int state;
+ int running;
+ time_t time;
+ thread_fn *fn;
+ pthread_t thread;
+ pthread_mutex_t lock;
+ pthread_cond_t active;
+ pthread_spinlock_t hldr_lock;
+ int holders;
+ char message[CHECKER_MSG_LEN];
+};
+
+int libcheck_init(struct checker * c)
+{
+ struct rbd_checker_context *ct;
+ struct udev_device *block_dev;
+ struct udev_device *bus_dev;
+ struct udev *udev;
+ struct stat sb;
+ const char *block_name, *addr, *config_info;
+ const char *image, *pool, *snap, *username;
+ char sysfs_path[PATH_SIZE];
+ int ret;
+
+ ct = malloc(sizeof(struct rbd_checker_context));
+ if (!ct)
+ return 1;
+ memset(ct, 0, sizeof(struct rbd_checker_context));
+ ct->holders = 1;
+ pthread_cond_init(&ct->active, NULL);
+ pthread_mutex_init(&ct->lock, NULL);
+ pthread_spin_init(&ct->hldr_lock, PTHREAD_PROCESS_PRIVATE);
+ c->context = ct;
+
+ /*
+ * The rbd block layer sysfs device is not linked to the rbd bus
+ * device that we interact with, so figure that out now.
+ */
+ if (fstat(c->fd, &sb) != 0)
+ goto free_ct;
+
+ udev = udev_new();
+ if (!udev)
+ goto free_ct;
+
+ block_dev = udev_device_new_from_devnum(udev, 'b', sb.st_rdev);
+ if (!block_dev)
+ goto free_udev;
+
+ block_name = udev_device_get_sysname(block_dev);
+ ret = sscanf(block_name, "rbd%d", &ct->rbd_bus_id);
+
+ udev_device_unref(block_dev);
+ if (ret != 1)
+ goto free_udev;
+
+ snprintf(sysfs_path, sizeof(sysfs_path), "/sys/bus/rbd/devices/%d",
+ ct->rbd_bus_id);
+ bus_dev = udev_device_new_from_syspath(udev, sysfs_path);
+ if (!bus_dev)
+ goto free_udev;
+
+ addr = udev_device_get_sysattr_value(bus_dev, "client_addr");
+ if (!addr) {
+ condlog(0, "Could not find client_addr in rbd sysfs. Try "
+ "updating kernel");
+ goto free_dev;
+ }
+
+ ct->client_addr = strdup(addr);
+ if (!ct->client_addr)
+ goto free_dev;
+
+ config_info = udev_device_get_sysattr_value(bus_dev, "config_info");
+ if (!config_info)
+ goto free_addr;
+
+ ct->config_info = strdup(config_info);
+ if (!ct->config_info)
+ goto free_addr;
+
+ username = strstr(config_info, "name=");
+ if (username) {
+ char *end;
+ int len;
+
+ username += 5;
+ end = strchr(username, ',');
+ if (!end)
+ goto free_info;
+ len = end - username;
+
+ ct->username = malloc(len + 1);
+ if (!ct->username)
+ goto free_info;
+ strncpy(ct->username, username, len);
+ ct->username[len] = '\0';
+ }
+
+ image = udev_device_get_sysattr_value(bus_dev, "name");
+ if (!image)
+ goto free_username;
+
+ ct->image = strdup(image);
+ if (!ct->image)
+ goto free_info;
+
+ pool = udev_device_get_sysattr_value(bus_dev, "pool");
+ if (!pool)
+ goto free_image;
+
+ ct->pool = strdup(pool);
+ if (!ct->pool)
+ goto free_image;
+
+ snap = udev_device_get_sysattr_value(bus_dev, "current_snap");
+ if (!snap)
+ goto free_pool;
+
+ if (strcmp("-", snap)) {
+ ct->snap = strdup(snap);
+ if (!ct->snap)
+ goto free_pool;
+ }
+
+ if (rados_create(&ct->cluster, NULL) < 0) {
+ condlog(0, "Could not create rados cluster");
+ goto free_snap;
+ }
+
+ if (rados_conf_read_file(ct->cluster, NULL) < 0) {
+ condlog(0, "Could not read rados conf");
+ goto shutdown_rados;
+ }
+
+ ret = rados_connect(ct->cluster);
+ if (ret < 0) {
+ condlog(0, "Could not connect to rados cluster");
+ goto shutdown_rados;
+ }
+
+ udev_device_unref(bus_dev);
+ udev_unref(udev);
+
+ condlog(3, "rbd%d checker init %s %s/%s@%s %s", ct->rbd_bus_id,
+ ct->client_addr, ct->pool, ct->image, ct->snap ? ct->snap : "-",
+ ct->username ? ct->username : "none");
+ return 0;
+
+shutdown_rados:
+ rados_shutdown(ct->cluster);
+free_snap:
+ if (ct->snap)
+ free(ct->snap);
+free_pool:
+ free(ct->pool);
+free_image:
+ free(ct->image);
+free_username:
+ if (ct->username)
+ free(ct->username);
+free_info:
+ free(ct->config_info);
+free_addr:
+ free(ct->client_addr);
+free_dev:
+ udev_device_unref(bus_dev);
+free_udev:
+ udev_unref(udev);
+free_ct:
+ free(ct);
+ return 1;
+}
+
+void cleanup_context(struct rbd_checker_context *ct)
+{
+ pthread_mutex_destroy(&ct->lock);
+ pthread_cond_destroy(&ct->active);
+ pthread_spin_destroy(&ct->hldr_lock);
+
+ rados_shutdown(ct->cluster);
+
+ if (ct->username)
+ free(ct->username);
+ if (ct->snap)
+ free(ct->snap);
+ free(ct->pool);
+ free(ct->image);
+ free(ct->config_info);
+ free(ct->client_addr);
+ free(ct);
+}
+
+void libcheck_free(struct checker * c)
+{
+ if (c->context) {
+ struct rbd_checker_context *ct = c->context;
+ int holders;
+ pthread_t thread;
+
+ pthread_spin_lock(&ct->hldr_lock);
+ ct->holders--;
+ holders = ct->holders;
+ thread = ct->thread;
+ pthread_spin_unlock(&ct->hldr_lock);
+ if (holders)
+ pthread_cancel(thread);
+ else
+ cleanup_context(ct);
+ c->context = NULL;
+ }
+}
+
+static int rbd_is_blacklisted(struct rbd_checker_context *ct, char *msg)
+{
+ char *addr_tok, *start, *save;
+ char *cmd[2];
+ char *blklist, *stat;
+ size_t blklist_len, stat_len;
+ int ret;
+ char *end;
+
+ cmd[0] = "{\"prefix\": \"osd blacklist ls\"}";
+ cmd[1] = NULL;
+
+ ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0,
+ &blklist, &blklist_len, &stat, &stat_len);
+ if (ret < 0) {
+ RBD_MSG(msg, "rbd checker failed: mon command failed %d",
+ ret);
+ return ret;
+ }
+
+ if (!blklist || !blklist_len)
+ goto free_bufs;
+
+ /*
+ * parse list of addrs with the format
+ * ipv4:port/nonce date time\n
+ * or
+ * [ipv6]:port/nonce date time\n
+ */
+ ret = 0;
+ for (start = blklist; ; start = NULL) {
+ addr_tok = strtok_r(start, "\n", &save);
+ if (!addr_tok || !strlen(addr_tok))
+ break;
+
+ end = strchr(addr_tok, ' ');
+ if (!end) {
+ RBD_MSG(msg, "rbd%d checker failed: invalid blacklist %s",
+ ct->rbd_bus_id, addr_tok);
+ break;
+ }
+ *end = '\0';
+
+ if (!strcmp(addr_tok, ct->client_addr)) {
+ ct->blacklisted = 1;
+ RBD_MSG(msg, "rbd%d checker: %s is blacklisted",
+ ct->rbd_bus_id, ct->client_addr);
+ ret = 1;
+ break;
+ }
+ }
+
+free_bufs:
+ rados_buffer_free(blklist);
+ rados_buffer_free(stat);
+ return ret;
+}
+
+int rbd_check(struct rbd_checker_context *ct, char *msg)
+{
+ if (ct->blacklisted || rbd_is_blacklisted(ct, msg) == 1)
+ return PATH_DOWN;
+
+ RBD_MSG(msg, "rbd checker reports path is up");
+ /*
+ * Path may have issues, but the ceph cluster is at least
+ * accepting IO, so we can attempt to do IO.
+ *
+ * TODO: in future versions, we can run other tests to
+ * verify OSDs and networks.
+ */
+ return PATH_UP;
+}
+
+int safe_write(int fd, const void *buf, size_t count)
+{
+ while (count > 0) {
+ ssize_t r = write(fd, buf, count);
+ if (r < 0) {
+ if (errno == EINTR)
+ continue;
+ return -errno;
+ }
+ count -= r;
+ buf = (char *)buf + r;
+ }
+ return 0;
+}
+
+static int sysfs_write_rbd_bus(const char *which, const char *buf,
+ size_t buf_len)
+{
+ char sysfs_path[PATH_SIZE];
+ int fd;
+ int r;
+
+ /* we require newer kernels so single_major should alwayws be there */
+ snprintf(sysfs_path, sizeof(sysfs_path),
+ "/sys/bus/rbd/%s_single_major", which);
+ fd = open(sysfs_path, O_WRONLY);
+ if (fd < 0)
+ return -errno;
+
+ r = safe_write(fd, buf, buf_len);
+ close(fd);
+ return r;
+}
+
+static int rbd_remap(struct rbd_checker_context *ct)
+{
+ char *argv[11];
+ pid_t pid;
+ int ret = 0, i = 0;
+ int status;
+
+ pid = fork();
+ switch (pid) {
+ case 0:
+ argv[i++] = "rbd";
+ argv[i++] = "map";
+ argv[i++] = "-o noshare";
+ if (ct->username) {
+ argv[i++] = "--id";
+ argv[i++] = ct->username;
+ }
+ argv[i++] = "--pool";
+ argv[i++] = ct->pool;
+ if (ct->snap) {
+ argv[i++] = "--snap";
+ argv[i++] = ct->snap;
+ }
+ argv[i++] = ct->image;
+ argv[i] = NULL;
+
+ ret = execvp(argv[0], argv);
+ condlog(0, "Error executing rbd: %s", strerror(errno));
+ exit(-1);
+ case -1:
+ condlog(0, "fork failed: %s", strerror(errno));
+ return -1;
+ default:
+ ret = -1;
+ wait(&status);
+ if (WIFEXITED(status)) {
+ status = WEXITSTATUS(status);
+ if (status == 0)
+ ret = 0;
+ else
+ condlog(0, "rbd failed with %d", status);
+ }
+ }
+
+ return ret;
+}
+
+static int sysfs_write_rbd_remove(const char *buf, int buf_len)
+{
+ return sysfs_write_rbd_bus("remove", buf, buf_len);
+}
+
+static int rbd_rm_blacklist(struct rbd_checker_context *ct)
+{
+ char *cmd[2];
+ char *stat, *cmd_str;
+ size_t stat_len;
+ int ret;
+
+ ret = asprintf(&cmd_str, "{\"prefix\": \"osd blacklist\", \"blacklistop\": \"rm\", \"addr\": \"%s\"}",
+ ct->client_addr);
+ if (ret == -1)
+ return -ENOMEM;
+
+ cmd[0] = cmd_str;
+ cmd[1] = NULL;
+
+ ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0,
+ NULL, 0, &stat, &stat_len);
+ if (ret < 0) {
+ condlog(1, "rbd%d repair failed to remove blacklist for %s %d",
+ ct->rbd_bus_id, ct->client_addr, ret);
+ goto free_cmd;
+ }
+
+ condlog(1, "rbd%d repair rm blacklist for %s",
+ ct->rbd_bus_id, ct->client_addr);
+ free(stat);
+free_cmd:
+ free(cmd_str);
+ return ret;
+}
+
+static int rbd_repair(struct rbd_checker_context *ct, char *msg)
+{
+ char del[17];
+ int ret;
+
+ if (!ct->blacklisted)
+ return PATH_UP;
+
+ if (!ct->remapped) {
+ ret = rbd_remap(ct);
+ if (ret) {
+ RBD_MSG(msg, "rbd%d repair failed to remap. Err %d",
+ ct->rbd_bus_id, ret);
+ return PATH_DOWN;
+ }
+ }
+ ct->remapped = 1;
+
+ snprintf(del, sizeof(del), "%d force", ct->rbd_bus_id);
+ ret = sysfs_write_rbd_remove(del, strlen(del) + 1);
+ if (ret) {
+ RBD_MSG(msg, "rbd%d repair failed to clean up. Err %d",
+ ct->rbd_bus_id, ret);
+ return PATH_DOWN;
+ }
+
+ ret = rbd_rm_blacklist(ct);
+ if (ret) {
+ RBD_MSG(msg, "rbd%d repair could not remove blacklist entry. Err %d",
+ ct->rbd_bus_id, ret);
+ return PATH_DOWN;
+ }
+
+ ct->remapped = 0;
+ ct->blacklisted = 0;
+
+ RBD_MSG(msg, "rbd%d has been repaired", ct->rbd_bus_id);
+ return PATH_UP;
+}
+
+#define rbd_thread_cleanup_push(ct) pthread_cleanup_push(cleanup_func, ct)
+#define rbd_thread_cleanup_pop(ct) pthread_cleanup_pop(1)
+
+void cleanup_func(void *data)
+{
+ int holders;
+ struct rbd_checker_context *ct = data;
+ pthread_spin_lock(&ct->hldr_lock);
+ ct->holders--;
+ holders = ct->holders;
+ ct->thread = 0;
+ pthread_spin_unlock(&ct->hldr_lock);
+ if (!holders)
+ cleanup_context(ct);
+}
+
+void *rbd_thread(void *ctx)
+{
+ struct rbd_checker_context *ct = ctx;
+ int state;
+
+ condlog(3, "rbd%d thread starting up", ct->rbd_bus_id);
+
+ ct->message[0] = '\0';
+ /* This thread can be canceled, so setup clean up */
+ rbd_thread_cleanup_push(ct)
+
+ /* checker start up */
+ pthread_mutex_lock(&ct->lock);
+ ct->state = PATH_PENDING;
+ pthread_mutex_unlock(&ct->lock);
+
+ state = ct->fn(ct, ct->message);
+
+ /* checker done */
+ pthread_mutex_lock(&ct->lock);
+ ct->state = state;
+ pthread_mutex_unlock(&ct->lock);
+ pthread_cond_signal(&ct->active);
+
+ condlog(3, "rbd%d thead finished, state %s", ct->rbd_bus_id,
+ checker_state_name(state));
+ rbd_thread_cleanup_pop(ct);
+ return ((void *)0);
+}
+
+static void rbd_timeout(struct timespec *tsp)
+{
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ tsp->tv_sec = now.tv_sec;
+ tsp->tv_nsec = now.tv_usec * 1000;
+ tsp->tv_nsec += 1000000; /* 1 millisecond */
+}
+
+static int rbd_exec_fn(struct checker *c, thread_fn *fn)
+{
+ struct rbd_checker_context *ct = c->context;
+ struct timespec tsp;
+ pthread_attr_t attr;
+ int rbd_status, r;
+
+ if (c->sync)
+ return rbd_check(ct, c->message);
+ /*
+ * Async mode
+ */
+ r = pthread_mutex_lock(&ct->lock);
+ if (r != 0) {
+ condlog(2, "rbd%d mutex lock failed with %d", ct->rbd_bus_id,
+ r);
+ MSG(c, "rbd%d thread failed to initialize", ct->rbd_bus_id);
+ return PATH_WILD;
+ }
+
+ if (ct->running) {
+ /* Check if checker is still running */
+ if (ct->thread) {
+ condlog(3, "rbd%d thread not finished", ct->rbd_bus_id);
+ rbd_status = PATH_PENDING;
+ } else {
+ /* checker done */
+ ct->running = 0;
+ rbd_status = ct->state;
+ strncpy(c->message, ct->message, CHECKER_MSG_LEN);
+ c->message[CHECKER_MSG_LEN - 1] = '\0';
+ }
+ pthread_mutex_unlock(&ct->lock);
+ } else {
+ /* Start new checker */
+ ct->state = PATH_UNCHECKED;
+ ct->fn = fn;
+ pthread_spin_lock(&ct->hldr_lock);
+ ct->holders++;
+ pthread_spin_unlock(&ct->hldr_lock);
+ setup_thread_attr(&attr, 32 * 1024, 1);
+ r = pthread_create(&ct->thread, &attr, rbd_thread, ct);
+ if (r) {
+ pthread_mutex_unlock(&ct->lock);
+ ct->thread = 0;
+ ct->holders--;
+ condlog(3, "rbd%d failed to start rbd thread, using sync mode",
+ ct->rbd_bus_id);
+ return fn(ct, c->message);
+ }
+ pthread_attr_destroy(&attr);
+ rbd_timeout(&tsp);
+ r = pthread_cond_timedwait(&ct->active, &ct->lock, &tsp);
+ rbd_status = ct->state;
+ strncpy(c->message, ct->message,CHECKER_MSG_LEN);
+ c->message[CHECKER_MSG_LEN -1] = '\0';
+ pthread_mutex_unlock(&ct->lock);
+
+ if (ct->thread &&
+ (rbd_status == PATH_PENDING || rbd_status == PATH_UNCHECKED)) {
+ condlog(3, "rbd%d thread still running",
+ ct->rbd_bus_id);
+ ct->running = 1;
+ rbd_status = PATH_PENDING;
+ }
+ }
+
+ return rbd_status;
+}
+
+void libcheck_repair(struct checker * c)
+{
+ struct rbd_checker_context *ct = c->context;
+
+ if (!ct || !ct->blacklisted)
+ return;
+ rbd_exec_fn(c, rbd_repair);
+}
+
+int libcheck_check(struct checker * c)
+{
+ struct rbd_checker_context *ct = c->context;
+
+ if (!ct)
+ return PATH_UNCHECKED;
+
+ if (ct->blacklisted)
+ return PATH_DOWN;
+
+ return rbd_exec_fn(c, rbd_check);
+}
Index: multipath-tools-130222/multipath.conf.annotated
===================================================================
--- multipath-tools-130222.orig/multipath.conf.annotated
+++ multipath-tools-130222/multipath.conf.annotated
@@ -97,7 +97,7 @@
# # scope : multipath & multipathd
# # desc : the default method used to determine the paths' state
# # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac|
-# cciss_tur|hp_tur
+# cciss_tur|hp_tur|rbd
# # default : directio
# #
# path_checker directio
@@ -493,7 +493,7 @@
# # scope : multipathd & multipathd
# # desc : path checking algorithm to use to check path state
# # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac|
-# # cciss_tur|hp_tur
+# # cciss_tur|hp_tur|rbd
# #
# path_checker directio
#
Index: multipath-tools-130222/multipath/multipath.conf.5
===================================================================
--- multipath-tools-130222.orig/multipath/multipath.conf.5
+++ multipath-tools-130222/multipath/multipath.conf.5
@@ -284,6 +284,9 @@ Check the path state for LSI/Engenio/Net
.B directio
Read the first sector with direct I/O.
.TP
+.B rbd
+Check if the path is in the Ceph blacklist.
+.TP
Default value is \fIdirectio\fR.
.RE
.TP

View File

@ -0,0 +1,51 @@
From b25186a60347e2a0f2e53a10c05d9ad52a88c890 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Tue, 9 Aug 2016 13:53:21 -0500
Subject: [PATCH 05/11] multipath-tools: Add rbd to the hwtable
For BZ 1348372 from upstream commit:
commit 61fe9e521965ff70db6a65370b394d769077d54c
Author: Mike Christie <mchristi@redhat.com>
Date: Mon Aug 8 07:01:50 2016 -0500
multipath-tools: Add rbd to the hwtable
Add rbd to hwtable. These defaults are for the HA type of setup
supported by the checker. We do no support features like multibus
at the dm-multipath level yet
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/hwtable.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 61d1033..d278c04 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -1206,6 +1206,21 @@ static struct hwentry default_hw[] = {
.pgfailback = -FAILBACK_IMMEDIATE,
.checker_name = TUR,
},
+ {
+ /*
+ * Red Hat
+ *
+ * Maintainer: Mike Christie
+ * Mail: mchristi@redhat.com
+ */
+ .vendor = "Ceph",
+ .product = "RBD",
+ .pgpolicy = FAILOVER,
+ .no_path_retry = NO_PATH_RETRY_FAIL,
+ .checker_name = RBD,
+ .deferred_remove = DEFERRED_REMOVE_ON,
+ },
+
/*
* EOL
*/
--
1.8.3.1

View File

@ -0,0 +1,49 @@
From 7592f62383e6143a54d89885e505834c4977c4a6 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Tue, 16 Aug 2016 11:44:27 -0500
Subject: [PATCH 06/11] multipath-tools: check for initialized checker before
For bz from upstream commit:
commit b5773d46a4550c3c222bb415197e0bc5f09c1169
Author: Mike Christie <mchristi@redhat.com>
Date: Mon Aug 15 12:13:45 2016 -0500
multipath-tools: check for initialized checker before
This fixes a regression added with:
015f87b16a7797a17afd514aec46e65c2a1a2f73
We can hit a race where when pathinfo is setting up a path, the path
could have gone down already. In the DI_CHECKER chunk we then do not
run
get_state and attach a checker. Later when check_path is run
path_offline could still return PATH_DOWN or PATH_REMOVED and
get_state is again not run so we do not get to attach a checker. I
was then running repair_path since the state was PATH_DOWN, and we
then
hit a segfault.
This has us test if a checker is selected before running repair.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index fa7d8b7..6cd8d34 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -212,7 +212,7 @@ void checker_put (struct checker * dst)
void checker_repair (struct checker * c)
{
- if (!c)
+ if (!c || !checker_selected(c))
return;
c->message[0] = '\0';
--
1.8.3.1

View File

@ -0,0 +1,91 @@
From 2926316c8492a1d18c7bbdac0fac75c38ce16152 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Tue, 16 Aug 2016 11:47:16 -0500
Subject: [PATCH 07/11] multipathd: Don't call repair on blacklisted path
For BZ 1348372 from upstream commit:
Author: Mike Christie <mchristi@redhat.com>
Date: Mon Aug 15 12:13:46 2016 -0500
multipathd: Don't call repair on blacklisted paths
This fixes a regression added in
015f87b16a7797a17afd514aec46e65c2a1a2f73
If a path is blacklisted the checkerloop will free the path so
don't call repair on it.
This moves the repair call down into check_path, because I think
we also do not need to call it for other cases where we cannot get
the uuid info or being orphaned.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
multipathd/main.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index d26fd22..4638c8b 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1238,6 +1238,16 @@ int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh)
return 0;
}
+void repair_path(struct path * pp)
+{
+ if (pp->state != PATH_DOWN)
+ return;
+
+ checker_repair(&pp->checker);
+ if (strlen(checker_message(&pp->checker)))
+ LOG_MSG(1, checker_message(&pp->checker));
+}
+
void
check_path (struct vectors * vecs, struct path * pp)
{
@@ -1352,6 +1362,7 @@ check_path (struct vectors * vecs, struct path * pp)
pp->mpp->failback_tick = 0;
pp->mpp->stat_path_failures++;
+ repair_path(pp);
return;
}
@@ -1431,7 +1442,7 @@ check_path (struct vectors * vecs, struct path * pp)
}
pp->state = newstate;
-
+ repair_path(pp);
if (pp->mpp->wait_for_udev)
return;
@@ -1455,14 +1466,6 @@ check_path (struct vectors * vecs, struct path * pp)
}
}
-void repair_path(struct vectors * vecs, struct path * pp)
-{
- if (pp->state != PATH_DOWN)
- return;
-
- checker_repair(&pp->checker);
-}
-
static void *
checkerloop (void *ap)
{
@@ -1491,7 +1494,6 @@ checkerloop (void *ap)
if (vecs->pathvec) {
vector_foreach_slot (vecs->pathvec, pp, i) {
check_path(vecs, pp);
- repair_path(vecs, pp);
}
}
if (vecs->mpvec) {
--
1.8.3.1

View File

@ -0,0 +1,29 @@
From d1bda720153b4978121fbae40f82d2f4b9aff997 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Thu, 25 Aug 2016 01:34:11 -0500
Subject: [PATCH 08/11] rbd: fix sync repair support
If sync was set we were calling check instead
of function passed in.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers/rbd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c
index 6f1b53a..76f4005 100644
--- a/libmultipath/checkers/rbd.c
+++ b/libmultipath/checkers/rbd.c
@@ -554,7 +554,7 @@ static int rbd_exec_fn(struct checker *c, thread_fn *fn)
int rbd_status, r;
if (c->sync)
- return rbd_check(ct, c->message);
+ return fn(ct, c->message);
/*
* Async mode
*/
--
1.8.3.1

View File

@ -0,0 +1,32 @@
From c9a788f437f2729f943cd03c43e84b65d74eb015 Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Wed, 31 Aug 2016 15:22:09 -0500
Subject: [PATCH 09/11] rbd: check for nonshared clients
The rbd checker only supports nonshared clients so add a check
during init time.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers/rbd.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c
index 76f4005..a6f3405 100644
--- a/libmultipath/checkers/rbd.c
+++ b/libmultipath/checkers/rbd.c
@@ -123,6 +123,11 @@ int libcheck_init(struct checker * c)
if (!config_info)
goto free_addr;
+ if (!strstr(config_info, "noshare")) {
+ condlog(3, "Only nonshared clients supported.");
+ goto free_addr;
+ }
+
ct->config_info = strdup(config_info);
if (!ct->config_info)
goto free_addr;
--
1.8.3.1

View File

@ -0,0 +1,56 @@
From 513d210cdbccfdaadb0cf7f09ba97d563aac52bb Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Wed, 31 Aug 2016 15:40:16 -0500
Subject: [PATCH 10/11] rbd: check for exclusive lock enabled
Only attach the checker if the rbd image has the exclusive lock
enabled.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers/rbd.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c
index a6f3405..e34bf53 100644
--- a/libmultipath/checkers/rbd.c
+++ b/libmultipath/checkers/rbd.c
@@ -33,6 +33,8 @@ typedef int (thread_fn)(struct rbd_checker_context *ct, char *msg);
#define RBD_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args);
+#define RBD_FEATURE_EXCLUSIVE_LOCK (1 << 2)
+
struct rbd_checker_context {
int rbd_bus_id;
char *client_addr;
@@ -65,8 +67,9 @@ int libcheck_init(struct checker * c)
struct udev_device *bus_dev;
struct udev *udev;
struct stat sb;
- const char *block_name, *addr, *config_info;
+ const char *block_name, *addr, *config_info, *features_str;
const char *image, *pool, *snap, *username;
+ uint64_t features = 0;
char sysfs_path[PATH_SIZE];
int ret;
@@ -119,6 +122,15 @@ int libcheck_init(struct checker * c)
if (!ct->client_addr)
goto free_dev;
+ features_str = udev_device_get_sysattr_value(bus_dev, "features");
+ if (!features_str)
+ goto free_addr;
+ features = strtoll(features_str, NULL, 16);
+ if (!(features & RBD_FEATURE_EXCLUSIVE_LOCK)) {
+ condlog(3, "Exclusive lock not set.");
+ goto free_addr;
+ }
+
config_info = udev_device_get_sysattr_value(bus_dev, "config_info");
if (!config_info)
goto free_addr;
--
1.8.3.1

View File

@ -0,0 +1,238 @@
From 3ed9a923904887e41c774c71232ae2a1ff6fc3fb Mon Sep 17 00:00:00 2001
From: Mike Christie <mchristi@redhat.com>
Date: Wed, 31 Aug 2016 15:59:53 -0500
Subject: [PATCH 11/11] rbd: fixup log messages
Add rbd device prefix to condlog messages that was missing it, and drop
it in RBD_MSG because it is already added by caller.
Signed-off-by: Mike Christie <mchristi@redhat.com>
---
libmultipath/checkers/rbd.c | 67 +++++++++++++++++++++++----------------------
1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c
index e34bf53..8e6cd3c 100644
--- a/libmultipath/checkers/rbd.c
+++ b/libmultipath/checkers/rbd.c
@@ -113,8 +113,8 @@ int libcheck_init(struct checker * c)
addr = udev_device_get_sysattr_value(bus_dev, "client_addr");
if (!addr) {
- condlog(0, "Could not find client_addr in rbd sysfs. Try "
- "updating kernel");
+ condlog(0, "rbd%d: Could not find client_addr in rbd sysfs. "
+ "Try updating kernel", ct->rbd_bus_id);
goto free_dev;
}
@@ -127,7 +127,7 @@ int libcheck_init(struct checker * c)
goto free_addr;
features = strtoll(features_str, NULL, 16);
if (!(features & RBD_FEATURE_EXCLUSIVE_LOCK)) {
- condlog(3, "Exclusive lock not set.");
+ condlog(3, "rbd%d: Exclusive lock not set.", ct->rbd_bus_id);
goto free_addr;
}
@@ -136,7 +136,8 @@ int libcheck_init(struct checker * c)
goto free_addr;
if (!strstr(config_info, "noshare")) {
- condlog(3, "Only nonshared clients supported.");
+ condlog(3, "rbd%d: Only nonshared clients supported.",
+ ct->rbd_bus_id);
goto free_addr;
}
@@ -189,18 +190,20 @@ int libcheck_init(struct checker * c)
}
if (rados_create(&ct->cluster, NULL) < 0) {
- condlog(0, "Could not create rados cluster");
+ condlog(0, "rbd%d: Could not create rados cluster",
+ ct->rbd_bus_id);
goto free_snap;
}
if (rados_conf_read_file(ct->cluster, NULL) < 0) {
- condlog(0, "Could not read rados conf");
+ condlog(0, "rbd%d: Could not read rados conf", ct->rbd_bus_id);
goto shutdown_rados;
}
ret = rados_connect(ct->cluster);
if (ret < 0) {
- condlog(0, "Could not connect to rados cluster");
+ condlog(0, "rbd%d: Could not connect to rados cluster",
+ ct->rbd_bus_id);
goto shutdown_rados;
}
@@ -291,8 +294,7 @@ static int rbd_is_blacklisted(struct rbd_checker_context *ct, char *msg)
ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0,
&blklist, &blklist_len, &stat, &stat_len);
if (ret < 0) {
- RBD_MSG(msg, "rbd checker failed: mon command failed %d",
- ret);
+ RBD_MSG(msg, "checker failed: mon command failed %d", ret);
return ret;
}
@@ -313,16 +315,15 @@ static int rbd_is_blacklisted(struct rbd_checker_context *ct, char *msg)
end = strchr(addr_tok, ' ');
if (!end) {
- RBD_MSG(msg, "rbd%d checker failed: invalid blacklist %s",
- ct->rbd_bus_id, addr_tok);
+ RBD_MSG(msg, "checker failed: invalid blacklist %s",
+ addr_tok);
break;
}
*end = '\0';
if (!strcmp(addr_tok, ct->client_addr)) {
ct->blacklisted = 1;
- RBD_MSG(msg, "rbd%d checker: %s is blacklisted",
- ct->rbd_bus_id, ct->client_addr);
+ RBD_MSG(msg, "%s is blacklisted", ct->client_addr);
ret = 1;
break;
}
@@ -339,7 +340,7 @@ int rbd_check(struct rbd_checker_context *ct, char *msg)
if (ct->blacklisted || rbd_is_blacklisted(ct, msg) == 1)
return PATH_DOWN;
- RBD_MSG(msg, "rbd checker reports path is up");
+ RBD_MSG(msg, "checker reports path is up");
/*
* Path may have issues, but the ceph cluster is at least
* accepting IO, so we can attempt to do IO.
@@ -411,10 +412,12 @@ static int rbd_remap(struct rbd_checker_context *ct)
argv[i] = NULL;
ret = execvp(argv[0], argv);
- condlog(0, "Error executing rbd: %s", strerror(errno));
+ condlog(0, "rbd%d: Error executing rbd: %s", ct->rbd_bus_id,
+ strerror(errno));
exit(-1);
case -1:
- condlog(0, "fork failed: %s", strerror(errno));
+ condlog(0, "rbd%d: fork failed: %s", ct->rbd_bus_id,
+ strerror(errno));
return -1;
default:
ret = -1;
@@ -424,7 +427,8 @@ static int rbd_remap(struct rbd_checker_context *ct)
if (status == 0)
ret = 0;
else
- condlog(0, "rbd failed with %d", status);
+ condlog(0, "rbd%d: failed with %d",
+ ct->rbd_bus_id, status);
}
}
@@ -454,12 +458,12 @@ static int rbd_rm_blacklist(struct rbd_checker_context *ct)
ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0,
NULL, 0, &stat, &stat_len);
if (ret < 0) {
- condlog(1, "rbd%d repair failed to remove blacklist for %s %d",
+ condlog(1, "rbd%d: repair failed to remove blacklist for %s %d",
ct->rbd_bus_id, ct->client_addr, ret);
goto free_cmd;
}
- condlog(1, "rbd%d repair rm blacklist for %s",
+ condlog(1, "rbd%d: repair rm blacklist for %s",
ct->rbd_bus_id, ct->client_addr);
free(stat);
free_cmd:
@@ -478,8 +482,7 @@ static int rbd_repair(struct rbd_checker_context *ct, char *msg)
if (!ct->remapped) {
ret = rbd_remap(ct);
if (ret) {
- RBD_MSG(msg, "rbd%d repair failed to remap. Err %d",
- ct->rbd_bus_id, ret);
+ RBD_MSG(msg, "repair failed to remap. Err %d", ret);
return PATH_DOWN;
}
}
@@ -488,22 +491,21 @@ static int rbd_repair(struct rbd_checker_context *ct, char *msg)
snprintf(del, sizeof(del), "%d force", ct->rbd_bus_id);
ret = sysfs_write_rbd_remove(del, strlen(del) + 1);
if (ret) {
- RBD_MSG(msg, "rbd%d repair failed to clean up. Err %d",
- ct->rbd_bus_id, ret);
+ RBD_MSG(msg, "repair failed to clean up. Err %d", ret);
return PATH_DOWN;
}
ret = rbd_rm_blacklist(ct);
if (ret) {
- RBD_MSG(msg, "rbd%d repair could not remove blacklist entry. Err %d",
- ct->rbd_bus_id, ret);
+ RBD_MSG(msg, "repair could not remove blacklist entry. Err %d",
+ ret);
return PATH_DOWN;
}
ct->remapped = 0;
ct->blacklisted = 0;
- RBD_MSG(msg, "rbd%d has been repaired", ct->rbd_bus_id);
+ RBD_MSG(msg, "has been repaired");
return PATH_UP;
}
@@ -528,7 +530,7 @@ void *rbd_thread(void *ctx)
struct rbd_checker_context *ct = ctx;
int state;
- condlog(3, "rbd%d thread starting up", ct->rbd_bus_id);
+ condlog(3, "rbd%d: thread starting up", ct->rbd_bus_id);
ct->message[0] = '\0';
/* This thread can be canceled, so setup clean up */
@@ -547,7 +549,7 @@ void *rbd_thread(void *ctx)
pthread_mutex_unlock(&ct->lock);
pthread_cond_signal(&ct->active);
- condlog(3, "rbd%d thead finished, state %s", ct->rbd_bus_id,
+ condlog(3, "rbd%d: thead finished, state %s", ct->rbd_bus_id,
checker_state_name(state));
rbd_thread_cleanup_pop(ct);
return ((void *)0);
@@ -577,16 +579,17 @@ static int rbd_exec_fn(struct checker *c, thread_fn *fn)
*/
r = pthread_mutex_lock(&ct->lock);
if (r != 0) {
- condlog(2, "rbd%d mutex lock failed with %d", ct->rbd_bus_id,
+ condlog(2, "rbd%d: mutex lock failed with %d", ct->rbd_bus_id,
r);
- MSG(c, "rbd%d thread failed to initialize", ct->rbd_bus_id);
+ MSG(c, "rbd%d: thread failed to initialize", ct->rbd_bus_id);
return PATH_WILD;
}
if (ct->running) {
/* Check if checker is still running */
if (ct->thread) {
- condlog(3, "rbd%d thread not finished", ct->rbd_bus_id);
+ condlog(3, "rbd%d: thread not finished",
+ ct->rbd_bus_id);
rbd_status = PATH_PENDING;
} else {
/* checker done */
@@ -623,7 +626,7 @@ static int rbd_exec_fn(struct checker *c, thread_fn *fn)
if (ct->thread &&
(rbd_status == PATH_PENDING || rbd_status == PATH_UNCHECKED)) {
- condlog(3, "rbd%d thread still running",
+ condlog(3, "rbd%d: thread still running",
ct->rbd_bus_id);
ct->running = 1;
rbd_status = PATH_PENDING;
--
1.8.3.1

View File

@ -0,0 +1,208 @@
---
libmultipath/configure.c | 8 +++--
multipathd/main.c | 68 +++++++++++++++++++++++++++++++++++++----------
2 files changed, 59 insertions(+), 17 deletions(-)
Index: multipath-tools-130222/libmultipath/configure.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/configure.c
+++ multipath-tools-130222/libmultipath/configure.c
@@ -829,8 +829,10 @@ coalesce_paths (struct vectors * vecs, v
* at this point, we know we really got a new mp
*/
mpp = add_map_with_path(vecs, pp1, 0);
- if (!mpp)
- return 1;
+ if (!mpp) {
+ orphan_path(pp1);
+ continue;
+ }
if (pp1->priority == PRIO_UNDEF)
mpp->action = ACT_REJECT;
@@ -879,7 +881,7 @@ coalesce_paths (struct vectors * vecs, v
condlog(3, "%s: domap (%u) failure "
"for create/reload map",
mpp->alias, r);
- if (r == DOMAP_FAIL) {
+ if (r == DOMAP_FAIL || conf->daemon) {
condlog(2, "%s: %s map",
mpp->alias, (mpp->action == ACT_CREATE)?
"ignoring" : "removing");
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -821,7 +821,7 @@ map_discovery (struct vectors * vecs)
vector_foreach_slot (vecs->mpvec, mpp, i)
if (setup_multipath(vecs, mpp))
- return 1;
+ i--;
return 0;
}
@@ -1523,21 +1523,29 @@ configure (struct vectors * vecs, int st
vector mpvec;
int i, ret;
- if (!vecs->pathvec && !(vecs->pathvec = vector_alloc()))
+ if (!vecs->pathvec && !(vecs->pathvec = vector_alloc())) {
+ condlog(0, "couldn't allocate path vec in configure");
return 1;
+ }
- if (!vecs->mpvec && !(vecs->mpvec = vector_alloc()))
+ if (!vecs->mpvec && !(vecs->mpvec = vector_alloc())) {
+ condlog(0, "couldn't allocate multipath vec in configure");
return 1;
+ }
- if (!(mpvec = vector_alloc()))
+ if (!(mpvec = vector_alloc())) {
+ condlog(0, "couldn't allocate new maps vec in configure");
return 1;
+ }
/*
* probe for current path (from sysfs) and map (from dm) sets
*/
ret = path_discovery(vecs->pathvec, conf, DI_ALL);
- if (ret < 0)
+ if (ret < 0) {
+ condlog(0, "configure failed at path discovery");
return 1;
+ }
vector_foreach_slot (vecs->pathvec, pp, i){
if (filter_path(conf, pp) > 0){
@@ -1548,21 +1556,27 @@ configure (struct vectors * vecs, int st
else
pp->checkint = conf->checkint;
}
- if (map_discovery(vecs))
+ if (map_discovery(vecs)) {
+ condlog(0, "configure failed at map discovery");
return 1;
+ }
/*
* create new set of maps & push changed ones into dm
*/
- if (coalesce_paths(vecs, mpvec, NULL, 1))
+ if (coalesce_paths(vecs, mpvec, NULL, 1)) {
+ condlog(0, "configure failed while coalescing paths");
return 1;
+ }
/*
* may need to remove some maps which are no longer relevant
* e.g., due to blacklist changes in conf file
*/
- if (coalesce_maps(vecs, mpvec))
+ if (coalesce_maps(vecs, mpvec)) {
+ condlog(0, "configure failed while coalescing maps");
return 1;
+ }
dm_lib_release();
@@ -1588,11 +1602,15 @@ configure (struct vectors * vecs, int st
* start dm event waiter threads for these new maps
*/
vector_foreach_slot(vecs->mpvec, mpp, i) {
- if (setup_multipath(vecs, mpp))
- return 1;
+ if (setup_multipath(vecs, mpp)) {
+ i--;
+ continue;
+ }
if (start_waiters)
- if (start_waiter_thread(mpp, vecs))
- return 1;
+ if (start_waiter_thread(mpp, vecs)) {
+ remove_map(mpp, vecs, 1);
+ i--;
+ }
}
return 0;
}
@@ -1857,15 +1875,23 @@ child (void * param)
condlog(2, "--------start up--------");
condlog(2, "read " DEFAULT_CONFIGFILE);
- if (load_config(DEFAULT_CONFIGFILE, udev))
+ if (load_config(DEFAULT_CONFIGFILE, udev)) {
+ condlog(0, "failed to load config");
+ if (logsink)
+ log_thread_stop();
exit(1);
+ }
if (init_checkers()) {
condlog(0, "failed to initialize checkers");
+ if (logsink)
+ log_thread_stop();
exit(1);
}
if (init_prio()) {
condlog(0, "failed to initialize prioritizers");
+ if (logsink)
+ log_thread_stop();
exit(1);
}
@@ -1898,8 +1924,12 @@ child (void * param)
}
vecs = gvecs = init_vecs();
- if (!vecs)
+ if (!vecs) {
+ condlog(0, "failed to create vecs");
+ if (logsink)
+ log_thread_stop();
exit(1);
+ }
setscheduler();
set_oom_adj();
@@ -1911,11 +1941,15 @@ child (void * param)
*/
if ((rc = pthread_create(&uevent_thr, &uevent_attr, ueventloop, udev))) {
condlog(0, "failed to create uevent thread: %d", rc);
+ if (logsink)
+ log_thread_stop();
exit(1);
}
pthread_attr_destroy(&uevent_attr);
if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) {
condlog(0, "failed to create cli listener: %d", rc);
+ if (logsink)
+ log_thread_stop();
exit(1);
}
/*
@@ -1927,6 +1961,8 @@ child (void * param)
if (configure(vecs, 1)) {
unlock(vecs->lock);
condlog(0, "failure during configuration");
+ if (logsink)
+ log_thread_stop();
exit(1);
}
unlock(vecs->lock);
@@ -1936,10 +1972,14 @@ child (void * param)
*/
if ((rc = pthread_create(&check_thr, &misc_attr, checkerloop, vecs))) {
condlog(0,"failed to create checker loop thread: %d", rc);
+ if (logsink)
+ log_thread_stop();
exit(1);
}
if ((rc = pthread_create(&uevq_thr, &misc_attr, uevqloop, vecs))) {
condlog(0, "failed to create uevent dispatcher: %d", rc);
+ if (logsink)
+ log_thread_stop();
exit(1);
}
pthread_attr_destroy(&misc_attr);

View File

@ -0,0 +1,168 @@
---
libmultipath/config.c | 1 +
libmultipath/config.h | 1 +
libmultipath/devmapper.c | 35 +++++++++++++++++++----------------
libmultipath/dict.c | 25 +++++++++++++++++++++++++
multipath.conf.defaults | 1 +
multipath/multipath.conf.5 | 5 +++++
6 files changed, 52 insertions(+), 16 deletions(-)
Index: multipath-tools-130222/libmultipath/devmapper.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/devmapper.c
+++ multipath-tools-130222/libmultipath/devmapper.c
@@ -803,10 +803,11 @@ dm_flush_map_nopaths(const char * mapnam
extern int
dm_suspend_and_flush_map (const char * mapname)
{
- int s = 0, queue_if_no_path = 0;
+ int need_reset = 0, queue_if_no_path = 0;
unsigned long long mapsize;
char params[PARAMS_SIZE] = {0};
int udev_flags = 0;
+ int retries = conf->remove_retries;
if (!dm_is_mpath(mapname))
return 0; /* nothing to do */
@@ -821,22 +822,24 @@ dm_suspend_and_flush_map (const char * m
queue_if_no_path = 1;
}
- if (queue_if_no_path)
- s = dm_queue_if_no_path((char *)mapname, 0);
- /* Leave queue_if_no_path alone if unset failed */
- if (s)
- queue_if_no_path = 0;
- else
- s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0, 0);
-
- if (!dm_flush_map(mapname)) {
- condlog(4, "multipath map %s removed", mapname);
- return 0;
- }
+ if (queue_if_no_path && dm_queue_if_no_path((char *)mapname, 0) == 0)
+ need_reset = 1;
+
+ do {
+ if (!queue_if_no_path || need_reset)
+ dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0, 0);
+
+ if (!dm_flush_map(mapname)) {
+ condlog(4, "multipath map %s removed", mapname);
+ return 0;
+ }
+ dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, udev_flags);
+ if (retries)
+ sleep(1);
+ } while (retries-- > 0);
condlog(2, "failed to remove multipath map %s", mapname);
- dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, udev_flags);
- if (queue_if_no_path)
- s = dm_queue_if_no_path((char *)mapname, 1);
+ if (need_reset)
+ dm_queue_if_no_path((char *)mapname, 1);
return 1;
}
Index: multipath-tools-130222/libmultipath/config.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.c
+++ multipath-tools-130222/libmultipath/config.c
@@ -680,6 +680,7 @@ load_config (char * file, struct udev *u
conf->new_bindings_in_boot = 0;
conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
conf->skip_kpartx = DEFAULT_SKIP_KPARTX;
+ conf->remove_retries = 0;
/*
* preload default hwtable
Index: multipath-tools-130222/libmultipath/config.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.h
+++ multipath-tools-130222/libmultipath/config.h
@@ -146,6 +146,7 @@ struct config {
int delayed_reconfig;
int uev_wait_timeout;
int skip_kpartx;
+ int remove_retries;
unsigned int version[3];
char * dev;
Index: multipath-tools-130222/libmultipath/dict.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/dict.c
+++ multipath-tools-130222/libmultipath/dict.c
@@ -935,6 +935,24 @@ def_new_bindings_in_boot_handler(vector
return 0;
}
+static int
+def_remove_retries_handler(vector strvec)
+{
+ char *buff;
+
+ buff = set_value(strvec);
+
+ if (!buff)
+ return 1;
+
+ conf->remove_retries = atoi(buff);
+ if (conf->remove_retries < 0)
+ conf->remove_retries = 0;
+ FREE(buff);
+
+ return 0;
+}
+
/*
* blacklist block handlers
*/
@@ -3405,6 +3423,12 @@ snprint_def_new_bindings_in_boot(char *
}
static int
+snprint_def_remove_retries (char * buff, int len, void * data)
+{
+ return snprintf(buff, len, "%i", conf->remove_retries);
+}
+
+static int
snprint_ble_simple (char * buff, int len, void * data)
{
struct blentry * ble = (struct blentry *)data;
@@ -3483,6 +3507,7 @@ init_keywords(void)
install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay);
install_keyword("missing_uev_wait_timeout", &def_uev_wait_timeout_handler, &snprint_def_uev_wait_timeout);
install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot);
+ install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries);
__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);
Index: multipath-tools-130222/multipath.conf.defaults
===================================================================
--- multipath-tools-130222.orig/multipath.conf.defaults
+++ multipath-tools-130222/multipath.conf.defaults
@@ -41,6 +41,7 @@
# retrigger_delay 10
# missing_uev_wait_timeout 30
# new_bindings_in_boot no
+# remove_retries 0
#}
#blacklist {
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
Index: multipath-tools-130222/multipath/multipath.conf.5
===================================================================
--- multipath-tools-130222.orig/multipath/multipath.conf.5
+++ multipath-tools-130222/multipath/multipath.conf.5
@@ -556,6 +556,11 @@ user_friendly_names. When multipathd is
regular filesystem, the device will be renamed to a user_friendly_name. The
default is
.I no
+.TP
+.B remove_retries
+This sets how may times multipath will retry removing a device that is in-use.
+Between each attempt, multipath will sleep 1 second. The default is
+.I 0
.
.SH "blacklist section"
The

View File

@ -0,0 +1,38 @@
---
libmultipath/checkers/rbd.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
Index: multipath-tools-130222/libmultipath/checkers/rbd.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/checkers/rbd.c
+++ multipath-tools-130222/libmultipath/checkers/rbd.c
@@ -45,6 +45,7 @@ struct rbd_checker_context {
char *username;
int remapped;
int blacklisted;
+ int lock_on_read:1;
rados_t cluster;
@@ -141,6 +142,9 @@ int libcheck_init(struct checker * c)
goto free_addr;
}
+ if (strstr(config_info, "lock_on_read"))
+ ct->lock_on_read = 1;
+
ct->config_info = strdup(config_info);
if (!ct->config_info)
goto free_addr;
@@ -397,7 +401,10 @@ static int rbd_remap(struct rbd_checker_
case 0:
argv[i++] = "rbd";
argv[i++] = "map";
- argv[i++] = "-o noshare";
+ if (ct->lock_on_read)
+ argv[i++] = "-o noshare,lock_on_read";
+ else
+ argv[i++] = "-o noshare";
if (ct->username) {
argv[i++] = "--id";
argv[i++] = ct->username;

View File

@ -0,0 +1,210 @@
---
libmultipath/config.c | 1 +
libmultipath/config.h | 1 +
libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++
libmultipath/discovery.c | 11 ++++++-----
libmultipath/discovery.h | 1 +
libmultipath/structs.h | 1 +
multipathd/main.c | 26 ++++++++++++++++++++++++++
7 files changed, 69 insertions(+), 5 deletions(-)
Index: multipath-tools-130222/libmultipath/discovery.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.c
+++ multipath-tools-130222/libmultipath/discovery.c
@@ -1155,8 +1155,8 @@ free_dev:
return ret;
}
-static int
-get_uid (struct path * pp)
+int
+get_uid (struct path * pp, struct udev_device *udev)
{
char *c;
const char *value;
@@ -1165,7 +1165,7 @@ get_uid (struct path * pp)
if (!pp->uid_attribute)
select_getuid(pp);
- if (!pp->udev) {
+ if (!udev) {
condlog(1, "%s: no udev information", pp->dev);
return 1;
}
@@ -1180,7 +1180,7 @@ get_uid (struct path * pp)
pp->tick = conf->retrigger_delay;
}
} else {
- value = udev_device_get_property_value(pp->udev,
+ value = udev_device_get_property_value(udev,
pp->uid_attribute);
if ((!value || strlen(value) == 0) &&
conf->cmd == CMD_VALID_PATH)
@@ -1194,6 +1194,7 @@ get_uid (struct path * pp)
len = strlen(value);
}
strncpy(pp->wwid, value, len);
+ condlog(4, "%s: got wwid of '%s'", pp->dev, pp->wwid);
pp->missing_udev_info = INFO_OK;
pp->tick = 0;
} else {
@@ -1282,7 +1283,7 @@ pathinfo (struct path *pp, vector hwtabl
}
if ((mask & DI_WWID) && !strlen(pp->wwid))
- get_uid(pp);
+ get_uid(pp, pp->udev);
if (mask & DI_BLACKLIST && mask & DI_WWID) {
if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
pp->wwid) > 0) {
Index: multipath-tools-130222/libmultipath/discovery.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.h
+++ multipath-tools-130222/libmultipath/discovery.h
@@ -44,6 +44,7 @@ int sysfs_set_scsi_tmo (struct multipath
int sysfs_get_timeout(struct path *pp, unsigned int *timeout);
int sysfs_get_host_pci_name(struct path *pp, char *pci_name);
int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address);
+int get_uid (struct path * pp, struct udev_device *udev);
/*
* discovery bitmask
Index: multipath-tools-130222/libmultipath/structs.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/structs.h
+++ multipath-tools-130222/libmultipath/structs.h
@@ -209,6 +209,7 @@ struct path {
int fd;
int missing_udev_info;
int retriggers;
+ int wwid_changed;
/* configlet pointers */
struct hwentry * hwe;
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -784,6 +784,26 @@ uev_update_path (struct uevent *uev, str
if (pp->missing_udev_info == INFO_REQUESTED)
return uev_add_path(uev, vecs);
+ if (conf->disable_changed_wwids &&
+ (strlen(pp->wwid) || pp->wwid_changed)) {
+ char wwid[WWID_SIZE];
+
+ strcpy(wwid, pp->wwid);
+ get_uid(pp, uev->udev);
+ if (strcmp(wwid, pp->wwid) != 0) {
+ condlog(0, "%s: path wwid changed from '%s' to '%s'. disallowing", uev->kernel, wwid, pp->wwid);
+ strcpy(pp->wwid, wwid);
+ if (!pp->wwid_changed) {
+ pp->wwid_changed = 1;
+ pp->tick = 1;
+ dm_fail_path(pp->mpp->alias, pp->dev_t);
+ }
+ }
+ else {
+ pp->wwid_changed = 0;
+ }
+ }
+
/* reinit the prio values on change event, in case something is
* different */
prio_init(&pp->prio);
@@ -1284,6 +1304,12 @@ check_path (struct vectors * vecs, struc
else
checker_clear_message(&pp->checker);
+ if (pp->wwid_changed) {
+ condlog(2, "%s: path wwid has changed. Refusing to use",
+ pp->dev);
+ newstate = PATH_DOWN;
+ }
+
if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) {
condlog(2, "%s: unusable path", pp->dev);
pathinfo(pp, conf->hwtable, 0);
Index: multipath-tools-130222/libmultipath/config.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.c
+++ multipath-tools-130222/libmultipath/config.c
@@ -681,6 +681,7 @@ load_config (char * file, struct udev *u
conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
conf->skip_kpartx = DEFAULT_SKIP_KPARTX;
conf->remove_retries = 0;
+ conf->disable_changed_wwids = 0;
/*
* preload default hwtable
Index: multipath-tools-130222/libmultipath/config.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.h
+++ multipath-tools-130222/libmultipath/config.h
@@ -147,6 +147,7 @@ struct config {
int uev_wait_timeout;
int skip_kpartx;
int remove_retries;
+ int disable_changed_wwids;
unsigned int version[3];
char * dev;
Index: multipath-tools-130222/libmultipath/dict.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/dict.c
+++ multipath-tools-130222/libmultipath/dict.c
@@ -953,6 +953,29 @@ def_remove_retries_handler(vector strvec
return 0;
}
+static int
+def_disable_changed_wwids_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->disable_changed_wwids = 0;
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
+ conf->disable_changed_wwids = 1;
+ else
+ conf->disable_changed_wwids = 0;
+
+ FREE(buff);
+ return 0;
+}
+
/*
* blacklist block handlers
*/
@@ -3429,6 +3452,15 @@ snprint_def_remove_retries (char * buff,
}
static int
+snprint_def_disable_changed_wwids(char * buff, int len, void * data)
+{
+ if (conf->disable_changed_wwids == 1)
+ 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;
@@ -3508,6 +3540,7 @@ init_keywords(void)
install_keyword("missing_uev_wait_timeout", &def_uev_wait_timeout_handler, &snprint_def_uev_wait_timeout);
install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot);
install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries);
+ install_keyword("disable_changed_wwids", &def_disable_changed_wwids_handler, &snprint_def_disable_changed_wwids);
__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);

View File

@ -0,0 +1,34 @@
---
libmultipath/hwtable.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
Index: multipath-tools-130222/libmultipath/hwtable.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/hwtable.c
+++ multipath-tools-130222/libmultipath/hwtable.c
@@ -1168,6 +1168,25 @@ static struct hwentry default_hw[] = {
.prio_name = PRIO_ALUA,
.prio_args = NULL,
},
+ /*
+ * Infinidat
+ */
+ {
+ .vendor = "NFINIDAT",
+ .product = "InfiniBox.*",
+ .features = DEFAULT_FEATURES,
+ .hwhandler = DEFAULT_HWHANDLER,
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = 30,
+ .rr_weight = RR_WEIGHT_PRIO,
+ .no_path_retry = NO_PATH_RETRY_FAIL,
+ .checker_name = TUR,
+ .prio_name = PRIO_ALUA,
+ .prio_args = NULL,
+ .selector = "round-robin 0",
+ .flush_on_last_del = FLUSH_ENABLED,
+ .dev_loss = 30,
+ },
{
.vendor = "XtremIO",
.product = "XtremApp",

View File

@ -0,0 +1,17 @@
---
kpartx/dos.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: multipath-tools-130222/kpartx/dos.c
===================================================================
--- multipath-tools-130222.orig/kpartx/dos.c
+++ multipath-tools-130222/kpartx/dos.c
@@ -46,7 +46,7 @@ read_extended_partition(int fd, struct p
for (i=0; i<2; i++) {
memcpy(&p, bp + 0x1be + i * sizeof (p), sizeof (p));
if (is_extended(p.sys_type)) {
- if (p.nr_sects && !moretodo) {
+ if (p.start_sect && p.nr_sects && !moretodo) {
next = start + sector_size_mul * le32_to_cpu(p.start_sect);
moretodo = 1;
}

View File

@ -0,0 +1,111 @@
---
libmultipath/configure.c | 21 ++++++++++++++++++++-
libmultipath/configure.h | 1 +
multipath/main.c | 21 +++++++++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
Index: multipath-tools-130222/libmultipath/configure.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/configure.c
+++ multipath-tools-130222/libmultipath/configure.c
@@ -743,7 +743,8 @@ deadmap (struct multipath * mpp)
return 1; /* dead */
}
-int check_daemon(void)
+extern int
+check_daemon(void)
{
int fd;
char *reply;
@@ -776,6 +777,7 @@ coalesce_paths (struct vectors * vecs, v
{
int r = 1;
int k, i;
+ int map_processed = 0;
char empty_buff[WWID_SIZE];
char params[PARAMS_SIZE];
struct multipath * mpp;
@@ -936,6 +938,13 @@ coalesce_paths (struct vectors * vecs, v
else
remove_map(mpp, vecs, 0);
}
+
+ /* By now at least one multipath device map is processed,
+ * so set map_processed = 1
+ */
+ if (!map_processed)
+ map_processed = 1;
+
}
/*
* Flush maps with only dead paths (ie not in sysfs)
@@ -963,6 +972,16 @@ coalesce_paths (struct vectors * vecs, v
condlog(2, "%s: remove (dead)", alias);
}
}
+
+ /* If there is at least one multipath device map processed then
+ * check if 'multipathd' service is running or not?
+ */
+ if (map_processed) {
+ if (!conf->daemon && !check_daemon())
+ condlog(0, "'multipathd' service is currently not "
+ "running, IO failover/failback will not work");
+ }
+
return 0;
}
Index: multipath-tools-130222/libmultipath/configure.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/configure.h
+++ multipath-tools-130222/libmultipath/configure.h
@@ -27,6 +27,7 @@ enum actions {
int setup_map (struct multipath * mpp, char * params, int params_size );
int domap (struct multipath * mpp, char * params);
int reinstate_paths (struct multipath *mpp);
+int check_daemon(void);
int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload);
int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid);
int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh);
Index: multipath-tools-130222/multipath/main.c
===================================================================
--- multipath-tools-130222.orig/multipath/main.c
+++ multipath-tools-130222/multipath/main.c
@@ -178,6 +178,7 @@ static int
get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
{
int i;
+ int maps_present = 0;
struct multipath * mpp;
char params[PARAMS_SIZE], status[PARAMS_SIZE];
@@ -226,7 +227,27 @@ get_dm_mpvec (vector curmp, vector pathv
if (conf->cmd == CMD_CREATE)
reinstate_paths(mpp);
+
+ /* At this place we have found at least one multipath
+ * device map, so set maps_present = 1
+ */
+ if (!maps_present)
+ maps_present = 1;
+
}
+
+ /* If there is at least one multipath device map present then
+ * check if 'multipathd' service is running or not?
+ */
+ if (maps_present) {
+ if (!conf->daemon && !check_daemon()) {
+ condlog(0, "multipath device maps are present, but "
+ "'multipathd' service is not running");
+ condlog(0, "IO failover/failback will not work without "
+ "'multipathd' service running");
+ }
+ }
+
return 0;
}

View File

@ -0,0 +1,38 @@
---
libmultipath/configure.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
Index: multipath-tools-130222/libmultipath/configure.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/configure.c
+++ multipath-tools-130222/libmultipath/configure.c
@@ -257,7 +257,7 @@ extern int
setup_map (struct multipath * mpp, char * params, int params_size)
{
struct pathgroup * pgp;
- int i;
+ int i, old_nr_active;
/*
* don't bother if devmap size is unknown
@@ -311,8 +311,12 @@ setup_map (struct multipath * mpp, char
if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
return 1;
+ old_nr_active = mpp->nr_active;
mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
+ if (mpp->nr_active && !old_nr_active)
+ mpp->force_udev_reload = 1;
+
/*
* ponders each path group and determine highest prio pg
* to switch over (default to first)
@@ -445,7 +449,6 @@ select_action (struct multipath * mpp, v
mpp->alias);
return;
}
- mpp->force_udev_reload = !pathcount(mpp, PATH_WILD);
if (cmpp->size != mpp->size) {
mpp->force_udev_reload = 1;
mpp->action = ACT_RESIZE;

View File

@ -0,0 +1,474 @@
---
libmultipath/config.c | 3 +
libmultipath/config.h | 3 +
libmultipath/configure.c | 1
libmultipath/defaults.h | 1
libmultipath/devmapper.c | 4 +-
libmultipath/dict.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
libmultipath/discovery.c | 60 +++++++++++++++++++++++++++++++
libmultipath/discovery.h | 1
libmultipath/propsel.c | 25 ++++++++++++
libmultipath/propsel.h | 1
libmultipath/structs.h | 7 +++
multipath/multipath.conf.5 | 8 ++++
12 files changed, 200 insertions(+), 1 deletion(-)
Index: multipath-tools-130222/libmultipath/config.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.c
+++ multipath-tools-130222/libmultipath/config.c
@@ -344,6 +344,7 @@ merge_hwe (struct hwentry * dst, struct
merge_num(delay_watch_checks);
merge_num(delay_wait_checks);
merge_num(skip_kpartx);
+ merge_num(max_sectors_kb);
/*
* Make sure features is consistent with
@@ -405,6 +406,7 @@ overwrite_hwe (struct hwentry * dst, str
overwrite_num(delay_watch_checks);
overwrite_num(delay_wait_checks);
overwrite_num(skip_kpartx);
+ overwrite_num(max_sectors_kb);
/*
* Make sure features is consistent with
@@ -682,6 +684,7 @@ load_config (char * file, struct udev *u
conf->skip_kpartx = DEFAULT_SKIP_KPARTX;
conf->remove_retries = 0;
conf->disable_changed_wwids = 0;
+ conf->max_sectors_kb = DEFAULT_MAX_SECTORS_KB;
/*
* preload default hwtable
Index: multipath-tools-130222/libmultipath/config.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.h
+++ multipath-tools-130222/libmultipath/config.h
@@ -65,6 +65,7 @@ struct hwentry {
int delay_watch_checks;
int delay_wait_checks;
int skip_kpartx;
+ int max_sectors_kb;
char * bl_product;
};
@@ -92,6 +93,7 @@ struct mpentry {
int delay_watch_checks;
int delay_wait_checks;
int skip_kpartx;
+ int max_sectors_kb;
uid_t uid;
gid_t gid;
mode_t mode;
@@ -148,6 +150,7 @@ struct config {
int skip_kpartx;
int remove_retries;
int disable_changed_wwids;
+ int max_sectors_kb;
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
@@ -295,6 +295,7 @@ setup_map (struct multipath * mpp, char
select_delay_watch_checks(mpp);
select_delay_wait_checks(mpp);
select_skip_kpartx(mpp);
+ select_max_sectors_kb(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
@@ -25,6 +25,7 @@
#define DEFAULT_RETRIGGER_TRIES 3
#define DEFAULT_UEV_WAIT_TIMEOUT 30
#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF
+#define DEFAULT_MAX_SECTORS_KB MAX_SECTORS_KB_UNDEF
#define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2)
Index: multipath-tools-130222/libmultipath/dict.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/dict.c
+++ multipath-tools-130222/libmultipath/dict.c
@@ -976,6 +976,22 @@ def_disable_changed_wwids_handler(vector
return 0;
}
+static int
+def_max_sectors_kb_handler(vector strvec)
+{
+ char * buff;
+
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+
+ if ((conf->max_sectors_kb = atoi(buff)) < MAX_SECTORS_KB_MIN)
+ conf->max_sectors_kb = MAX_SECTORS_KB_UNDEF;
+
+ FREE(buff);
+ return 0;
+}
+
/*
* blacklist block handlers
*/
@@ -1765,6 +1781,26 @@ hw_delay_wait_checks_handler(vector strv
return 0;
}
+static int
+hw_max_sectors_kb_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 ((hwe->max_sectors_kb = atoi(buff)) < MAX_SECTORS_KB_MIN)
+ hwe->max_sectors_kb = MAX_SECTORS_KB_UNDEF;
+
+ FREE(buff);
+ return 0;
+}
+
/*
* multipaths block handlers
*/
@@ -2316,6 +2352,26 @@ mp_delay_wait_checks_handler(vector strv
return 0;
}
+static int
+mp_max_sectors_kb_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 ((mpe->max_sectors_kb = atoi(buff)) < MAX_SECTORS_KB_MIN)
+ mpe->max_sectors_kb = MAX_SECTORS_KB_UNDEF;
+
+ FREE(buff);
+ return 0;
+}
+
/*
* config file keywords printing
*/
@@ -2615,6 +2671,16 @@ snprint_mp_delay_wait_checks(char * buff
}
static int
+snprint_mp_max_sectors_kb(char * buff, int len, void * data)
+{
+ struct mpentry * mpe = (struct mpentry *)data;
+
+ if (mpe->max_sectors_kb == MAX_SECTORS_KB_UNDEF)
+ return 0;
+ return snprintf(buff, len, "%d", mpe->max_sectors_kb);
+}
+
+static int
snprint_hw_fast_io_fail(char * buff, int len, void * data)
{
struct hwentry * hwe = (struct hwentry *)data;
@@ -2993,6 +3059,16 @@ snprint_detect_prio(char * buff, int len
}
static int
+snprint_hw_max_sectors_kb(char * buff, int len, void * data)
+{
+ struct hwentry * hwe = (struct hwentry *)data;
+
+ if (hwe->max_sectors_kb == MAX_SECTORS_KB_UNDEF)
+ return 0;
+ return snprintf(buff, len, "%d", hwe->max_sectors_kb);
+}
+
+static int
snprint_def_polling_interval (char * buff, int len, void * data)
{
return snprintf(buff, len, "%i", conf->checkint);
@@ -3461,6 +3537,14 @@ snprint_def_disable_changed_wwids(char *
}
static int
+snprint_def_max_sectors_kb(char * buff, int len, void * data)
+{
+ if (conf->max_sectors_kb == MAX_SECTORS_KB_UNDEF)
+ return 0;
+ return snprintf(buff, len, "%d", conf->max_sectors_kb);
+}
+
+static int
snprint_ble_simple (char * buff, int len, void * data)
{
struct blentry * ble = (struct blentry *)data;
@@ -3541,6 +3625,7 @@ init_keywords(void)
install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot);
install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries);
install_keyword("disable_changed_wwids", &def_disable_changed_wwids_handler, &snprint_def_disable_changed_wwids);
+ install_keyword("max_sectors_kb", &def_max_sectors_kb_handler, &snprint_def_max_sectors_kb);
__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);
@@ -3609,6 +3694,7 @@ init_keywords(void)
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_keyword("max_sectors_kb", &hw_max_sectors_kb_handler, &snprint_hw_max_sectors_kb);
install_sublevel_end();
install_keyword_root("multipaths", &multipaths_handler);
@@ -3637,5 +3723,6 @@ init_keywords(void)
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_keyword("max_sectors_kb", &mp_max_sectors_kb_handler, &snprint_mp_max_sectors_kb);
install_sublevel_end();
}
Index: multipath-tools-130222/libmultipath/discovery.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.c
+++ multipath-tools-130222/libmultipath/discovery.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include <libgen.h>
#include <libudev.h>
+#include <libdevmapper.h>
#include "checkers.h"
#include "vector.h"
@@ -27,6 +28,7 @@
#include "discovery.h"
#include "prio.h"
#include "defaults.h"
+#include "devmapper.h"
int
store_pathinfo (vector pathvec, vector hwtable, struct udev_device *udevice,
@@ -166,6 +168,64 @@ declare_sysfs_get_str(rev);
declare_sysfs_get_str(dev);
int
+sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload)
+{
+ struct pathgroup * pgp;
+ struct path *pp;
+ char buff[11];
+ struct udev_device *udevice = NULL;
+ int i, j, len, ret;
+ int max_sectors_kb;
+
+ if (mpp->max_sectors_kb == MAX_SECTORS_KB_UNDEF)
+ return 0;
+ max_sectors_kb = mpp->max_sectors_kb;
+ if (is_reload) {
+ if (!mpp->dmi && dm_get_info(mpp->alias, &mpp->dmi) != 0) {
+ condlog(0, "failed to get dm info on %s to set max_sectors_kb", mpp->alias);
+ return 1;
+ }
+ udevice = udev_device_new_from_devnum(conf->udev, 'b',
+ makedev(mpp->dmi->major,
+ mpp->dmi->minor));
+ if (!udevice) {
+ condlog(0, "failed to get udev device to set max_sectors_kb for %s", mpp->alias);
+ return 1;
+ }
+ if (sysfs_attr_get_value(udevice, "queue/max_sectors_kb",
+ buff, sizeof(buff)) <= 0) {
+ condlog(0, "failed to get current max_sectors_kb from %s", mpp->alias);
+ goto fail_reload;
+ }
+ if (sscanf(buff, "%u\n", &max_sectors_kb) != 1) {
+ condlog(0, "can't parse current max_sectors_kb from %s",
+ mpp->alias);
+ goto fail_reload;
+ }
+ udev_device_unref(udevice);
+ }
+ snprintf(buff, 11, "%d", max_sectors_kb);
+ len = strlen(buff);
+
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ ret = sysfs_attr_set_value(pp->udev,
+ "queue/max_sectors_kb",
+ buff, len);
+ if (ret < 0) {
+ condlog(0, "failed setting max_sectors_kb on %s : %s", pp->dev, strerror(-ret));
+ return 1;
+ }
+ }
+ }
+ return 0;
+
+fail_reload:
+ udev_device_unref(udevice);
+ return 1;
+}
+
+int
sysfs_get_timeout(struct path *pp, unsigned int *timeout)
{
const char *attr = NULL;
Index: multipath-tools-130222/libmultipath/discovery.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.h
+++ multipath-tools-130222/libmultipath/discovery.h
@@ -41,6 +41,7 @@ int store_pathinfo (vector pathvec, vect
struct udev_device *udevice, int flag,
struct path **pp_ptr);
int sysfs_set_scsi_tmo (struct multipath *mpp);
+int sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload);
int sysfs_get_timeout(struct path *pp, unsigned int *timeout);
int sysfs_get_host_pci_name(struct path *pp, char *pci_name);
int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address);
Index: multipath-tools-130222/libmultipath/propsel.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/propsel.c
+++ multipath-tools-130222/libmultipath/propsel.c
@@ -880,3 +880,28 @@ select_skip_kpartx (struct multipath * m
condlog(3, "skip_kpartx = DISABLED (internal default)");
return 0;
}
+
+extern int
+select_max_sectors_kb (struct multipath * mp)
+{
+ if (mp->mpe && mp->mpe->max_sectors_kb != MAX_SECTORS_KB_UNDEF) {
+ mp->max_sectors_kb = mp->mpe->max_sectors_kb;
+ condlog(3, "max_sectors_kb = %i (multipath setting)",
+ mp->max_sectors_kb);
+ return 0;
+ }
+ if (mp->hwe && mp->hwe->max_sectors_kb != MAX_SECTORS_KB_UNDEF) {
+ mp->max_sectors_kb = mp->hwe->max_sectors_kb;
+ condlog(3, "max_sectors_kb = %i (controler setting)",
+ mp->max_sectors_kb);
+ return 0;
+ }
+ if (conf->max_sectors_kb != MAX_SECTORS_KB_UNDEF) {
+ mp->max_sectors_kb = conf->max_sectors_kb;
+ condlog(3, "max_sectors_kb = %i (config file default)",
+ mp->max_sectors_kb);
+ return 0;
+ }
+ mp->max_sectors_kb = MAX_SECTORS_KB_UNDEF;
+ return 0;
+}
Index: multipath-tools-130222/libmultipath/propsel.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/propsel.h
+++ multipath-tools-130222/libmultipath/propsel.h
@@ -24,3 +24,4 @@ int select_deferred_remove(struct multip
int select_delay_watch_checks (struct multipath * mp);
int select_delay_wait_checks (struct multipath * mp);
int select_skip_kpartx (struct multipath * mp);
+int select_max_sectors_kb (struct multipath * mp);
Index: multipath-tools-130222/libmultipath/structs.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/structs.h
+++ multipath-tools-130222/libmultipath/structs.h
@@ -128,6 +128,12 @@ enum skip_kpartx_states {
SKIP_KPARTX_ON,
};
+
+enum max_sectors_kb_states {
+ MAX_SECTORS_KB_UNDEF = 0,
+ MAX_SECTORS_KB_MIN = 4, /* can't be smaller than page size */
+};
+
enum scsi_protocol {
SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
@@ -245,6 +251,7 @@ struct multipath {
int delay_wait_checks;
int force_udev_reload;
int skip_kpartx;
+ int max_sectors_kb;
unsigned int dev_loss;
uid_t uid;
gid_t gid;
Index: multipath-tools-130222/multipath/multipath.conf.5
===================================================================
--- multipath-tools-130222.orig/multipath/multipath.conf.5
+++ multipath-tools-130222/multipath/multipath.conf.5
@@ -561,6 +561,10 @@ default is
This sets how may times multipath will retry removing a device that is in-use.
Between each attempt, multipath will sleep 1 second. The default is
.I 0
+.TP
+.B max_sectors_kb
+Sets the max_sectors_kb device parameter on all path devices and the multipath
+device to the specified value. Default is device dependent.
.
.SH "blacklist section"
The
@@ -672,6 +676,8 @@ section:
.B delay_wait_checks
.TP
.B skip_kpartx
+.TP
+.B max_sectors_kb
.RE
.PD
.LP
@@ -772,6 +778,8 @@ section:
.B delay_wait_checks
.TP
.B skip_kpartx
+.TP
+.B max_sectors_kb
.RE
.PD
.LP
Index: multipath-tools-130222/libmultipath/devmapper.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/devmapper.c
+++ multipath-tools-130222/libmultipath/devmapper.c
@@ -21,7 +21,7 @@
#include "devmapper.h"
#include "config.h"
#include "sysfs.h"
-
+#include "discovery.h"
#include "log_pthread.h"
#include <sys/types.h>
#include <time.h>
@@ -330,6 +330,7 @@ extern int
dm_addmap_create (struct multipath *mpp, char * params) {
int ro;
+ sysfs_set_max_sectors_kb(mpp, 0);
for (ro = 0; ro <= 1; ro++) {
int err;
@@ -356,6 +357,7 @@ dm_addmap_create (struct multipath *mpp,
extern int
dm_addmap_reload (struct multipath *mpp, char *params) {
+ sysfs_set_max_sectors_kb(mpp, 1);
if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW, SKIP_KPARTX_OFF))
return 1;
if (errno != EROFS)

View File

@ -0,0 +1,377 @@
---
libmultipath/config.c | 4 ++
libmultipath/config.h | 2 +
libmultipath/defaults.h | 1
libmultipath/dict.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
libmultipath/discovery.c | 1
libmultipath/hwtable.c | 1
libmultipath/propsel.c | 65 +++++++++++++++++++++++++++++++--------
libmultipath/propsel.h | 1
libmultipath/structs.h | 7 ++++
multipath/multipath.conf.5 | 9 +++++
10 files changed, 152 insertions(+), 13 deletions(-)
Index: multipath-tools-130222/libmultipath/config.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.c
+++ multipath-tools-130222/libmultipath/config.c
@@ -340,6 +340,7 @@ merge_hwe (struct hwentry * dst, struct
merge_num(user_friendly_names);
merge_num(retain_hwhandler);
merge_num(detect_prio);
+ merge_num(detect_checker);
merge_num(deferred_remove);
merge_num(delay_watch_checks);
merge_num(delay_wait_checks);
@@ -402,6 +403,7 @@ overwrite_hwe (struct hwentry * dst, str
overwrite_num(user_friendly_names);
overwrite_num(retain_hwhandler);
overwrite_num(detect_prio);
+ overwrite_num(detect_checker);
overwrite_num(deferred_remove);
overwrite_num(delay_watch_checks);
overwrite_num(delay_wait_checks);
@@ -476,6 +478,7 @@ store_hwe (vector hwtable, struct hwentr
hwe->user_friendly_names = dhwe->user_friendly_names;
hwe->retain_hwhandler = dhwe->retain_hwhandler;
hwe->detect_prio = dhwe->detect_prio;
+ hwe->detect_checker = dhwe->detect_checker;
if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
goto out;
@@ -672,6 +675,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->detect_checker = DEFAULT_DETECT_CHECKER;
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 detect_checker;
int deferred_remove;
int delay_watch_checks;
int delay_wait_checks;
@@ -136,6 +137,7 @@ struct config {
int reassign_maps;
int retain_hwhandler;
int detect_prio;
+ int detect_checker;
int force_sync;
int deferred_remove;
int ignore_new_boot_devs;
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_DETECT_CHECKER DETECT_CHECKER_OFF
#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF
#define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF
#define DEFAULT_RETRIGGER_DELAY 10
Index: multipath-tools-130222/libmultipath/dict.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/dict.c
+++ multipath-tools-130222/libmultipath/dict.c
@@ -714,6 +714,29 @@ def_detect_prio_handler(vector strvec)
}
static int
+def_detect_checker_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->detect_checker = DETECT_CHECKER_OFF;
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
+ conf->detect_checker = DETECT_CHECKER_ON;
+ else
+ conf->detect_checker = DETECT_CHECKER_UNDEF;
+
+ FREE(buff);
+ return 0;
+}
+
+static int
def_hw_strmatch_handler(vector strvec)
{
char *buff;
@@ -1682,6 +1705,33 @@ hw_detect_prio_handler(vector strvec)
}
static int
+hw_detect_checker_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->detect_checker = DETECT_CHECKER_OFF;
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
+ hwe->detect_checker = DETECT_CHECKER_ON;
+ else
+ hwe->detect_checker = DETECT_CHECKER_UNDEF;
+
+ FREE(buff);
+ return 0;
+}
+
+static int
hw_deferred_remove_handler(vector strvec)
{
struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
@@ -3059,6 +3109,19 @@ snprint_detect_prio(char * buff, int len
}
static int
+snprint_detect_checker(char * buff, int len, void * data)
+{
+ struct hwentry * hwe = (struct hwentry *)data;
+
+ if (hwe->detect_checker == DETECT_CHECKER_ON)
+ return snprintf(buff, len, "yes");
+ else if (hwe->detect_checker == DETECT_CHECKER_OFF)
+ return snprintf(buff, len, "no");
+ else
+ return 0;
+}
+
+static int
snprint_hw_max_sectors_kb(char * buff, int len, void * data)
{
struct hwentry * hwe = (struct hwentry *)data;
@@ -3424,6 +3487,15 @@ snprint_def_detect_prio(char * buff, int
}
static int
+snprint_def_detect_checker(char * buff, int len, void * data)
+{
+ if (conf->detect_checker == DETECT_PRIO_ON)
+ return snprintf(buff, len, "yes");
+ else
+ return snprintf(buff, len, "no");
+}
+
+static int
snprint_def_hw_strmatch(char * buff, int len, void * data)
{
if (conf->hw_strmatch)
@@ -3611,6 +3683,7 @@ init_keywords(void)
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);
install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio);
+ install_keyword("detect_path_checker", &def_detect_checker_handler, &snprint_def_detect_checker);
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);
@@ -3690,6 +3763,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("detect_path_checker", &hw_detect_checker_handler, &snprint_detect_checker);
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);
Index: multipath-tools-130222/libmultipath/discovery.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.c
+++ multipath-tools-130222/libmultipath/discovery.c
@@ -1107,6 +1107,7 @@ get_state (struct path * pp, int daemon)
return PATH_UNCHECKED;
}
}
+ select_detect_checker(pp);
select_checker(pp);
if (!checker_selected(c)) {
condlog(3, "%s: No checker selected", pp->dev);
Index: multipath-tools-130222/libmultipath/hwtable.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/hwtable.c
+++ multipath-tools-130222/libmultipath/hwtable.c
@@ -289,6 +289,7 @@ static struct hwentry default_hw[] = {
.prio_args = NULL,
.retain_hwhandler = RETAIN_HWHANDLER_ON,
.detect_prio = DETECT_PRIO_ON,
+ .detect_checker = DETECT_CHECKER_ON,
},
{
.vendor = "EMC",
Index: multipath-tools-130222/libmultipath/propsel.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/propsel.c
+++ multipath-tools-130222/libmultipath/propsel.c
@@ -335,11 +335,43 @@ select_hwhandler (struct multipath * mp)
return 0;
}
+int
+detect_alua(struct path * pp)
+{
+ int ret;
+ int tpgs = 0;
+
+ if ((tpgs = get_target_port_group_support(pp->fd)) <= 0)
+ return 0;
+ pp->tpgs = tpgs;
+ ret = get_target_port_group(pp->fd, NULL);
+ if (ret < 0)
+ return 0;
+ if (get_asymmetric_access_state(pp->fd, ret, NULL) < 0)
+ return 0;
+ return 1;
+}
+
+void
+detect_checker(struct path * pp)
+{
+ if (detect_alua(pp))
+ checker_get(&pp->checker, TUR);
+}
+
extern int
select_checker(struct path *pp)
{
struct checker * c = &pp->checker;
+ if (pp->detect_checker == DETECT_CHECKER_ON) {
+ detect_checker(pp);
+ if (checker_selected(c)) {
+ condlog(3, "%s: path checker = %s (detected setting)",
+ pp->dev, checker_name(c));
+ goto out;
+ }
+ }
if (pp->hwe && pp->hwe->checker_name) {
checker_get(c, pp->hwe->checker_name);
condlog(3, "%s: path checker = %s (controller setting)",
@@ -396,19 +428,8 @@ select_getuid (struct path * pp)
void
detect_prio(struct path * pp)
{
- int ret;
- struct prio *p = &pp->prio;
- int tpgs = 0;
-
- if ((tpgs = get_target_port_group_support(pp->fd)) <= 0)
- return;
- pp->tpgs = tpgs;
- ret = get_target_port_group(pp->fd, NULL);
- if (ret < 0)
- return;
- if (get_asymmetric_access_state(pp->fd, ret, NULL) < 0)
- return;
- prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS);
+ if (detect_alua(pp))
+ prio_get(&pp->prio, PRIO_ALUA, DEFAULT_PRIO_ARGS);
}
extern int
@@ -803,6 +824,24 @@ select_detect_prio (struct path * pp)
return 0;
}
+extern int
+select_detect_checker (struct path * pp)
+{
+ if (pp->hwe && pp->hwe->detect_checker) {
+ pp->detect_checker = pp->hwe->detect_checker;
+ condlog(3, "%s: detect_checker = %d (controller default)", pp->dev, pp->detect_checker);
+ return 0;
+ }
+ if (conf->detect_checker) {
+ pp->detect_checker = conf->detect_checker;
+ condlog(3, "%s: detect_checker = %d (config file default)", pp->dev, pp->detect_checker);
+ return 0;
+ }
+ pp->detect_checker = DEFAULT_DETECT_CHECKER;
+ condlog(3, "%s: detect_checker = %d (compiled in default)", pp->dev, pp->detect_checker);
+ return 0;
+}
+
extern int
select_delay_watch_checks (struct multipath * mp)
{
Index: multipath-tools-130222/libmultipath/propsel.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/propsel.h
+++ multipath-tools-130222/libmultipath/propsel.h
@@ -20,6 +20,7 @@ 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_detect_checker(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);
Index: multipath-tools-130222/libmultipath/structs.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/structs.h
+++ multipath-tools-130222/libmultipath/structs.h
@@ -115,6 +115,12 @@ enum detect_prio_states {
DETECT_PRIO_ON,
};
+enum detect_checker_states {
+ DETECT_CHECKER_UNDEF,
+ DETECT_CHECKER_OFF,
+ DETECT_CHECKER_ON,
+};
+
enum deferred_remove_states {
DEFERRED_REMOVE_UNDEF,
DEFERRED_REMOVE_OFF,
@@ -204,6 +210,7 @@ struct path {
int priority;
int pgindex;
int detect_prio;
+ int detect_checker;
int watch_checks;
int wait_checks;
int tpgs;
Index: multipath-tools-130222/multipath/multipath.conf.5
===================================================================
--- multipath-tools-130222.orig/multipath/multipath.conf.5
+++ multipath-tools-130222/multipath/multipath.conf.5
@@ -448,6 +448,15 @@ will automatically use the
prioritizer. If not, the prioritizer will be selected as usual. Default is
.I no
.TP
+.B detect_checker
+If set to
+.I yes
+, multipath will try to detect if the device supports ALUA. If so, the device
+will automatically use the
+.I tur
+checker. If not, the prioritizer will be selected as ususal. Default is
+.I no
+.TP
.B hw_str_match
If set to
.I yes

View File

@ -0,0 +1,17 @@
---
libmultipath/hwtable.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: multipath-tools-130222/libmultipath/hwtable.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/hwtable.c
+++ multipath-tools-130222/libmultipath/hwtable.c
@@ -69,7 +69,7 @@ static struct hwentry default_hw[] = {
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
.rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
+ .no_path_retry = 12,
.checker_name = DEFAULT_CHECKER,
.prio_name = DEFAULT_PRIO,
.prio_args = NULL,

View File

@ -0,0 +1,29 @@
---
libmultipath/print.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
Index: multipath-tools-130222/libmultipath/print.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/print.c
+++ multipath-tools-130222/libmultipath/print.c
@@ -386,7 +386,9 @@ snprint_dev_t (char * buff, size_t len,
static int
snprint_offline (char * buff, size_t len, struct path * pp)
{
- if (pp->offline)
+ if (!pp || !pp->mpp)
+ return snprintf(buff, len, "unknown");
+ else if (pp->offline)
return snprintf(buff, len, "offline");
else
return snprintf(buff, len, "running");
@@ -395,6 +397,9 @@ snprint_offline (char * buff, size_t len
static int
snprint_chk_state (char * buff, size_t len, struct path * pp)
{
+ if (!pp || !pp->mpp)
+ return snprintf(buff, len, "undef");
+
switch (pp->state) {
case PATH_UP:
return snprintf(buff, len, "ready");

View File

@ -0,0 +1,59 @@
---
libmultipath/discovery.c | 15 +++++++++++----
multipathd/main.c | 10 ++++++++++
2 files changed, 21 insertions(+), 4 deletions(-)
Index: multipath-tools-130222/libmultipath/discovery.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.c
+++ multipath-tools-130222/libmultipath/discovery.c
@@ -84,10 +84,6 @@ path_discover (vector pathvec, struct co
if (!devname)
return PATHINFO_FAILED;
- if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
- (char *)devname) > 0)
- return PATHINFO_SKIPPED;
-
pp = find_path_by_dev(pathvec, (char *)devname);
if (!pp) {
return store_pathinfo(pathvec, conf->hwtable,
@@ -1286,6 +1282,17 @@ pathinfo (struct path *pp, vector hwtabl
if (!pp)
return PATHINFO_FAILED;
+ /*
+ * For behavior backward-compatibility with multipathd,
+ * the blacklisting by filter_devnode() is not
+ * limited by DI_BLACKLIST and occurs before this debug
+ * message with the mask value.
+ */
+ if (filter_devnode(conf->blist_devnode,
+ conf->elist_devnode,
+ pp->dev) > 0)
+ return PATHINFO_SKIPPED;
+
condlog(3, "%s: mask = 0x%x", pp->dev, mask);
/*
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -776,6 +776,16 @@ uev_update_path (struct uevent *uev, str
pp = find_path_by_dev(vecs->pathvec, uev->kernel);
if (!pp) {
+ /* If the path is blacklisted, print a debug/non-default verbosity message. */
+ if (uev->udev) {
+ int flag = DI_SYSFS | DI_WWID;
+
+ if (store_pathinfo(NULL, conf->hwtable, uev->udev, flag, NULL) == PATHINFO_SKIPPED) {
+ condlog(3, "%s: spurious uevent, path is blacklisted", uev->kernel);
+ return 0;
+ }
+ }
+
condlog(0, "%s: spurious uevent, path not found",
uev->kernel);
return 1;

View File

@ -0,0 +1,18 @@
---
multipathd/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -1248,7 +1248,8 @@ int update_prio(struct path *pp, int ref
return changed;
}
oldpriority = pp->priority;
- pathinfo(pp, conf->hwtable, DI_PRIO);
+ if (pp->state != PATH_DOWN)
+ pathinfo(pp, conf->hwtable, DI_PRIO);
if (pp->priority == oldpriority)
return 0;

View File

@ -0,0 +1,24 @@
---
multipathd/main.c | 2 ++
1 file changed, 2 insertions(+)
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -337,6 +337,7 @@ ev_add_map (char * dev, char * alias, st
if (mpp) {
if (mpp->wait_for_udev > 1) {
+ condlog(2, "%s: performing delayed actions", mpp->alias);
if (update_map(mpp, vecs))
/* setup multipathd removed the map */
return 1;
@@ -535,6 +536,7 @@ ev_add_path (struct path * pp, struct ve
pp->tpgs == TPGS_IMPLICIT))
mpp->force_udev_reload = 1;
else {
+ condlog(2, "%s : delaying path addition until %s is fully initialized", pp->dev, mpp->alias);
mpp->wait_for_udev = 2;
orphan_path(pp);
return 0;

View File

@ -0,0 +1,28 @@
---
libmultipath/hwtable.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
Index: multipath-tools-130222/libmultipath/hwtable.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/hwtable.c
+++ multipath-tools-130222/libmultipath/hwtable.c
@@ -1189,6 +1189,19 @@ static struct hwentry default_hw[] = {
.dev_loss = 30,
},
{
+ .vendor = "Nimble",
+ .product = "Server",
+ .features = "1 queue_if_no_path",
+ .hwhandler = "1 alua",
+ .pgpolicy = GROUP_BY_PRIO,
+ .prio_name = PRIO_ALUA,
+ .prio_args = NULL,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .selector = "round-robin 0",
+ .dev_loss = MAX_DEV_LOSS_TMO,
+ .fast_io_fail = 1,
+ },
+ {
.vendor = "XtremIO",
.product = "XtremApp",
.features = DEFAULT_FEATURES,

View File

@ -0,0 +1,108 @@
---
multipathd/cli.c | 2 ++
multipathd/cli_handlers.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
multipathd/cli_handlers.h | 2 ++
multipathd/main.c | 2 ++
4 files changed, 50 insertions(+)
Index: multipath-tools-130222/multipathd/cli.c
===================================================================
--- multipath-tools-130222.orig/multipathd/cli.c
+++ multipath-tools-130222/multipathd/cli.c
@@ -482,6 +482,8 @@ cli_init (void) {
add_handler(LIST+BLACKLIST, NULL);
add_handler(LIST+DEVICES, NULL);
add_handler(LIST+WILDCARDS, NULL);
+ add_handler(RESET+MAPS+STATS, NULL);
+ add_handler(RESET+MAP+STATS, NULL);
add_handler(ADD+PATH, NULL);
add_handler(DEL+PATH, NULL);
add_handler(ADD+MAP, NULL);
Index: multipath-tools-130222/multipathd/cli_handlers.c
===================================================================
--- multipath-tools-130222.orig/multipathd/cli_handlers.c
+++ multipath-tools-130222/multipathd/cli_handlers.c
@@ -233,6 +233,17 @@ show_config (char ** r, int * len)
return 0;
}
+void
+reset_stats(struct multipath * mpp)
+{
+ mpp->stat_switchgroup = 0;
+ mpp->stat_path_failures = 0;
+ mpp->stat_map_loads = 0;
+ mpp->stat_total_queueing_time = 0;
+ mpp->stat_queueing_timeouts = 0;
+ mpp->stat_map_failures = 0;
+}
+
int
cli_list_config (void * v, char ** reply, int * len, void * data)
{
@@ -501,6 +512,39 @@ cli_list_daemon (void * v, char ** reply
}
int
+cli_reset_maps_stats (void * v, char ** reply, int * len, void * data)
+{
+ struct vectors * vecs = (struct vectors *)data;
+ int i;
+ struct multipath * mpp;
+
+ condlog(3, "reset multipaths stats (operator)");
+
+ vector_foreach_slot(vecs->mpvec, mpp, i) {
+ reset_stats(mpp);
+ }
+ return 0;
+}
+
+int
+cli_reset_map_stats (void * v, char ** reply, int * len, void * data)
+{
+ struct vectors * vecs = (struct vectors *)data;
+ struct multipath * mpp;
+ char * param = get_keyparam(v, MAP);
+
+ param = convert_dev(param, 0);
+ mpp = find_mp_by_str(vecs->mpvec, param);
+
+ if (!mpp)
+ return 1;
+
+ condlog(3, "reset multipath %s stats (operator)", param);
+ reset_stats(mpp);
+ return 0;
+}
+
+int
cli_add_path (void * v, char ** reply, int * len, void * data)
{
struct vectors * vecs = (struct vectors *)data;
Index: multipath-tools-130222/multipathd/cli_handlers.h
===================================================================
--- multipath-tools-130222.orig/multipathd/cli_handlers.h
+++ multipath-tools-130222/multipathd/cli_handlers.h
@@ -16,6 +16,8 @@ int cli_list_config (void * v, char ** r
int cli_list_blacklist (void * v, char ** reply, int * len, void * data);
int cli_list_devices (void * v, char ** reply, int * len, void * data);
int cli_list_wildcards (void * v, char ** reply, int * len, void * data);
+int cli_reset_maps_stats (void * v, char ** reply, int * len, void * data);
+int cli_reset_map_stats (void * v, char ** reply, int * len, void * data);
int cli_add_path (void * v, char ** reply, int * len, void * data);
int cli_del_path (void * v, char ** reply, int * len, void * data);
int cli_add_map (void * v, char ** reply, int * len, void * data);
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -1011,6 +1011,8 @@ uxlsnrloop (void * ap)
set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
set_handler_callback(LIST+DEVICES, cli_list_devices);
set_handler_callback(LIST+WILDCARDS, cli_list_wildcards);
+ set_handler_callback(RESET+MAPS+STATS, cli_reset_maps_stats);
+ set_handler_callback(RESET+MAP+STATS, cli_reset_map_stats);
set_handler_callback(ADD+PATH, cli_add_path);
set_handler_callback(DEL+PATH, cli_del_path);
set_handler_callback(ADD+MAP, cli_add_map);

View File

@ -0,0 +1,121 @@
---
libmultipath/configure.c | 2 -
libmultipath/devmapper.h | 6 ++++
multipath/11-dm-mpath.rules | 61 +++++++++++++++++++++++++++++++++-----------
3 files changed, 54 insertions(+), 15 deletions(-)
Index: multipath-tools-130222/libmultipath/configure.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/configure.c
+++ multipath-tools-130222/libmultipath/configure.c
@@ -615,7 +615,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);
+ 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) | ((mpp->nr_active)? 0 : MPATH_UDEV_NO_PATHS_FLAG);
/*
* last chance to quit before touching the devmaps
Index: multipath-tools-130222/libmultipath/devmapper.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/devmapper.h
+++ multipath-tools-130222/libmultipath/devmapper.h
@@ -18,6 +18,12 @@
#define MPATH_UDEV_NO_KPARTX_FLAG 0
#endif
+#ifdef DM_SUBSYSTEM_UDEV_FLAG2
+#define MPATH_UDEV_NO_PATHS_FLAG DM_SUBSYSTEM_UDEV_FLAG2
+#else
+#define MPATH_UDEV_NO_PATHS_FLAG 0
+#endif
+
void dm_init(void);
int dm_prereq (void);
int dm_drv_version (unsigned int * version, char * str);
Index: multipath-tools-130222/multipath/11-dm-mpath.rules
===================================================================
--- multipath-tools-130222.orig/multipath/11-dm-mpath.rules
+++ multipath-tools-130222/multipath/11-dm-mpath.rules
@@ -2,33 +2,66 @@ ACTION!="add|change", GOTO="mpath_end"
ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="mpath_end"
ENV{DM_UUID}!="mpath-?*", GOTO="mpath_end"
+IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD"
+IMPORT{db}="MPATH_DEVICE_READY"
+
+# If this uevent didn't come from dm, don't try to update the
+# device state
+ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", IMPORT{db}="DM_UDEV_DISABLE_OTHER_RULES_FLAG", IMPORT{db}="DM_NOSCAN", GOTO="scan_import"
+
+ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}"
+
+# multipath sets DM_SUBSYSTEM_UDEV_FLAG2 when it reloads a
+# table with no active devices. If this happens, mark the
+# device not ready
+ENV{DM_SUBSYSTEM_UDEV_FLAG2}=="1", ENV{MPATH_DEVICE_READY}="0",\
+ GOTO="mpath_action"
+
+# If the last path has failed mark the device not ready
+ENV{DM_ACTION}=="PATH_FAILED", ENV{DM_NR_VALID_PATHS}=="0",\
+ ENV{MPATH_DEVICE_READY}="0", GOTO="mpath_action"
+
+# Don't mark a device ready on a PATH_FAILED event. even if
+# DM_NR_VALID_PATHS is greater than 0. Just keep the existing
+# value
+ENV{DM_ACTION}=="PATH_FAILED", GOTO="mpath_action"
+
+# This event is either a PATH_REINSTATED or a table reload where
+# there are active paths. Mark the device ready
+ENV{MPATH_DEVICE_READY}=""
+
+LABEL="mpath_action"
+# DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem.
+# Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its
+# paths are lost/recovered. For any stack above the mpath device, this is not
+# something that should be reacted upon since it would be useless extra work.
+# It's exactly mpath's job to provide *seamless* device access to any of the
+# paths that are available underneath.
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_ACTIVATION}="0"
+
# Do not initiate scanning if no path is available,
# otherwise there would be a hang or IO error on access.
# We'd like to avoid this, especially within udev processing.
-ENV{DM_NR_VALID_PATHS}!="?*", IMPORT{db}="DM_NR_VALID_PATHS"
-ENV{DM_NR_VALID_PATHS}=="0", ENV{DM_NOSCAN}="1"
+ENV{MPATH_DEVICE_READY}=="0", ENV{DM_NOSCAN}="1"
# Also skip all foreign rules if no path is available.
# Remember the original value of DM_DISABLE_OTHER_RULES_FLAG
# and restore it back once we have at least one path available.
-IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD"
-ENV{DM_ACTION}=="PATH_FAILED",\
- ENV{DM_NR_VALID_PATHS}=="0",\
+ENV{MPATH_DEVICE_READY}=="0", ENV{.MPATH_DEVICE_READY_OLD}!="0",\
ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}=="",\
ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}",\
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
-ENV{DM_ACTION}=="PATH_REINSTATED",\
- ENV{DM_NR_VALID_PATHS}=="1",\
+ENV{MPATH_DEVICE_READY}!="0", ENV{.MPATH_DEVICE_READY_OLD}=="0",\
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}",\
ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="",\
ENV{DM_ACTIVATION}="1"
-# DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem.
-# Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its
-# paths are lost/recovered. For any stack above the mpath device, this is not
-# something that should be reacted upon since it would be useless extra work.
-# It's exactly mpath's job to provide *seamless* device access to any of the
-# paths that are available underneath.
-ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_ACTIVATION}="0"
+LABEL="scan_import"
+ENV{DM_NOSCAN}!="1", GOTO="mpath_end"
+ENV{ID_FS_TYPE}!="?*", IMPORT{db}="ID_FS_TYPE"
+ENV{ID_FS_USAGE}!="?*", IMPORT{db}="ID_FS_USAGE"
+ENV{ID_FS_UUID}!="?*", IMPORT{db}="ID_FS_UUID"
+ENV{ID_FS_ENC}!="?*", IMPORT{db}="ID_FS_UUID_ENC"
+ENV{ID_FS_VERSION}!="?*", IMPORT{db}="ID_FS_VERSION"
LABEL="mpath_end"

View File

@ -0,0 +1,840 @@
From c146b5840bbd7ad89c8a8de6192590ad0595a977 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 7 Apr 2016 18:19:58 -0500
Subject: [PATCH] Add libmpathcmd library and use it internally
Other programs would like to communicate with multipathd to issue
command or check status. Instead of having them exec multipathd,
I've pulled the code that sends commands and receives replies from
multipathd into its own library. I've made the multipath tools use
this library internally as well.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile | 1
Makefile.inc | 2
libmpathcmd/Makefile | 32 +++++++
libmpathcmd/mpath_cmd.c | 178 +++++++++++++++++++++++++++++++++++++++
libmpathcmd/mpath_cmd.h | 125 +++++++++++++++++++++++++++
libmpathpersist/Makefile | 5 -
libmpathpersist/mpath_updatepr.c | 30 +++---
libmultipath/Makefile | 4
libmultipath/config.c | 1
libmultipath/configure.c | 10 +-
libmultipath/uxsock.c | 88 +++----------------
libmultipath/uxsock.h | 6 -
mpathpersist/Makefile | 2
multipath/Makefile | 5 -
multipathd/Makefile | 4
multipathd/uxclnt.c | 13 +-
multipathd/uxlsnr.c | 9 -
17 files changed, 401 insertions(+), 114 deletions(-)
create mode 100644 libmpathcmd/Makefile
create mode 100644 libmpathcmd/mpath_cmd.c
create mode 100644 libmpathcmd/mpath_cmd.h
Index: multipath-tools-130222/Makefile
===================================================================
--- multipath-tools-130222.orig/Makefile
+++ multipath-tools-130222/Makefile
@@ -20,6 +20,7 @@ export KRNLSRC
export KRNLOBJ
BUILDDIRS = \
+ libmpathcmd \
libmultipath \
libmultipath/prioritizers \
libmultipath/checkers \
Index: multipath-tools-130222/Makefile.inc
===================================================================
--- multipath-tools-130222.orig/Makefile.inc
+++ multipath-tools-130222/Makefile.inc
@@ -34,6 +34,8 @@ syslibdir = $(prefix)/usr/$(LIB)
libdir = $(prefix)/usr/$(LIB)/multipath
unitdir = $(prefix)/lib/systemd/system
mpathpersistdir = $(TOPDIR)/libmpathpersist
+includedir = $(prefix)/usr/include
+mpathcmddir = $(TOPDIR)/libmpathcmd
GZIP = /bin/gzip -9 -c
INSTALL_PROGRAM = install
Index: multipath-tools-130222/libmpathcmd/Makefile
===================================================================
--- /dev/null
+++ multipath-tools-130222/libmpathcmd/Makefile
@@ -0,0 +1,32 @@
+# Makefile
+#
+include ../Makefile.inc
+
+SONAME=0
+DEVLIB = libmpathcmd.so
+LIBS = $(DEVLIB).$(SONAME)
+
+CFLAGS += -fPIC
+
+OBJS = mpath_cmd.o
+
+all: $(LIBS)
+
+$(LIBS): $(OBJS)
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ $(CFLAGS) -o $@ $(OBJS) $(LIBDEPS)
+ ln -sf $@ $(DEVLIB)
+
+install: $(LIBS)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
+ $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
+ ln -sf $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(includedir)
+ $(INSTALL_PROGRAM) -m 644 mpath_cmd.h $(DESTDIR)$(includedir)
+
+uninstall:
+ rm -f $(DESTDIR)$(syslibdir)/$(LIBS)
+ rm -f $(DESTDIR)$(syslibdir)/$(DEVLIB)
+ rm -f $(DESTDIR)$(includedir)/mpath_cmd.h
+
+clean:
+ rm -f core *.a *.o *.gz *.so *.so.*
Index: multipath-tools-130222/libmpathcmd/mpath_cmd.c
===================================================================
--- /dev/null
+++ multipath-tools-130222/libmpathcmd/mpath_cmd.c
@@ -0,0 +1,178 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <poll.h>
+#include <string.h>
+#include <errno.h>
+
+#include "mpath_cmd.h"
+
+/*
+ * keep reading until its all read
+ */
+static ssize_t read_all(int fd, void *buf, size_t len, unsigned int timeout)
+{
+ size_t total = 0;
+ ssize_t n;
+ int ret;
+ struct pollfd pfd;
+
+ while (len) {
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ ret = poll(&pfd, 1, timeout);
+ if (!ret) {
+ errno = ETIMEDOUT;
+ return -1;
+ } else if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ return -1;
+ } else if (!(pfd.revents & POLLIN))
+ continue;
+ n = read(fd, buf, len);
+ if (n < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ return -1;
+ }
+ if (!n)
+ return total;
+ buf = n + (char *)buf;
+ len -= n;
+ total += n;
+ }
+ return total;
+}
+
+/*
+ * keep writing until it's all sent
+ */
+static size_t write_all(int fd, const void *buf, size_t len)
+{
+ size_t total = 0;
+
+ while (len) {
+ ssize_t n = write(fd, buf, len);
+ if (n < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ return total;
+ }
+ if (!n)
+ return total;
+ buf = n + (char *)buf;
+ len -= n;
+ total += n;
+ }
+ return total;
+}
+
+/*
+ * connect to a unix domain socket
+ */
+int mpath_connect(void)
+{
+ int fd, len;
+ struct sockaddr_un addr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ addr.sun_path[0] = '\0';
+ len = strlen(DEFAULT_SOCKET) + 1 + sizeof(sa_family_t);
+ strncpy(&addr.sun_path[1], DEFAULT_SOCKET, len);
+
+ fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (fd == -1)
+ return -1;
+
+ if (connect(fd, (struct sockaddr *)&addr, len) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+int mpath_disconnect(int fd)
+{
+ return close(fd);
+}
+
+ssize_t mpath_recv_reply_len(int fd, unsigned int timeout)
+{
+ size_t len;
+ ssize_t ret;
+
+ ret = read_all(fd, &len, sizeof(len), timeout);
+ if (ret < 0)
+ return ret;
+ if (ret != sizeof(len)) {
+ errno = EIO;
+ return -1;
+ }
+ return len;
+}
+
+int mpath_recv_reply_data(int fd, char *reply, size_t len,
+ unsigned int timeout)
+{
+ ssize_t ret;
+
+ ret = read_all(fd, reply, len, timeout);
+ if (ret < 0)
+ return ret;
+ if (ret != len) {
+ errno = EIO;
+ return -1;
+ }
+ reply[len - 1] = '\0';
+ return 0;
+}
+
+int mpath_recv_reply(int fd, char **reply, unsigned int timeout)
+{
+ int err;
+ ssize_t len;
+
+ *reply = NULL;
+ len = mpath_recv_reply_len(fd, timeout);
+ if (len <= 0)
+ return -1;
+ *reply = malloc(len);
+ if (!*reply)
+ return -1;
+ err = mpath_recv_reply_data(fd, *reply, len, timeout);
+ if (err) {
+ free(*reply);
+ *reply = NULL;
+ return -1;
+ }
+ return 0;
+}
+
+int mpath_send_cmd(int fd, const char *cmd)
+{
+ size_t len;
+
+ if (cmd != NULL)
+ len = strlen(cmd) + 1;
+ else
+ len = 0;
+ if (write_all(fd, &len, sizeof(len)) != sizeof(len))
+ return -1;
+ if (len && write_all(fd, cmd, len) != len)
+ return -1;
+ return 0;
+}
+
+int mpath_process_cmd(int fd, const char *cmd, char **reply,
+ unsigned int timeout)
+{
+ if (mpath_send_cmd(fd, cmd) != 0)
+ return -1;
+ return mpath_recv_reply(fd, reply, timeout);
+}
Index: multipath-tools-130222/libmpathcmd/mpath_cmd.h
===================================================================
--- /dev/null
+++ multipath-tools-130222/libmpathcmd/mpath_cmd.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This file is part of the device-mapper multipath userspace tools.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef LIB_MPATH_CMD_H
+#define LIB_MPATH_CMD_H
+
+#ifdef __cpluscplus
+extern "C" {
+#endif
+
+#define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd"
+#define DEFAULT_REPLY_TIMEOUT 10000
+
+
+/*
+ * DESCRIPTION:
+ * Connect to the running multipathd daemon. On systems with the
+ * multipathd.socket systemd unit file installed, this command will
+ * start multipathd if it is not already running. This function
+ * must be run before any of the others in this library
+ *
+ * RETURNS:
+ * A file descriptor on success. -1 on failure (with errno set).
+ */
+int mpath_connect(void);
+
+
+/*
+ * DESCRIPTION:
+ * Disconnect from the multipathd daemon. This function must be
+ * run after after processing all the multipath commands.
+ *
+ * RETURNS:
+ * 0 on success. -1 on failure (with errno set).
+ */
+int mpath_disconnect(int fd);
+
+
+/*
+ * DESCRIPTION
+ * Send multipathd a command and return the reply. This function
+ * does the same as calling mpath_send_cmd() and then
+ * mpath_recv_reply()
+ *
+ * RETURNS:
+ * 0 on successs, and reply will either be NULL (if there was no
+ * reply data), or point to the reply string, which must be freed by
+ * the caller. -1 on failure (with errno set).
+ */
+int mpath_process_cmd(int fd, const char *cmd, char **reply,
+ unsigned int timeout);
+
+
+/*
+ * DESCRIPTION:
+ * Send a command to multipathd
+ *
+ * RETURNS:
+ * 0 on success. -1 on failure (with errno set)
+ */
+int mpath_send_cmd(int fd, const char *cmd);
+
+
+/*
+ * DESCRIPTION:
+ * Return a reply from multipathd for a previously sent command.
+ * This is equivalent to calling mpath_recv_reply_len(), allocating
+ * a buffer of the appropriate size, and then calling
+ * mpath_recv_reply_data() with that buffer.
+ *
+ * RETURNS:
+ * 0 on success, and reply will either be NULL (if there was no
+ * reply data), or point to the reply string, which must be freed by
+ * the caller, -1 on failure (with errno set).
+ */
+int mpath_recv_reply(int fd, char **reply, unsigned int timeout);
+
+
+/*
+ * DESCRIPTION:
+ * Return the size of the upcoming reply data from the sent multipath
+ * command. This must be called before calling mpath_recv_reply_data().
+ *
+ * RETURNS:
+ * The required size of the reply data buffer on success. -1 on
+ * failure (with errno set).
+ */
+ssize_t mpath_recv_reply_len(int fd, unsigned int timeout);
+
+
+/*
+ * DESCRIPTION:
+ * Return the reply data from the sent multipath command.
+ * mpath_recv_reply_len must be called first. reply must point to a
+ * buffer of len size.
+ *
+ * RETURNS:
+ * 0 on success, and reply will contain the reply data string. -1
+ * on failure (with errno set).
+ */
+int mpath_recv_reply_data(int fd, char *reply, size_t len,
+ unsigned int timeout);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* LIB_MPATH_CMD_H */
Index: multipath-tools-130222/libmpathpersist/Makefile
===================================================================
--- multipath-tools-130222.orig/libmpathpersist/Makefile
+++ multipath-tools-130222/libmpathpersist/Makefile
@@ -10,8 +10,9 @@ DEVLIB = libmpathpersist.so
LIBS = $(DEVLIB).$(SONAME)
-CFLAGS += -fPIC -I$(multipathdir) -I$(mpathpersistdir)
-LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath
+CFLAGS += -fPIC -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir)
+LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath \
+ -L$(mpathcmddir) -lmpathcmd
OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o
Index: multipath-tools-130222/libmpathpersist/mpath_updatepr.c
===================================================================
--- multipath-tools-130222.orig/libmpathpersist/mpath_updatepr.c
+++ multipath-tools-130222/libmpathpersist/mpath_updatepr.c
@@ -12,9 +12,9 @@
#include <sys/poll.h>
#include <errno.h>
#include <debug.h>
+#include <mpath_cmd.h>
+#include <uxsock.h>
#include "memory.h"
-#include "../libmultipath/uxsock.h"
-#include "../libmultipath/defaults.h"
unsigned long mem_allocated; /* Total memory used in Bytes */
@@ -23,10 +23,9 @@ int update_prflag(char * arg1, char * ar
int fd;
char str[64];
char *reply;
- size_t len;
int ret = 0;
- fd = ux_socket_connect(DEFAULT_SOCKET);
+ fd = mpath_connect();
if (fd == -1) {
condlog (0, "ux socket connect error");
return 1 ;
@@ -34,18 +33,23 @@ int update_prflag(char * arg1, char * ar
snprintf(str,sizeof(str),"map %s %s", arg1, arg2);
condlog (2, "%s: pr flag message=%s", arg1, str);
- send_packet(fd, str, strlen(str) + 1);
- recv_packet(fd, &reply, &len);
-
- condlog (2, "%s: message=%s reply=%s", arg1, str, reply);
- if (!reply || strncmp(reply,"ok", 2) == 0)
- ret = -1;
- else if (strncmp(reply, "fail", 4) == 0)
+ send_packet(fd, str);
+ ret = recv_packet(fd, &reply);
+ if (ret < 0) {
+ condlog(2, "%s: message=%s recv error=%d", arg1, str, errno);
ret = -2;
- else{
- ret = atoi(reply);
+ } else {
+ condlog (2, "%s: message=%s reply=%s", arg1, str, reply);
+ if (!reply || strncmp(reply,"ok", 2) == 0)
+ ret = -1;
+ else if (strncmp(reply, "fail", 4) == 0)
+ ret = -2;
+ else{
+ ret = atoi(reply);
+ }
}
free(reply);
+ mpath_disconnect(fd);
return ret;
}
Index: multipath-tools-130222/libmultipath/Makefile
===================================================================
--- multipath-tools-130222.orig/libmultipath/Makefile
+++ multipath-tools-130222/libmultipath/Makefile
@@ -7,8 +7,8 @@ include ../Makefile.inc
SONAME=0
DEVLIB = libmultipath.so
LIBS = $(DEVLIB).$(SONAME)
-LIBDEPS = -lpthread -ldl -ldevmapper -ludev
-CFLAGS += -fPIC
+LIBDEPS = -lpthread -ldl -ldevmapper -ludev -L$(mpathcmddir) -lmpathcmd
+CFLAGS += -fPIC -I$(mpathcmddir)
OBJS = memory.o parser.o vector.o devmapper.o \
hwtable.o blacklist.o util.o dmparser.o config.o \
Index: multipath-tools-130222/libmultipath/config.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/config.c
+++ multipath-tools-130222/libmultipath/config.c
@@ -25,6 +25,7 @@
#include "prio.h"
#include "devmapper.h"
#include "version.h"
+#include "mpath_cmd.h"
static int
hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
Index: multipath-tools-130222/libmultipath/configure.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/configure.c
+++ multipath-tools-130222/libmultipath/configure.c
@@ -14,6 +14,7 @@
#include <errno.h>
#include <libdevmapper.h>
#include <libudev.h>
+#include <mpath_cmd.h>
#include "checkers.h"
#include "vector.h"
@@ -752,16 +753,15 @@ check_daemon(void)
{
int fd;
char *reply;
- size_t len;
int ret = 0;
- fd = ux_socket_connect(DEFAULT_SOCKET);
+ fd = mpath_connect();
if (fd == -1)
return 0;
- if (send_packet(fd, "show daemon", 12) != 0)
+ if (send_packet(fd, "show daemon") != 0)
goto out;
- if (recv_packet(fd, &reply, &len) != 0)
+ if (recv_packet(fd, &reply) != 0)
goto out;
if (strstr(reply, "shutdown"))
@@ -772,7 +772,7 @@ check_daemon(void)
out_free:
FREE(reply);
out:
- close(fd);
+ mpath_disconnect(fd);
return ret;
}
Index: multipath-tools-130222/libmultipath/uxsock.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/uxsock.c
+++ multipath-tools-130222/libmultipath/uxsock.c
@@ -16,37 +16,10 @@
#include <sys/poll.h>
#include <signal.h>
#include <errno.h>
+#include <mpath_cmd.h>
#include "memory.h"
#include "uxsock.h"
-
-/*
- * connect to a unix domain socket
- */
-int ux_socket_connect(const char *name)
-{
- int fd, len;
- struct sockaddr_un addr;
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_LOCAL;
- addr.sun_path[0] = '\0';
- len = strlen(name) + 1 + sizeof(sa_family_t);
- strncpy(&addr.sun_path[1], name, len);
-
- fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (fd == -1) {
- return -1;
- }
-
- if (connect(fd, (struct sockaddr *)&addr, len) == -1) {
- close(fd);
- return -1;
- }
-
- return fd;
-}
-
/*
* create a unix domain socket and start listening on it
* return a file descriptor open on the socket
@@ -102,32 +75,9 @@ size_t write_all(int fd, const void *buf
}
/*
- * keep reading until its all read
- */
-size_t read_all(int fd, void *buf, size_t len)
-{
- size_t total = 0;
-
- while (len) {
- ssize_t n = read(fd, buf, len);
- if (n < 0) {
- if ((errno == EINTR) || (errno == EAGAIN))
- continue;
- return total;
- }
- if (!n)
- return total;
- buf = n + (char *)buf;
- len -= n;
- total += n;
- }
- return total;
-}
-
-/*
* send a packet in length prefix format
*/
-int send_packet(int fd, const char *buf, size_t len)
+int send_packet(int fd, const char *buf)
{
int ret = 0;
sigset_t set, old;
@@ -137,10 +87,7 @@ int send_packet(int fd, const char *buf,
sigaddset(&set, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &set, &old);
- if (write_all(fd, &len, sizeof(len)) != sizeof(len))
- ret = -1;
- if (!ret && write_all(fd, buf, len) != len)
- ret = -1;
+ ret = mpath_send_cmd(fd, buf);
/* And unblock it again */
pthread_sigmask(SIG_SETMASK, &old, NULL);
@@ -151,25 +98,24 @@ int send_packet(int fd, const char *buf,
/*
* receive a packet in length prefix format
*/
-int recv_packet(int fd, char **buf, size_t *len)
+int recv_packet(int fd, char **buf)
{
- if (read_all(fd, len, sizeof(*len)) != sizeof(*len)) {
- (*buf) = NULL;
- *len = 0;
- return -1;
- }
- if (len == 0) {
- (*buf) = NULL;
- return 0;
- }
- (*buf) = MALLOC(*len);
+ int err;
+ ssize_t len;
+ unsigned int timeout = DEFAULT_REPLY_TIMEOUT;
+
+ *buf = NULL;
+ len = mpath_recv_reply_len(fd, timeout);
+ if (len <= 0)
+ return len;
+ (*buf) = MALLOC(len);
if (!*buf)
- return -1;
- if (read_all(fd, *buf, *len) != *len) {
+ return -ENOMEM;
+ err = mpath_recv_reply_data(fd, *buf, len, timeout);
+ if (err) {
FREE(*buf);
(*buf) = NULL;
- *len = 0;
- return -1;
+ return err;
}
return 0;
}
Index: multipath-tools-130222/libmultipath/uxsock.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/uxsock.h
+++ multipath-tools-130222/libmultipath/uxsock.h
@@ -1,7 +1,5 @@
/* some prototypes */
-int ux_socket_connect(const char *name);
int ux_socket_listen(const char *name);
-int send_packet(int fd, const char *buf, size_t len);
-int recv_packet(int fd, char **buf, size_t *len);
+int send_packet(int fd, const char *buf);
+int recv_packet(int fd, char **buf);
size_t write_all(int fd, const void *buf, size_t len);
-size_t read_all(int fd, void *buf, size_t len);
Index: multipath-tools-130222/mpathpersist/Makefile
===================================================================
--- multipath-tools-130222.orig/mpathpersist/Makefile
+++ multipath-tools-130222/mpathpersist/Makefile
@@ -5,7 +5,7 @@ include ../Makefile.inc
OBJS = main.o
CFLAGS += -I$(multipathdir) -I$(mpathpersistdir)
-LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath -ludev
+LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -L$(mpathcmddir) -lmpathcmd -lmultipath -ludev
EXEC = mpathpersist
Index: multipath-tools-130222/multipath/Makefile
===================================================================
--- multipath-tools-130222.orig/multipath/Makefile
+++ multipath-tools-130222/multipath/Makefile
@@ -6,8 +6,9 @@ include ../Makefile.inc
OBJS = main.o
-CFLAGS += -fPIC -I$(multipathdir)
-LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath -ludev
+CFLAGS += -I$(multipathdir) -I$(mpathcmddir)
+LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath -ludev \
+ -L$(mpathcmddir) -lmpathcmd
EXEC = multipath
Index: multipath-tools-130222/multipathd/Makefile
===================================================================
--- multipath-tools-130222.orig/multipathd/Makefile
+++ multipath-tools-130222/multipathd/Makefile
@@ -5,10 +5,10 @@ include ../Makefile.inc
#
# basic flags setting
#
-CFLAGS += -fPIE -DPIE -I$(multipathdir) -I$(mpathpersistdir)
+CFLAGS += -fPIE -DPIE -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir)
LDFLAGS += -lpthread -ldevmapper -lreadline -ludev -ldl \
-L$(multipathdir) -lmultipath -L$(mpathpersistdir) -lmpathpersist \
- -Wl,-z,now -pie
+ -L$(mpathcmddir) -lmpathcmd -Wl,-z,now -pie
#
# debuging stuff
Index: multipath-tools-130222/multipathd/uxclnt.c
===================================================================
--- multipath-tools-130222.orig/multipathd/uxclnt.c
+++ multipath-tools-130222/multipathd/uxclnt.c
@@ -17,6 +17,7 @@
#include <readline/readline.h>
#include <readline/history.h>
+#include <mpath_cmd.h>
#include <uxsock.h>
#include <memory.h>
#include <defaults.h>
@@ -49,7 +50,6 @@ static void process(int fd)
rl_readline_name = "multipathd";
rl_completion_entry_function = key_generator;
while ((line = readline("multipathd> "))) {
- size_t len;
size_t llen = strlen(line);
if (!llen) {
@@ -61,8 +61,8 @@ static void process(int fd)
if (!strncmp(line, "quit", 4) && llen == 4)
break;
- if (send_packet(fd, line, llen + 1) != 0) break;
- if (recv_packet(fd, &reply, &len) != 0) break;
+ if (send_packet(fd, line) != 0) break;
+ if (recv_packet(fd, &reply) != 0) break;
print_reply(reply);
@@ -77,13 +77,12 @@ static void process(int fd)
static void process_req(int fd, char * inbuf)
{
char *reply;
- size_t len;
- if (send_packet(fd, inbuf, strlen(inbuf) + 1) != 0) {
+ if (send_packet(fd, inbuf) != 0) {
printf("cannot send packet\n");
return;
}
- if (recv_packet(fd, &reply, &len) != 0)
+ if (recv_packet(fd, &reply) != 0)
printf("error receiving packet\n");
else {
printf("%s", reply);
@@ -98,7 +97,7 @@ int uxclnt(char * inbuf)
{
int fd;
- fd = ux_socket_connect(DEFAULT_SOCKET);
+ fd = mpath_connect();
if (fd == -1) {
perror("ux_socket_connect");
exit(1);
Index: multipath-tools-130222/multipathd/uxlsnr.c
===================================================================
--- multipath-tools-130222.orig/multipathd/uxlsnr.c
+++ multipath-tools-130222/multipathd/uxlsnr.c
@@ -29,6 +29,7 @@
#include <structs_vec.h>
#include <uxsock.h>
#include <defaults.h>
+#include <mpath_cmd.h>
#include "main.h"
#include "cli.h"
@@ -108,7 +109,6 @@ void * uxsock_listen(int (*uxsock_trigge
void * trigger_data)
{
int ux_sock;
- size_t len;
int rlen;
char *inbuf;
char *reply;
@@ -171,16 +171,15 @@ void * uxsock_listen(int (*uxsock_trigge
struct client *next = c->next;
if (polls[i].revents & POLLIN) {
- if (recv_packet(c->fd, &inbuf, &len) != 0) {
+ if (recv_packet(c->fd, &inbuf) != 0) {
dead_client(c);
} else {
- inbuf[len - 1] = 0;
condlog(4, "Got request [%s]", inbuf);
uxsock_trigger(inbuf, &reply, &rlen,
trigger_data);
if (reply) {
- if (send_packet(c->fd, reply,
- rlen) != 0) {
+ if (send_packet(c->fd,
+ reply) != 0) {
dead_client(c);
}
condlog(4, "Reply [%d bytes]",

View File

@ -0,0 +1,280 @@
[PATCH] Multipath: Remove duplicated memset() for multipathd show command.
[PATCH] multipath-tools: New way to limit the IPC command length.
[PATCH] multipath-tools: Perform socket client uid check on IPC commands.
Signed-off-by: Gris Ge <fge@redhat.com>
---
libmultipath/print.c | 10 ----------
libmultipath/uxsock.c | 38 +++++++++++++++++++++++++++++---------
libmultipath/uxsock.h | 9 +++++++++
multipathd/main.c | 15 +++++++++++++--
multipathd/uxlsnr.c | 31 ++++++++++++++++++++++++++-----
multipathd/uxlsnr.h | 8 +++++---
6 files changed, 82 insertions(+), 29 deletions(-)
Index: multipath-tools-130222/libmultipath/print.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/print.c
+++ multipath-tools-130222/libmultipath/print.c
@@ -771,8 +771,6 @@ snprint_multipath_header (char * line, i
int fwd;
struct multipath_data * data;
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -806,8 +804,6 @@ snprint_multipath (char * line, int len,
struct multipath_data * data;
char buff[MAX_FIELD_LEN] = {};
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -842,8 +838,6 @@ snprint_path_header (char * line, int le
int fwd;
struct path_data * data;
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -877,8 +871,6 @@ snprint_path (char * line, int len, char
struct path_data * data;
char buff[MAX_FIELD_LEN];
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -914,8 +906,6 @@ snprint_pathgroup (char * line, int len,
struct pathgroup_data * data;
char buff[MAX_FIELD_LEN];
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
Index: multipath-tools-130222/libmultipath/uxsock.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/uxsock.c
+++ multipath-tools-130222/libmultipath/uxsock.c
@@ -20,6 +20,15 @@
#include "memory.h"
#include "uxsock.h"
+
+/*
+ * Code is similar with mpath_recv_reply() with data size limitation
+ * and debug-able malloc.
+ * When limit == 0, it means no limit on data size, used for socket client
+ * to receiving data from multipathd.
+ */
+static int _recv_packet(int fd, char **buf, ssize_t limit);
+
/*
* create a unix domain socket and start listening on it
* return a file descriptor open on the socket
@@ -95,27 +104,38 @@ int send_packet(int fd, const char *buf)
return ret;
}
-/*
- * receive a packet in length prefix format
- */
-int recv_packet(int fd, char **buf)
+static int _recv_packet(int fd, char **buf, ssize_t limit)
{
- int err;
- ssize_t len;
+ int err = 0;
+ ssize_t len = 0;
unsigned int timeout = DEFAULT_REPLY_TIMEOUT;
*buf = NULL;
len = mpath_recv_reply_len(fd, timeout);
if (len <= 0)
return len;
+ if ((limit > 0) && (len > limit))
+ return -EINVAL;
(*buf) = MALLOC(len);
if (!*buf)
return -ENOMEM;
err = mpath_recv_reply_data(fd, *buf, len, timeout);
- if (err) {
+ if (err != 0) {
FREE(*buf);
(*buf) = NULL;
- return err;
}
- return 0;
+ return err;
+}
+
+/*
+ * receive a packet in length prefix format
+ */
+int recv_packet(int fd, char **buf)
+{
+ return _recv_packet(fd, buf, 0 /* no limit */);
+}
+
+int recv_packet_from_client(int fd, char **buf)
+{
+ return _recv_packet(fd, buf, _MAX_CMD_LEN);
}
Index: multipath-tools-130222/libmultipath/uxsock.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/uxsock.h
+++ multipath-tools-130222/libmultipath/uxsock.h
@@ -3,3 +3,12 @@ int ux_socket_listen(const char *name);
int send_packet(int fd, const char *buf);
int recv_packet(int fd, char **buf);
size_t write_all(int fd, const void *buf, size_t len);
+
+#define _MAX_CMD_LEN 512
+
+/*
+ * Used for receiving socket command from untrusted socket client where data
+ * size is restricted to 512(_MAX_CMD_LEN) at most.
+ * Return -EINVAL if data length requested by client exceeded the _MAX_CMD_LEN.
+ */
+int recv_packet_from_client(int fd, char **buf);
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -18,6 +18,7 @@
#include <linux/oom.h>
#include <libudev.h>
#include <semaphore.h>
+#include <stdbool.h>
#include <mpath_persist.h>
#include "prioritizers/alua_rtpg.h"
@@ -859,7 +860,8 @@ map_discovery (struct vectors * vecs)
}
int
-uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data)
+uxsock_trigger (char * str, char ** reply, int * len, bool is_root,
+ void * trigger_data)
{
struct vectors * vecs;
int r;
@@ -872,6 +874,15 @@ uxsock_trigger (char * str, char ** repl
lock(vecs->lock);
pthread_testcancel();
+ if ((str != NULL) && (is_root == false) &&
+ (strncmp(str, "list", strlen("list")) != 0) &&
+ (strncmp(str, "show", strlen("show")) != 0)) {
+ *reply = STRDUP("permission deny: need to be root");
+ *len = strlen(*reply) + 1;
+ r = 1;
+ goto out;
+ }
+
r = parse_cmd(str, reply, len, vecs);
if (r > 0) {
@@ -885,7 +896,7 @@ uxsock_trigger (char * str, char ** repl
r = 0;
}
/* else if (r < 0) leave *reply alone */
-
+out:
lock_cleanup_pop(vecs->lock);
return r;
}
Index: multipath-tools-130222/multipathd/uxlsnr.c
===================================================================
--- multipath-tools-130222.orig/multipathd/uxlsnr.c
+++ multipath-tools-130222/multipathd/uxlsnr.c
@@ -21,6 +21,7 @@
#include <sys/un.h>
#include <sys/poll.h>
#include <signal.h>
+#include <stdbool.h>
#include <checkers.h>
#include <memory.h>
#include <debug.h>
@@ -48,6 +49,23 @@ struct pollfd *polls;
volatile sig_atomic_t reconfig_sig = 0;
volatile sig_atomic_t log_reset_sig = 0;
+static bool _socket_client_is_root(int fd);
+
+static bool _socket_client_is_root(int fd)
+{
+ socklen_t len = 0;
+ struct ucred uc;
+
+ len = sizeof(struct ucred);
+ if ((fd >= 0) &&
+ (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &uc, &len) == 0) &&
+ (uc.uid == 0))
+ return true;
+
+ /* Treat error as not root client */
+ return false;
+}
+
/*
* handle a new client joining
*/
@@ -105,8 +123,7 @@ void uxsock_cleanup(void *arg)
/*
* entry point
*/
-void * uxsock_listen(int (*uxsock_trigger)(char *, char **, int *, void *),
- void * trigger_data)
+void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
{
int ux_sock;
int rlen;
@@ -171,12 +188,16 @@ void * uxsock_listen(int (*uxsock_trigge
struct client *next = c->next;
if (polls[i].revents & POLLIN) {
- if (recv_packet(c->fd, &inbuf) != 0) {
+ if (recv_packet_from_client(c->fd,
+ &inbuf) != 0) {
dead_client(c);
+ } else if (!inbuf) {
+ condlog(4, "recv_packet_from_client "
+ "get null request");
+ continue;
} else {
condlog(4, "Got request [%s]", inbuf);
- uxsock_trigger(inbuf, &reply, &rlen,
- trigger_data);
+ uxsock_trigger(inbuf, &reply, &rlen, _socket_client_is_root(c->fd), trigger_data);
if (reply) {
if (send_packet(c->fd,
reply) != 0) {
Index: multipath-tools-130222/multipathd/uxlsnr.h
===================================================================
--- multipath-tools-130222.orig/multipathd/uxlsnr.h
+++ multipath-tools-130222/multipathd/uxlsnr.h
@@ -1,9 +1,11 @@
#ifndef _UXLSNR_H
#define _UXLSNR_H
-void * uxsock_listen(int (*uxsock_trigger)
- (char *, char **, int *, void *),
- void * trigger_data);
+#include <stdbool.h>
+
+typedef int (uxsock_trigger_fn)(char *, char **, int *, bool, void *);
+
+void *uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data);
extern volatile sig_atomic_t reconfig_sig;
extern volatile sig_atomic_t log_reset_sig;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
---
libmpathpersist/Makefile | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
Index: multipath-tools-130222/libmpathpersist/Makefile
===================================================================
--- multipath-tools-130222.orig/libmpathpersist/Makefile
+++ multipath-tools-130222/libmpathpersist/Makefile
@@ -33,12 +33,14 @@ install: $(LIBS)
ln -sf $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
install -m 644 mpath_persistent_reserve_in.3.gz $(DESTDIR)$(man3dir)
install -m 644 mpath_persistent_reserve_out.3.gz $(DESTDIR)$(man3dir)
+ $(INSTALL_PROGRAM) -m 644 mpath_persist.h $(DESTDIR)$(includedir)
uninstall:
rm -f $(DESTDIR)$(syslibdir)/$(LIBS)
rm -f $(DESTDIR)$(syslibdir)/$(DEVLIB)
- rm $(DESTDIR)$(mandir)/mpath_persistent_reserve_in.3.gz
- rm $(DESTDIR)$(mandir)/mpath_persistent_reserve_out.3.gz
+ rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_in.3.gz
+ rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_out.3.gz
+ rm -f $(DESTDIR)$(includedir)/mpath_persist.h
clean:
rm -f core *.a *.o

35
0211-RH-strlen-fix.patch Normal file
View File

@ -0,0 +1,35 @@
---
multipathd/main.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -878,7 +878,8 @@ uxsock_trigger (char * str, char ** repl
(strncmp(str, "list", strlen("list")) != 0) &&
(strncmp(str, "show", strlen("show")) != 0)) {
*reply = STRDUP("permission deny: need to be root");
- *len = strlen(*reply) + 1;
+ if (*reply)
+ *len = strlen(*reply) + 1;
r = 1;
goto out;
}
@@ -887,12 +888,14 @@ uxsock_trigger (char * str, char ** repl
if (r > 0) {
*reply = STRDUP("fail\n");
- *len = strlen(*reply) + 1;
+ if (*reply)
+ *len = strlen(*reply) + 1;
r = 1;
}
else if (!r && *len == 0) {
*reply = STRDUP("ok\n");
- *len = strlen(*reply) + 1;
+ if (*reply)
+ *len = strlen(*reply) + 1;
r = 0;
}
/* else if (r < 0) leave *reply alone */

View File

@ -0,0 +1,56 @@
---
libmultipath/devmapper.c | 10 ++++++----
libmultipath/structs.h | 1 +
multipathd/main.c | 5 +++--
3 files changed, 10 insertions(+), 6 deletions(-)
Index: multipath-tools-130222/libmultipath/devmapper.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/devmapper.c
+++ multipath-tools-130222/libmultipath/devmapper.c
@@ -358,10 +358,12 @@ dm_addmap_create (struct multipath *mpp,
extern int
dm_addmap_reload (struct multipath *mpp, char *params) {
sysfs_set_max_sectors_kb(mpp, 1);
- if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW, SKIP_KPARTX_OFF))
- return 1;
- if (errno != EROFS)
- return 0;
+ if (!mpp->force_readonly) {
+ 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, SKIP_KPARTX_OFF);
}
Index: multipath-tools-130222/libmultipath/structs.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/structs.h
+++ multipath-tools-130222/libmultipath/structs.h
@@ -259,6 +259,7 @@ struct multipath {
int force_udev_reload;
int skip_kpartx;
int max_sectors_kb;
+ int force_readonly;
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
@@ -831,9 +831,10 @@ uev_update_path (struct uevent *uev, str
pp->mpp->wait_for_udev = 2;
return 0;
}
-
+ if (ro == 1)
+ pp->mpp->force_readonly = 1;
retval = reload_map(vecs, pp->mpp, 0);
-
+ pp->mpp->force_readonly = 0;
condlog(2, "%s: map %s reloaded (retval %d)",
uev->kernel, pp->mpp->alias, retval);
}

View File

@ -1,7 +1,7 @@
Summary: Tools to manage multipath devices using device-mapper Summary: Tools to manage multipath devices using device-mapper
Name: device-mapper-multipath Name: device-mapper-multipath
Version: 0.4.9 Version: 0.4.9
Release: 85%{?dist} Release: 86%{?dist}
License: GPL+ License: GPL+
Group: System Environment/Base Group: System Environment/Base
URL: http://christophe.varoqui.free.fr/ URL: http://christophe.varoqui.free.fr/
@ -180,21 +180,64 @@ Patch0169: 0169-UPBZ-1353357-json-output.patch
Patch0170: 0170-UPBZ-1352925-fix-typo.patch Patch0170: 0170-UPBZ-1352925-fix-typo.patch
Patch0171: 0171-UPBZ-1356651-allow-zero-size.patch Patch0171: 0171-UPBZ-1356651-allow-zero-size.patch
Patch0172: 0172-RHBZ-1350931-no-active-add.patch Patch0172: 0172-RHBZ-1350931-no-active-add.patch
Patch0173: 0173-RH-update-man-page.patch
Patch0174: 0174-RHBZ-1362396-modprobe.patch
Patch0175: 0175-RHBZ-1357382-ordering.patch
Patch0176: 0176-RHBZ-1363830-fix-rename.patch
Patch0177: 0177-libmultipath-correctly-initialize-pp-sg_id.patch
Patch0178: 0178-libmultipath-add-rbd-discovery.patch
Patch0179: 0179-multipath-tools-add-checker-callout-to-repair-path.patch
Patch0180: 0180-multipath-tools-Add-rbd-checker.patch
Patch0181: 0181-multipath-tools-Add-rbd-to-the-hwtable.patch
Patch0182: 0182-multipath-tools-check-for-initialized-checker-before.patch
Patch0183: 0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch
Patch0184: 0184-rbd-fix-sync-repair-support.patch
Patch0185: 0185-rbd-check-for-nonshared-clients.patch
Patch0186: 0186-rbd-check-for-exclusive-lock-enabled.patch
Patch0187: 0187-rbd-fixup-log-messages.patch
Patch0188: 0188-RHBZ-1368501-dont-exit.patch
Patch0189: 0189-RHBZ-1368211-remove-retries.patch
Patch0190: 0190-RHBZ-1380602-rbd-lock-on-read.patch
Patch0191: 0191-RHBZ-1169168-disable-changed-paths.patch
Patch0192: 0192-RHBZ-1362409-infinibox-config.patch
Patch0194: 0194-RHBZ-1351964-kpartx-recurse.patch
Patch0195: 0195-RHBZ-1359510-no-daemon-msg.patch
Patch0196: 0196-RHBZ-1239173-dont-set-flag.patch
Patch0197: 0197-RHBZ-1394059-max-sectors-kb.patch
Patch0198: 0198-RHBZ-1372032-detect-path-checker.patch
Patch0199: 0199-RHBZ-1279355-3pardata-config.patch
Patch0200: 0200-RHBZ-1402092-orphan-status.patch
Patch0201: 0201-RHBZ-1403552-silence-warning.patch
Patch0202: 0202-RHBZ-1362120-skip-prio.patch
Patch0203: 0203-RHBZ-1363718-add-msgs.patch
Patch0204: 0204-RHBZ-1406226-nimble-config.patch
Patch0205: 0205-RHBZ-1416569-reset-stats.patch
Patch0206: 0206-RHBZ-1239173-pt2-no-paths.patch
Patch0207: 0207-UP-add-libmpathcmd.patch
Patch0208: 0208-UPBZ-1430097-multipathd-IPC-changes.patch
Patch0209: 0209-UPBZ-1430097-multipath-C-API.patch
Patch0210: 0210-RH-fix-uninstall.patch
Patch0211: 0211-RH-strlen-fix.patch
Patch0212: 0212-RHBZ-1431562-for-read-only.patch
# runtime # runtime
Requires: %{name}-libs = %{version}-%{release} Requires: %{name}-libs = %{version}-%{release}
Requires: kpartx = %{version}-%{release} Requires: kpartx = %{version}-%{release}
Requires: device-mapper >= 1.02.96 Requires: device-mapper >= 7:1.02.96
Requires: initscripts Requires: initscripts
Requires(post): systemd-units systemd-sysv chkconfig Requires(post): systemd-units systemd-sysv chkconfig
Requires(preun): systemd-units Requires(preun): systemd-units
Requires(postun): systemd-units Requires(postun): systemd-units
# build/setup # build/setup
BuildRequires: libaio-devel, device-mapper-devel >= 1.02.82-2 BuildRequires: libaio-devel, device-mapper-devel >= 1.02.89
BuildRequires: libselinux-devel, libsepol-devel BuildRequires: libselinux-devel, libsepol-devel
BuildRequires: readline-devel, ncurses-devel BuildRequires: readline-devel, ncurses-devel
BuildRequires: systemd-units, systemd-devel BuildRequires: systemd-units, systemd-devel
BuildRequires: json-c-devel, perl, pkgconfig
%ifarch x86_64
BuildRequires: librados2-devel
%endif
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
@ -212,9 +255,20 @@ Group: System Environment/Libraries
%description libs %description libs
The %{name}-libs provides the path checker The %{name}-libs provides the path checker
and prioritizer modules. It also contains the multipath shared library, and prioritizer modules. It also contains the libmpathpersist and
libmpathcmd shared libraries, as well as multipath's internal library,
libmultipath. libmultipath.
%package devel
Summary: Development libraries and headers for %{name}
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release}
%description devel
This package contains the files need to develop applications that use
device-mapper-multipath's lbmpathpersist and libmpathcmd libraries.
%if 0%{?fedora} < 23 %if 0%{?fedora} < 23
%package sysvinit %package sysvinit
Summary: SysV init script for device-mapper-multipath Summary: SysV init script for device-mapper-multipath
@ -232,6 +286,27 @@ Group: System Environment/Base
%description -n kpartx %description -n kpartx
kpartx manages partition creation and removal for device-mapper devices. kpartx manages partition creation and removal for device-mapper devices.
%package -n libdmmp
Summary: device-mapper-multipath C API library
Group: System Environment/Libraries
Requires: json-c
Requires: %{name} = %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release}
%description -n libdmmp
This package contains the shared library for the device-mapper-multipath
C API library.
%package -n libdmmp-devel
Summary: device-mapper-multipath C API library headers
Group: Development/Libraries
Requires: pkgconfig
Requires: libdmmp = %{version}-%{release}
%description -n libdmmp-devel
This package contains the files needed to develop applications that use
device-mapper-multipath's libdmmp C API library
%prep %prep
%setup -q -n multipath-tools-130222 %setup -q -n multipath-tools-130222
%patch0001 -p1 %patch0001 -p1
@ -405,12 +480,52 @@ kpartx manages partition creation and removal for device-mapper devices.
%patch0170 -p1 %patch0170 -p1
%patch0171 -p1 %patch0171 -p1
%patch0172 -p1 %patch0172 -p1
%patch0173 -p1
%patch0174 -p1
%patch0175 -p1
%patch0176 -p1
%patch0177 -p1
%patch0178 -p1
%patch0179 -p1
%patch0180 -p1
%patch0181 -p1
%patch0182 -p1
%patch0183 -p1
%patch0184 -p1
%patch0185 -p1
%patch0186 -p1
%patch0187 -p1
%patch0188 -p1
%patch0189 -p1
%patch0190 -p1
%patch0191 -p1
%patch0192 -p1
%patch0194 -p1
%patch0195 -p1
%patch0196 -p1
%patch0197 -p1
%patch0198 -p1
%patch0199 -p1
%patch0200 -p1
%patch0201 -p1
%patch0202 -p1
%patch0203 -p1
%patch0204 -p1
%patch0205 -p1
%patch0206 -p1
%patch0207 -p1
%patch0208 -p1
%patch0209 -p1
%patch0210 -p1
%patch0211 -p1
%patch0212 -p1
cp %{SOURCE1} . cp %{SOURCE1} .
%build %build
%define _sbindir /usr/sbin %define _sbindir /usr/sbin
%define _libdir /usr/%{_lib} %define _libdir /usr/%{_lib}
%define _libmpathdir %{_libdir}/multipath %define _libmpathdir %{_libdir}/multipath
%define _pkgconfdir %{_libdir}/pkgconfig
make %{?_smp_mflags} LIB=%{_lib} make %{?_smp_mflags} LIB=%{_lib}
%install %install
@ -422,7 +537,9 @@ make install \
syslibdir=%{_libdir} \ syslibdir=%{_libdir} \
libdir=%{_libmpathdir} \ libdir=%{_libmpathdir} \
rcdir=%{_initrddir} \ rcdir=%{_initrddir} \
unitdir=%{_unitdir} unitdir=%{_unitdir} \
includedir=%{_includedir} \
pkgconfdir=%{_pkgconfdir}
# tree fix up # tree fix up
install -d %{buildroot}/etc/multipath install -d %{buildroot}/etc/multipath
@ -464,8 +581,6 @@ fi
%{_sbindir}/mpathconf %{_sbindir}/mpathconf
%{_sbindir}/mpathpersist %{_sbindir}/mpathpersist
%{_unitdir}/multipathd.service %{_unitdir}/multipathd.service
%{_mandir}/man3/mpath_persistent_reserve_in.3.gz
%{_mandir}/man3/mpath_persistent_reserve_out.3.gz
%{_mandir}/man5/multipath.conf.5.gz %{_mandir}/man5/multipath.conf.5.gz
%{_mandir}/man8/multipath.8.gz %{_mandir}/man8/multipath.8.gz
%{_mandir}/man8/multipathd.8.gz %{_mandir}/man8/multipathd.8.gz
@ -486,8 +601,8 @@ fi
%license COPYING %license COPYING
%{_libdir}/libmultipath.so %{_libdir}/libmultipath.so
%{_libdir}/libmultipath.so.* %{_libdir}/libmultipath.so.*
%{_libdir}/libmpathpersist.so
%{_libdir}/libmpathpersist.so.* %{_libdir}/libmpathpersist.so.*
%{_libdir}/libmpathcmd.so.*
%dir %{_libmpathdir} %dir %{_libmpathdir}
%{_libmpathdir}/* %{_libmpathdir}/*
@ -495,6 +610,16 @@ fi
%postun libs -p /sbin/ldconfig %postun libs -p /sbin/ldconfig
%files devel
%defattr(-,root,root,-)
%doc AUTHOR COPYING
%{_libdir}/libmpathpersist.so
%{_libdir}/libmpathcmd.so
%{_includedir}/mpath_cmd.h
%{_includedir}/mpath_persist.h
%{_mandir}/man3/mpath_persistent_reserve_in.3.gz
%{_mandir}/man3/mpath_persistent_reserve_out.3.gz
%if 0%{?fedora} < 23 %if 0%{?fedora} < 23
%files sysvinit %files sysvinit
%{_initrddir}/multipathd %{_initrddir}/multipathd
@ -505,7 +630,114 @@ fi
%{_sbindir}/kpartx %{_sbindir}/kpartx
%{_mandir}/man8/kpartx.8.gz %{_mandir}/man8/kpartx.8.gz
%files -n libdmmp
%defattr(-,root,root,-)
%doc AUTHOR COPYING
%{_libdir}/libdmmp.so.*
%post -n libdmmp -p /sbin/ldconfig
%postun -n libdmmp -p /sbin/ldconfig
%files -n libdmmp-devel
%defattr(-,root,root,-)
%doc AUTHOR COPYING
%{_libdir}/libdmmp.so
%dir %{_includedir}/libdmmp
%{_includedir}/libdmmp/*
%{_mandir}/man3/dmmp_*
%{_mandir}/man3/libdmmp.h.3.gz
%{_pkgconfdir}/libdmmp.pc
%changelog %changelog
* Fri Apr 7 2017 Benjamin Marzinski <bmarzins@redhat.com> 0.4.9-86
- Modify 0136-RHBZ-1304687-wait-for-map-add.patch
* switch to missing_uev_wait_timeout to stop waiting for uev
- Refresh 0137-RHBZ-1280524-clear-chkr-msg.patch
- Refresh 0150-RHBZ-1253913-fix-startup-msg.patch
- Refresh 0154-UPBZ-1291406-disable-reinstate.patch
- Refresh 0156-UPBZ-1313324-dont-fail-discovery.patch
- Refresh 0161-RHBZ-1311659-no-kpartx.patch
- Refresh 0167-RHBZ-1335176-fix-show-cmds.patch
- Add 0173-RH-update-man-page.patch
- Add 0174-RHBZ-1362396-modprobe.patch
* make starting the multipathd service modprobe dm-multipath in the
sysvinit scripts
- Add 0175-RHBZ-1357382-ordering.patch
* force multipathd.service to start after systemd-udev-trigger.service
- Add 0176-RHBZ-1363830-fix-rename.patch
* initialized a variable to make dm_rename not fail randomly
- Add 0177-libmultipath-correctly-initialize-pp-sg_id.patch
* This and all the following patches add the rbd patch checker
- Add 0178-libmultipath-add-rbd-discovery.patch
- Add 0179-multipath-tools-add-checker-callout-to-repair-path.patch
- Add 0180-multipath-tools-Add-rbd-checker.patch
- Add 0181-multipath-tools-Add-rbd-to-the-hwtable.patch
- Add 0182-multipath-tools-check-for-initialized-checker-before.patch
- Add 0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch
- Add 0184-rbd-fix-sync-repair-support.patch
- Add 0185-rbd-check-for-nonshared-clients.patch
- Add 0186-rbd-check-for-exclusive-lock-enabled.patch
- Add 0187-rbd-fixup-log-messages.patch
- Add 0188-RHBZ-1368501-dont-exit.patch
* make multipathd not exit if it encounters recoverable errors on startup
- Add 0189-RHBZ-1368211-remove-retries.patch
* add "remove_retries" multipath.conf parameter to make multiple attempts
to remove a multipath device if it is busy.
- Add 0190-RHBZ-1380602-rbd-lock-on-read.patch
* pass lock_on_read when remapping image
- Add 0191-RHBZ-1169168-disable-changed-paths.patch
* add "disabled_changed_wwids" multipath.conf parameter to disable
paths whose wwid changes
- Add 0192-RHBZ-1362409-infinibox-config.patch
- Add 0194-RHBZ-1351964-kpartx-recurse.patch
* fix recursion on corrupt dos partitions
- Add 0195-RHBZ-1359510-no-daemon-msg.patch
* print a messages when multipathd isn't running
- Add 0196-RHBZ-1239173-dont-set-flag.patch
* don't set reload flag on reloads when you gain your first
valid path
- Add 0197-RHBZ-1394059-max-sectors-kb.patch
* add "max_sectors_kb" multipath.conf parameter to set max_sectors_kb
on a multipath device and all its path devices
- Add 0198-RHBZ-1372032-detect-path-checker.patch
* add "detect_checker" multipath.conf parameter to detect ALUA arrays
and set the path checker to TUR
- Add 0199-RHBZ-1279355-3pardata-config.patch
- Add 0200-RHBZ-1402092-orphan-status.patch
* clear status on orphan paths
- Add 0201-RHBZ-1403552-silence-warning.patch
- Add 0202-RHBZ-1362120-skip-prio.patch
* don't run prio on failed paths
- Add 0203-RHBZ-1363718-add-msgs.patch
- Add 0204-RHBZ-1406226-nimble-config.patch
- Add 0205-RHBZ-1416569-reset-stats.patch
* add "reset maps stats" and "reset map <map> stats" multipathd
interactive commands to reset the stats tracked by multipathd
- Add 0206-RHBZ-1239173-pt2-no-paths.patch
* make multipath correctly disable scanning and rules running when
it gets a uevent and there are not valid paths.
- Add 0207-UP-add-libmpathcmd.patch
* New shared library, libmpathcmd, that sends and receives messages from
multipathd. device-mapper-multipath now uses this library internally.
- Add 0208-UPBZ-1430097-multipathd-IPC-changes.patch
* validation that modifying commands are coming from root.
- Add 0209-UPBZ-1430097-multipath-C-API.patch
* New shared library. libdmmp, that presents the information from multipathd
in a structured manner to make it easier for callers to use
- Add 0210-RH-fix-uninstall.patch
* Minor compilation fixes
- Add 0211-RH-strlen-fix.patch
* checks that variables are not NULL before passing them to strlen
- Add 0212-RHBZ-1431562-for-read-only.patch
- Make 3 new subpackages
* device-mapper-multipath-devel, libdmmp, and libdmmp-devel. libmpathcmd
and libmpathprio are in device-mapper-multipath-libs and
device-mapper-multipath-devel. libdmmp is in its own subpackages
- Move libmpathprio devel files to device-mapper-multipath-devel
- Added BuildRequires on librados2-devel
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.9-85 * Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.9-85
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild