|
|
|
---
|
|
|
|
libmultipath/checkers.c | 19 +++-
|
|
|
|
libmultipath/checkers.h | 3
|
|
|
|
libmultipath/discovery.c | 183 +++++++++++++++++++++++++++++++++++++++------
|
|
|
|
libmultipath/discovery.h | 2
|
|
|
|
libmultipath/hwtable.c | 10 ++
|
|
|
|
libmultipath/structs.h | 1
|
|
|
|
libmultipath/uevent.c | 2
|
|
|
|
multipath/multipath.conf.5 | 3
|
|
|
|
multipathd/main.c | 27 ------
|
|
|
|
9 files changed, 194 insertions(+), 56 deletions(-)
|
|
|
|
|
|
|
|
Index: multipath-tools-130222/libmultipath/discovery.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/discovery.c
|
|
|
|
+++ multipath-tools-130222/libmultipath/discovery.c
|
|
|
|
@@ -13,6 +13,7 @@
|
|
|
|
#include <libgen.h>
|
|
|
|
#include <libudev.h>
|
|
|
|
#include <libdevmapper.h>
|
|
|
|
+#include <ctype.h>
|
|
|
|
|
|
|
|
#include "checkers.h"
|
|
|
|
#include "vector.h"
|
|
|
|
@@ -881,6 +882,46 @@ scsi_sysfs_pathinfo (struct path * pp)
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
+nvme_sysfs_pathinfo (struct path * pp)
|
|
|
|
+{
|
|
|
|
+ struct udev_device *parent;
|
|
|
|
+ const char *attr_path = NULL;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ attr_path = udev_device_get_sysname(pp->udev);
|
|
|
|
+ if (!attr_path)
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ if (sscanf(attr_path, "nvme%dn%d",
|
|
|
|
+ &pp->sg_id.host_no,
|
|
|
|
+ &pp->sg_id.scsi_id) != 2)
|
|
|
|
+ return 1;
|
|
|
|
+ pp->sg_id.channel = 0;
|
|
|
|
+ pp->sg_id.lun = 0;
|
|
|
|
+
|
|
|
|
+ parent = udev_device_get_parent(pp->udev);
|
|
|
|
+ if (!parent)
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ snprintf(pp->vendor_id, SCSI_VENDOR_SIZE, "NVME");
|
|
|
|
+ snprintf(pp->product_id, SCSI_PRODUCT_SIZE, "%s",
|
|
|
|
+ udev_device_get_sysattr_value(parent, "model"));
|
|
|
|
+ snprintf(pp->serial, SERIAL_SIZE, "%s",
|
|
|
|
+ udev_device_get_sysattr_value(parent, "serial"));
|
|
|
|
+ snprintf(pp->rev, SCSI_REV_SIZE, "%s",
|
|
|
|
+ udev_device_get_sysattr_value(parent, "firmware_rev"));
|
|
|
|
+
|
|
|
|
+ condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
|
|
|
|
+ condlog(3, "%s: product = %s", pp->dev, pp->product_id);
|
|
|
|
+ condlog(3, "%s: serial = %s", pp->dev, pp->serial);
|
|
|
|
+ condlog(3, "%s: rev = %s", pp->dev, pp->rev);
|
|
|
|
+
|
|
|
|
+ pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
rbd_sysfs_pathinfo (struct path * pp)
|
|
|
|
{
|
|
|
|
sprintf(pp->vendor_id, "Ceph");
|
|
|
|
@@ -1040,14 +1081,20 @@ path_offline (struct path * pp)
|
|
|
|
{
|
|
|
|
struct udev_device * parent;
|
|
|
|
char buff[SCSI_STATE_SIZE];
|
|
|
|
+ const char *subsys_type;
|
|
|
|
|
|
|
|
- if (pp->bus != SYSFS_BUS_SCSI)
|
|
|
|
+ if (pp->bus == SYSFS_BUS_SCSI)
|
|
|
|
+ subsys_type = "scsi";
|
|
|
|
+ else if (pp->bus == SYSFS_BUS_NVME)
|
|
|
|
+ subsys_type = "nvme";
|
|
|
|
+ else
|
|
|
|
return PATH_UP;
|
|
|
|
|
|
|
|
parent = pp->udev;
|
|
|
|
while (parent) {
|
|
|
|
const char *subsys = udev_device_get_subsystem(parent);
|
|
|
|
- if (subsys && !strncmp(subsys, "scsi", 4))
|
|
|
|
+ if (subsys && !strncmp(subsys, subsys_type,
|
|
|
|
+ strlen(subsys_type)))
|
|
|
|
break;
|
|
|
|
parent = udev_device_get_parent(parent);
|
|
|
|
}
|
|
|
|
@@ -1063,15 +1110,30 @@ path_offline (struct path * pp)
|
|
|
|
|
|
|
|
condlog(3, "%s: path state = %s", pp->dev, buff);
|
|
|
|
|
|
|
|
- if (!strncmp(buff, "offline", 7)) {
|
|
|
|
- pp->offline = 1;
|
|
|
|
- return PATH_DOWN;
|
|
|
|
+ if (pp->bus == SYSFS_BUS_SCSI) {
|
|
|
|
+ if (!strncmp(buff, "offline", 7)) {
|
|
|
|
+ pp->offline = 1;
|
|
|
|
+ return PATH_DOWN;
|
|
|
|
+ }
|
|
|
|
+ pp->offline = 0;
|
|
|
|
+ if (!strncmp(buff, "blocked", 7) ||
|
|
|
|
+ !strncmp(buff, "quiesce", 7))
|
|
|
|
+ return PATH_PENDING;
|
|
|
|
+ else if (!strncmp(buff, "running", 7))
|
|
|
|
+ return PATH_UP;
|
|
|
|
+ }
|
|
|
|
+ else if (pp->bus == SYSFS_BUS_NVME) {
|
|
|
|
+ if (!strncmp(buff, "dead", 4)) {
|
|
|
|
+ pp->offline = 1;
|
|
|
|
+ return PATH_DOWN;
|
|
|
|
+ }
|
|
|
|
+ pp->offline = 0;
|
|
|
|
+ if (!strncmp(buff, "new", 3) ||
|
|
|
|
+ !strncmp(buff, "deleting", 8))
|
|
|
|
+ return PATH_PENDING;
|
|
|
|
+ else if (!strncmp(buff, "live", 4))
|
|
|
|
+ return PATH_UP;
|
|
|
|
}
|
|
|
|
- pp->offline = 0;
|
|
|
|
- if (!strncmp(buff, "blocked", 7) || !strncmp(buff, "quiesce", 7))
|
|
|
|
- return PATH_PENDING;
|
|
|
|
- else if (!strncmp(buff, "running", 7))
|
|
|
|
- return PATH_UP;
|
|
|
|
|
|
|
|
return PATH_DOWN;
|
|
|
|
}
|
|
|
|
@@ -1091,6 +1153,8 @@ sysfs_pathinfo(struct path * pp)
|
|
|
|
pp->bus = SYSFS_BUS_SCSI;
|
|
|
|
if (!strncmp(pp->dev,"rbd", 3))
|
|
|
|
pp->bus = SYSFS_BUS_RBD;
|
|
|
|
+ if (!strncmp(pp->dev,"nvme", 4))
|
|
|
|
+ pp->bus = SYSFS_BUS_NVME;
|
|
|
|
|
|
|
|
if (pp->bus == SYSFS_BUS_UNDEF)
|
|
|
|
return 0;
|
|
|
|
@@ -1106,6 +1170,9 @@ sysfs_pathinfo(struct path * pp)
|
|
|
|
} else if (pp->bus == SYSFS_BUS_RBD) {
|
|
|
|
if (rbd_sysfs_pathinfo(pp))
|
|
|
|
return 1;
|
|
|
|
+ } else if (pp->bus == SYSFS_BUS_NVME) {
|
|
|
|
+ if (nvme_sysfs_pathinfo(pp))
|
|
|
|
+ return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
@@ -1132,7 +1199,7 @@ cciss_ioctl_pathinfo (struct path * pp,
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
-get_state (struct path * pp, int daemon)
|
|
|
|
+get_state (struct path * pp, int daemon, int oldstate)
|
|
|
|
{
|
|
|
|
struct checker * c = &pp->checker;
|
|
|
|
int state;
|
|
|
|
@@ -1171,8 +1238,9 @@ get_state (struct path * pp, int daemon)
|
|
|
|
(pp->bus != SYSFS_BUS_SCSI ||
|
|
|
|
sysfs_get_timeout(pp, &(c->timeout))))
|
|
|
|
c->timeout = DEF_TIMEOUT;
|
|
|
|
- state = checker_check(c);
|
|
|
|
- condlog(3, "%s: state = %s", pp->dev, checker_state_name(state));
|
|
|
|
+ state = checker_check(c, oldstate);
|
|
|
|
+ condlog(3, "%s: %s state = %s", pp->dev,
|
|
|
|
+ checker_name(c), checker_state_name(state));
|
|
|
|
if (state != PATH_UP && state != PATH_GHOST &&
|
|
|
|
strlen(checker_message(c)))
|
|
|
|
condlog(3, "%s: checker msg is \"%s\"",
|
|
|
|
@@ -1256,6 +1324,82 @@ free_dev:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Mangle string of length *len starting at start
|
|
|
|
+ * by removing character sequence "00" (hex for a 0 byte),
|
|
|
|
+ * starting at end, backwards.
|
|
|
|
+ * Changes the value of *len if characters were removed.
|
|
|
|
+ * Returns a pointer to the position where "end" was moved to.
|
|
|
|
+ */
|
|
|
|
+static char *
|
|
|
|
+skip_zeroes_backward(char* start, int *len, char *end)
|
|
|
|
+{
|
|
|
|
+ char *p = end;
|
|
|
|
+
|
|
|
|
+ while (p >= start + 2 && *(p - 1) == '0' && *(p - 2) == '0')
|
|
|
|
+ p -= 2;
|
|
|
|
+
|
|
|
|
+ if (p == end)
|
|
|
|
+ return p;
|
|
|
|
+
|
|
|
|
+ memmove(p, end, start + *len + 1 - end);
|
|
|
|
+ *len -= end - p;
|
|
|
|
+
|
|
|
|
+ return p;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Fix for NVME wwids looking like this:
|
|
|
|
+ * nvme.0000-3163653363666438366239656630386200-4c696e75780000000000000000000000000000000000000000000000000000000000000000000000-00000002
|
|
|
|
+ * which are encountered in some combinations of Linux NVME host and target.
|
|
|
|
+ * The '00' are hex-encoded 0-bytes which are forbidden in the serial (SN)
|
|
|
|
+ * and model (MN) fields. Discard them.
|
|
|
|
+ * If a WWID of the above type is found, sets pp->wwid and returns a value > 0.
|
|
|
|
+ * Otherwise, returns 0.
|
|
|
|
+ */
|
|
|
|
+static int
|
|
|
|
+fix_broken_nvme_wwid(struct path *pp, const char *value, int size)
|
|
|
|
+{
|
|
|
|
+ static const char _nvme[] = "nvme.";
|
|
|
|
+ int len, i;
|
|
|
|
+ char mangled[256];
|
|
|
|
+ char *p;
|
|
|
|
+
|
|
|
|
+ len = strlen(value);
|
|
|
|
+ if (len >= sizeof(mangled))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ /* Check that value starts with "nvme.%04x-" */
|
|
|
|
+ if (memcmp(value, _nvme, sizeof(_nvme) - 1) || value[9] != '-')
|
|
|
|
+ return 0;
|
|
|
|
+ for (i = 5; i < 9; i++)
|
|
|
|
+ if (!isxdigit(value[i]))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ memcpy(mangled, value, len + 1);
|
|
|
|
+
|
|
|
|
+ /* search end of "model" part and strip trailing '00' */
|
|
|
|
+ p = memrchr(mangled, '-', len);
|
|
|
|
+ if (p == NULL)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ p = skip_zeroes_backward(mangled, &len, p);
|
|
|
|
+
|
|
|
|
+ /* search end of "serial" part */
|
|
|
|
+ p = memrchr(mangled, '-', p - mangled);
|
|
|
|
+ if (p == NULL || memrchr(mangled, '-', p - mangled) != mangled + 9)
|
|
|
|
+ /* We expect exactly 3 '-' in the value */
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ p = skip_zeroes_backward(mangled, &len, p);
|
|
|
|
+ if (len >= size)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ memcpy(pp->wwid, mangled, len + 1);
|
|
|
|
+ condlog(2, "%s: over-long WWID shortened to %s", pp->dev, pp->wwid);
|
|
|
|
+ return len;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
int
|
|
|
|
get_uid (struct path * pp, struct udev_device *udev)
|
|
|
|
{
|
|
|
|
@@ -1287,14 +1431,10 @@ get_uid (struct path * pp, struct udev_d
|
|
|
|
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) {
|
|
|
|
+ size_t len = strlcpy(pp->wwid, value, WWID_SIZE);
|
|
|
|
+ if (len > WWID_SIZE &&
|
|
|
|
+ !fix_broken_nvme_wwid(pp, value, WWID_SIZE))
|
|
|
|
condlog(0, "%s: wwid overflow", pp->dev);
|
|
|
|
- } else {
|
|
|
|
- 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;
|
|
|
|
@@ -1381,7 +1521,8 @@ pathinfo (struct path *pp, vector hwtabl
|
|
|
|
|
|
|
|
if (mask & DI_CHECKER) {
|
|
|
|
if (path_state == PATH_UP) {
|
|
|
|
- pp->chkrstate = pp->state = get_state(pp, 0);
|
|
|
|
+ pp->chkrstate = pp->state = get_state(pp, 0,
|
|
|
|
+ path_state);
|
|
|
|
if (pp->state == PATH_UNCHECKED ||
|
|
|
|
pp->state == PATH_WILD)
|
|
|
|
goto blank;
|
|
|
|
Index: multipath-tools-130222/libmultipath/hwtable.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/hwtable.c
|
|
|
|
+++ multipath-tools-130222/libmultipath/hwtable.c
|
|
|
|
@@ -1185,7 +1185,15 @@ static struct hwentry default_hw[] = {
|
|
|
|
.checker_name = RBD,
|
|
|
|
.deferred_remove = DEFERRED_REMOVE_ON,
|
|
|
|
},
|
|
|
|
-
|
|
|
|
+ /*
|
|
|
|
+ * Generic NVMe devices
|
|
|
|
+ */
|
|
|
|
+ {
|
|
|
|
+ .vendor = "NVME",
|
|
|
|
+ .product = ".*",
|
|
|
|
+ .uid_attribute = "ID_WWN",
|
|
|
|
+ .checker_name = NONE,
|
|
|
|
+ },
|
|
|
|
/*
|
|
|
|
* EOL
|
|
|
|
*/
|
|
|
|
Index: multipath-tools-130222/libmultipath/structs.h
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/structs.h
|
|
|
|
+++ multipath-tools-130222/libmultipath/structs.h
|
|
|
|
@@ -54,6 +54,7 @@ enum sysfs_buses {
|
|
|
|
SYSFS_BUS_CCW,
|
|
|
|
SYSFS_BUS_CCISS,
|
|
|
|
SYSFS_BUS_RBD,
|
|
|
|
+ SYSFS_BUS_NVME,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum pathstates {
|
|
|
|
Index: multipath-tools-130222/libmultipath/checkers.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/checkers.c
|
|
|
|
+++ multipath-tools-130222/libmultipath/checkers.c
|
|
|
|
@@ -101,6 +101,8 @@ struct checker * add_checker (char * nam
|
|
|
|
if (!c)
|
|
|
|
return NULL;
|
|
|
|
snprintf(c->name, CHECKER_NAME_LEN, "%s", name);
|
|
|
|
+ if (!strncmp(c->name, NONE, 4))
|
|
|
|
+ goto done;
|
|
|
|
snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so",
|
|
|
|
conf->multipath_dir, name);
|
|
|
|
if (stat(libname,&stbuf) < 0) {
|
|
|
|
@@ -144,7 +146,7 @@ struct checker * add_checker (char * nam
|
|
|
|
condlog(0, "A dynamic linking error occurred: (%s)", errstr);
|
|
|
|
if (!c->repair)
|
|
|
|
goto out;
|
|
|
|
-
|
|
|
|
+done:
|
|
|
|
c->fd = 0;
|
|
|
|
c->sync = 1;
|
|
|
|
list_add(&c->node, &checkers);
|
|
|
|
@@ -194,14 +196,16 @@ int checker_init (struct checker * c, vo
|
|
|
|
if (!c)
|
|
|
|
return 1;
|
|
|
|
c->mpcontext = mpctxt_addr;
|
|
|
|
- return c->init(c);
|
|
|
|
+ if (c->init)
|
|
|
|
+ return c->init(c);
|
|
|
|
+ return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void checker_put (struct checker * dst)
|
|
|
|
{
|
|
|
|
struct checker * src;
|
|
|
|
|
|
|
|
- if (!dst)
|
|
|
|
+ if (!dst || !strlen(dst->name))
|
|
|
|
return;
|
|
|
|
src = checker_lookup(dst->name);
|
|
|
|
if (dst->free)
|
|
|
|
@@ -221,10 +225,11 @@ void checker_repair (struct checker * c)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- c->repair(c);
|
|
|
|
+ if (c->repair)
|
|
|
|
+ c->repair(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
-int checker_check (struct checker * c)
|
|
|
|
+int checker_check (struct checker * c, int path_state)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
@@ -236,6 +241,8 @@ int checker_check (struct checker * c)
|
|
|
|
MSG(c, "checker disabled");
|
|
|
|
return PATH_UNCHECKED;
|
|
|
|
}
|
|
|
|
+ if (!strncmp(c->name, NONE, 4))
|
|
|
|
+ return path_state;
|
|
|
|
if (c->fd <= 0) {
|
|
|
|
MSG(c, "no usable fd");
|
|
|
|
return PATH_WILD;
|
|
|
|
@@ -249,6 +256,8 @@ int checker_selected (struct checker * c
|
|
|
|
{
|
|
|
|
if (!c)
|
|
|
|
return 0;
|
|
|
|
+ if (!strncmp(c->name, NONE, 4))
|
|
|
|
+ return 1;
|
|
|
|
return (c->check) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Index: multipath-tools-130222/libmultipath/checkers.h
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/checkers.h
|
|
|
|
+++ multipath-tools-130222/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 NONE "none"
|
|
|
|
#define RBD "rbd"
|
|
|
|
|
|
|
|
#define DEFAULT_CHECKER DIRECTIO
|
|
|
|
@@ -129,7 +130,7 @@ void checker_set_fd (struct checker *, i
|
|
|
|
void checker_enable (struct checker *);
|
|
|
|
void checker_disable (struct checker *);
|
|
|
|
void checker_repair (struct checker *);
|
|
|
|
-int checker_check (struct checker *);
|
|
|
|
+int checker_check (struct checker *, int);
|
|
|
|
int checker_selected (struct checker *);
|
|
|
|
char * checker_name (struct checker *);
|
|
|
|
char * checker_message (struct checker *);
|
|
|
|
Index: multipath-tools-130222/libmultipath/discovery.h
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/discovery.h
|
|
|
|
+++ multipath-tools-130222/libmultipath/discovery.h
|
|
|
|
@@ -35,7 +35,7 @@ int path_discovery (vector pathvec, stru
|
|
|
|
|
|
|
|
int do_tur (char *);
|
|
|
|
int path_offline (struct path *);
|
|
|
|
-int get_state (struct path * pp, int daemon);
|
|
|
|
+int get_state (struct path * pp, int daemon, int state);
|
|
|
|
int pathinfo (struct path *, vector hwtable, int mask);
|
|
|
|
int store_pathinfo (vector pathvec, vector hwtable,
|
|
|
|
struct udev_device *udevice, int flag,
|
|
|
|
Index: multipath-tools-130222/libmultipath/uevent.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/uevent.c
|
|
|
|
+++ multipath-tools-130222/libmultipath/uevent.c
|
|
|
|
@@ -447,7 +447,7 @@ int uevent_listen(struct udev *udev)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
err = udev_monitor_filter_add_match_subsystem_devtype(monitor, "block",
|
|
|
|
- NULL);
|
|
|
|
+ "disk");
|
|
|
|
if (err)
|
|
|
|
condlog(2, "failed to create filter : %s", strerror(-err));
|
|
|
|
err = udev_monitor_enable_receiving(monitor);
|
|
|
|
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 none
|
|
|
|
+Do not check the device, fallback to use the values retrieved from sysfs
|
|
|
|
+.TP
|
|
|
|
.B rbd
|
|
|
|
Check if the path is in the Ceph blacklist.
|
|
|
|
.TP
|
|
|
|
Index: multipath-tools-130222/multipathd/main.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/multipathd/main.c
|
|
|
|
+++ multipath-tools-130222/multipathd/main.c
|
|
|
|
@@ -908,28 +908,6 @@ out:
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int
|
|
|
|
-uev_discard(char * devpath)
|
|
|
|
-{
|
|
|
|
- char *tmp;
|
|
|
|
- char a[11], b[11];
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * keep only block devices, discard partitions
|
|
|
|
- */
|
|
|
|
- tmp = strstr(devpath, "/block/");
|
|
|
|
- if (tmp == NULL){
|
|
|
|
- condlog(4, "no /block/ in '%s'", devpath);
|
|
|
|
- return 1;
|
|
|
|
- }
|
|
|
|
- if (sscanf(tmp, "/block/%10s", a) != 1 ||
|
|
|
|
- sscanf(tmp, "/block/%10[^/]/%10s", a, b) == 2) {
|
|
|
|
- condlog(4, "discard event on %s", devpath);
|
|
|
|
- return 1;
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
int
|
|
|
|
uev_trigger (struct uevent * uev, void * trigger_data)
|
|
|
|
{
|
|
|
|
@@ -938,9 +916,6 @@ uev_trigger (struct uevent * uev, void *
|
|
|
|
|
|
|
|
vecs = (struct vectors *)trigger_data;
|
|
|
|
|
|
|
|
- if (uev_discard(uev->devpath))
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
pthread_cleanup_push(cleanup_lock, &vecs->lock);
|
|
|
|
lock(vecs->lock);
|
|
|
|
pthread_testcancel();
|
|
|
|
@@ -1358,7 +1333,7 @@ check_path (struct vectors * vecs, struc
|
|
|
|
|
|
|
|
newstate = path_offline(pp);
|
|
|
|
if (newstate == PATH_UP)
|
|
|
|
- newstate = get_state(pp, 1);
|
|
|
|
+ newstate = get_state(pp, 1, newstate);
|
|
|
|
else
|
|
|
|
checker_clear_message(&pp->checker);
|
|
|
|
|