summaryrefslogtreecommitdiff
path: root/libmultipath
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2023-01-13 15:40:25 +0900
committerJinWang An <jinwang.an@samsung.com>2023-01-13 15:40:25 +0900
commitf53f46f41365730fb623201ccda13edc58cc2890 (patch)
tree9e8fd6bfb227a5c9874e6ee80e8de0196abffdc6 /libmultipath
parent1ff3a804f63b56d0878adf894370b36890e560ff (diff)
downloadmultipath-tools-f53f46f41365730fb623201ccda13edc58cc2890.tar.gz
multipath-tools-f53f46f41365730fb623201ccda13edc58cc2890.tar.bz2
multipath-tools-f53f46f41365730fb623201ccda13edc58cc2890.zip
Imported Upstream version 0.8.9upstream/0.8.9
Diffstat (limited to 'libmultipath')
-rw-r--r--libmultipath/Makefile21
-rw-r--r--libmultipath/alias.c3
-rw-r--r--libmultipath/checkers.c1
-rw-r--r--libmultipath/checkers.h2
-rw-r--r--libmultipath/checkers/directio.c3
-rw-r--r--libmultipath/checkers/tur.c1
-rw-r--r--libmultipath/configure.c86
-rw-r--r--libmultipath/configure.h1
-rw-r--r--libmultipath/devmapper.c56
-rw-r--r--libmultipath/devmapper.h3
-rw-r--r--libmultipath/dict.c56
-rw-r--r--libmultipath/discovery.c88
-rw-r--r--libmultipath/discovery.h1
-rw-r--r--libmultipath/dmparser.c16
-rw-r--r--libmultipath/foreign.h2
-rw-r--r--libmultipath/foreign/nvme.c2
-rw-r--r--libmultipath/hwtable.c2
-rw-r--r--libmultipath/libmultipath.version7
-rw-r--r--libmultipath/print.c91
-rw-r--r--libmultipath/prioritizers/Makefile2
-rw-r--r--libmultipath/prioritizers/alua_spc3.h2
-rw-r--r--libmultipath/prioritizers/path_latency.c2
-rw-r--r--libmultipath/propsel.c47
-rw-r--r--libmultipath/structs.c20
-rw-r--r--libmultipath/structs.h23
-rw-r--r--libmultipath/structs_vec.c13
-rw-r--r--libmultipath/structs_vec.h3
-rw-r--r--libmultipath/uevent.c3
-rw-r--r--libmultipath/util.h10
-rw-r--r--libmultipath/version.h4
30 files changed, 348 insertions, 223 deletions
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index d4af1a5..77e954a 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -21,30 +21,35 @@ ifdef SYSTEMD
endif
endif
-ifneq ($(call check_func,dm_task_no_flush,/usr/include/libdevmapper.h),0)
+ifneq ($(call check_func,dm_task_no_flush,$(DEVMAPPER_INCDIR)/libdevmapper.h),0)
CFLAGS += -DLIBDM_API_FLUSH -D_GNU_SOURCE
endif
-ifneq ($(call check_func,dm_task_get_errno,/usr/include/libdevmapper.h),0)
+ifneq ($(call check_func,dm_task_get_errno,$(DEVMAPPER_INCDIR)/libdevmapper.h),0)
CFLAGS += -DLIBDM_API_GET_ERRNO
endif
-ifneq ($(call check_func,dm_task_set_cookie,/usr/include/libdevmapper.h),0)
+ifneq ($(call check_func,dm_task_set_cookie,$(DEVMAPPER_INCDIR)/libdevmapper.h),0)
CFLAGS += -DLIBDM_API_COOKIE
endif
-ifneq ($(call check_func,udev_monitor_set_receive_buffer_size,/usr/include/libudev.h),0)
+ifneq ($(call check_func,udev_monitor_set_receive_buffer_size,$(LIBUDEV_INCDIR)/libudev.h),0)
CFLAGS += -DLIBUDEV_API_RECVBUF
endif
-ifneq ($(call check_func,dm_task_deferred_remove,/usr/include/libdevmapper.h),0)
+ifneq ($(call check_func,dm_task_deferred_remove,$(DEVMAPPER_INCDIR)/libdevmapper.h),0)
CFLAGS += -DLIBDM_API_DEFERRED
endif
-ifneq ($(call check_func,dm_hold_control_dev,/usr/include/libdevmapper.h),0)
+ifneq ($(call check_func,dm_hold_control_dev,$(DEVMAPPER_INCDIR)/libdevmapper.h),0)
CFLAGS += -DLIBDM_API_HOLD_CONTROL
endif
+ifneq ($(call check_var,ELS_DTAG_LNK_INTEGRITY,$(LINUX_HEADERS_INCDIR)/scsi/fc/fc_els.h),0)
+ CFLAGS += -DFPIN_EVENT_HANDLER
+endif
+
+
OBJS = parser.o vector.o devmapper.o callout.o \
hwtable.o blacklist.o util.o dmparser.o config.o \
structs.o discovery.o propsel.o dict.o \
@@ -61,7 +66,7 @@ nvme-lib.o: nvme-lib.c nvme-ioctl.c nvme-ioctl.h
$(CC) $(CFLAGS) -Wno-unused-function -c -o $@ $<
# there are lots of "unused parameters" in dict.c
-# because not all handler / snprint methods nees all parameters
+# because not all handler / snprint methods need all parameters
dict.o: dict.c
$(CC) $(CFLAGS) -Wno-unused-parameter -c -o $@ $<
@@ -110,7 +115,7 @@ uninstall:
$(RM) $(DESTDIR)$(syslibdir)/$(DEVLIB)
clean: dep_clean
- $(RM) core *.a *.o *.so *.so.* *.gz *.abi nvme-ioctl.c nvme-ioctl.h $(NV_VERSION_SCRIPT)
+ $(RM) core *.a *.o *.so *.so.* *.abi nvme-ioctl.c nvme-ioctl.h $(NV_VERSION_SCRIPT)
include $(wildcard $(OBJS:.o=.d))
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 87c33af..548a118 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -4,7 +4,6 @@
*/
#include <stdlib.h>
#include <errno.h>
-#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
@@ -19,8 +18,6 @@
#include "checkers.h"
#include "structs.h"
#include "config.h"
-#include "util.h"
-#include "errno.h"
#include "devmapper.h"
#include "strbuf.h"
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index ef346d7..00554d6 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -5,6 +5,7 @@
#include <sys/stat.h>
#include <urcu.h>
#include <urcu/uatomic.h>
+#include <assert.h>
#include "debug.h"
#include "checkers.h"
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index f4600ed..5d25a42 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -156,7 +156,7 @@ void checker_disable (struct checker *);
*
* Rationale:
* Path checkers that do I/O may hang forever. To avoid blocking, some
- * checkers therefore use asyncronous, detached threads for checking
+ * checkers therefore use asynchronous, detached threads for checking
* the paths. These threads may continue hanging if multipathd is stopped.
* In this case, we can't unload the checker DSO at exit. In order to
* avoid race conditions and crashes, the entry point of the thread
diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c
index f73cbe3..bc7b7be 100644
--- a/libmultipath/checkers/directio.c
+++ b/libmultipath/checkers/directio.c
@@ -12,7 +12,6 @@
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <errno.h>
-#include <unistd.h>
#include <libaio.h>
#include "checkers.h"
@@ -23,7 +22,7 @@
/* Note: This checker type relies on the fact that only one checker can be run
* at a time, since multiple checkers share the same aio_group, and must be
- * able to modify other checker's async_reqs. If multple checkers become able
+ * able to modify other checker's async_reqs. If multiple checkers become able
* to be run at the same time, this checker will need to add locking, and
* probably polling on event fds, to deal with that */
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
index a4b4a21..c93e462 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -23,7 +23,6 @@
#include "../libmultipath/sg_include.h"
#include "../libmultipath/util.h"
#include "../libmultipath/time-util.h"
-#include "../libmultipath/util.h"
#define TUR_CMD_LEN 6
#define HEAVY_CHECK_COUNT 10
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 6745976..eca11ba 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -450,12 +450,12 @@ get_udev_for_mpp(const struct multipath *mpp)
dev_t devnum;
struct udev_device *udd;
- if (!mpp || !mpp->dmi) {
+ if (!mpp || !has_dm_info(mpp)) {
condlog(1, "%s called with empty mpp", __func__);
return NULL;
}
- devnum = makedev(mpp->dmi->major, mpp->dmi->minor);
+ devnum = makedev(mpp->dmi.major, mpp->dmi.minor);
udd = udev_device_new_from_devnum(udev, 'b', devnum);
if (!udd) {
condlog(1, "failed to get udev device for %s", mpp->alias);
@@ -503,11 +503,8 @@ unref:
}
void
-trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
+trigger_path_udev_change(struct path *pp, bool is_mpath)
{
- struct pathgroup *pgp;
- struct path *pp;
- int i, j;
/*
* If a path changes from multipath to non-multipath, we must
* synthesize an artificial "add" event, otherwise the LVM2 rules
@@ -515,6 +512,45 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
* irritate ourselves with an "add", so use "change".
*/
const char *action = is_mpath ? "change" : "add";
+ const char *env;
+
+ if (!pp->udev)
+ return;
+ /*
+ * Paths that are already classified as multipath
+ * members don't need another uevent.
+ */
+ env = udev_device_get_property_value(
+ pp->udev, "DM_MULTIPATH_DEVICE_PATH");
+
+ if (is_mpath && env != NULL && !strcmp(env, "1")) {
+ /*
+ * If FIND_MULTIPATHS_WAIT_UNTIL is not "0",
+ * path is in "maybe" state and timer is running
+ * Send uevent now (see multipath.rules).
+ */
+ env = udev_device_get_property_value(
+ pp->udev, "FIND_MULTIPATHS_WAIT_UNTIL");
+ if (env == NULL || !strcmp(env, "0"))
+ return;
+ } else if (!is_mpath &&
+ (env == NULL || !strcmp(env, "0")))
+ return;
+
+ condlog(3, "triggering %s uevent for %s (is %smultipath member)",
+ action, pp->dev, is_mpath ? "" : "no ");
+ sysfs_attr_set_value(pp->udev, "uevent",
+ action, strlen(action));
+ trigger_partitions_udev_change(pp->udev, action,
+ strlen(action));
+}
+
+void
+trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
+{
+ struct pathgroup *pgp;
+ struct path *pp;
+ int i, j;
if (!mpp || !mpp->pg)
return;
@@ -522,39 +558,8 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
vector_foreach_slot (mpp->pg, pgp, i) {
if (!pgp->paths)
continue;
- vector_foreach_slot(pgp->paths, pp, j) {
- const char *env;
-
- if (!pp->udev)
- continue;
- /*
- * Paths that are already classified as multipath
- * members don't need another uevent.
- */
- env = udev_device_get_property_value(
- pp->udev, "DM_MULTIPATH_DEVICE_PATH");
-
- if (is_mpath && env != NULL && !strcmp(env, "1")) {
- /*
- * If FIND_MULTIPATHS_WAIT_UNTIL is not "0",
- * path is in "maybe" state and timer is running
- * Send uevent now (see multipath.rules).
- */
- env = udev_device_get_property_value(
- pp->udev, "FIND_MULTIPATHS_WAIT_UNTIL");
- if (env == NULL || !strcmp(env, "0"))
- continue;
- } else if (!is_mpath &&
- (env == NULL || !strcmp(env, "0")))
- continue;
-
- condlog(3, "triggering %s uevent for %s (is %smultipath member)",
- action, pp->dev, is_mpath ? "" : "no ");
- sysfs_attr_set_value(pp->udev, "uevent",
- action, strlen(action));
- trigger_partitions_udev_change(pp->udev, action,
- strlen(action));
- }
+ vector_foreach_slot(pgp->paths, pp, j)
+ trigger_path_udev_change(pp, is_mpath);
}
mpp->needs_paths_uevent = 0;
@@ -574,7 +579,8 @@ sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload)
return 0;
max_sectors_kb = mpp->max_sectors_kb;
if (is_reload) {
- if (!mpp->dmi && dm_get_info(mpp->alias, &mpp->dmi) != 0) {
+ if (!has_dm_info(mpp) &&
+ dm_get_info(mpp->alias, &mpp->dmi) != 0) {
condlog(1, "failed to get dm info for %s", mpp->alias);
return 1;
}
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index efe18b7..2bf73e6 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -56,6 +56,7 @@ int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int forc
int get_refwwid (enum mpath_cmds cmd, const char *dev, enum devtypes dev_type,
vector pathvec, char **wwid);
struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
+void trigger_path_udev_change(struct path *pp, bool is_mpath);
void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath);
void trigger_partitions_udev_change(struct udev_device *dev, const char *action,
int len);
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index c0eb335..2507f77 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -473,14 +473,11 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
dm_task_set_ro(dmt);
if (task == DM_DEVICE_CREATE) {
- prefixed_uuid = calloc(1, UUID_PREFIX_LEN +
- strlen(mpp->wwid) + 1);
- if (!prefixed_uuid) {
+ if (asprintf(&prefixed_uuid, UUID_PREFIX "%s", mpp->wwid) < 0) {
condlog(0, "cannot create prefixed uuid : %s",
strerror(errno));
goto addout;
}
- sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid);
if (!dm_task_set_uuid(dmt, prefixed_uuid))
goto freeout;
dm_task_skip_lockfs(dmt);
@@ -611,12 +608,21 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush)
return 0;
}
-static int
-do_get_info(const char *name, struct dm_info *info)
+bool
+has_dm_info(const struct multipath *mpp)
+{
+ return (mpp && mpp->dmi.exists != 0);
+}
+
+int
+dm_get_info(const char *name, struct dm_info *info)
{
int r = -1;
struct dm_task *dmt;
+ if (!name || !info)
+ return r;
+
if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
return r;
@@ -646,7 +652,7 @@ int dm_map_present(const char * str)
{
struct dm_info info;
- return (do_get_info(str, &info) == 0);
+ return (dm_get_info(str, &info) == 0);
}
int dm_get_map(const char *name, unsigned long long *size, char **outparams)
@@ -969,7 +975,7 @@ dm_dev_t (const char * mapname, char * dev_t, int len)
{
struct dm_info info;
- if (do_get_info(mapname, &info) != 0)
+ if (dm_get_info(mapname, &info) != 0)
return 1;
if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
@@ -1013,7 +1019,7 @@ dm_get_major_minor(const char *name, int *major, int *minor)
{
struct dm_info info;
- if (do_get_info(name, &info) != 0)
+ if (dm_get_info(name, &info) != 0)
return -1;
*major = info.major;
@@ -1367,7 +1373,7 @@ dm_geteventnr (const char *name)
{
struct dm_info info;
- if (do_get_info(name, &info) != 0)
+ if (dm_get_info(name, &info) != 0)
return -1;
return info.event_nr;
@@ -1378,7 +1384,7 @@ dm_is_suspended(const char *name)
{
struct dm_info info;
- if (do_get_info(name, &info) != 0)
+ if (dm_get_info(name, &info) != 0)
return -1;
return info.suspended;
@@ -1542,7 +1548,7 @@ dm_get_deferred_remove (const char * mapname)
{
struct dm_info info;
- if (do_get_info(mapname, &info) != 0)
+ if (dm_get_info(mapname, &info) != 0)
return -1;
return info.deferred_remove;
@@ -1583,32 +1589,6 @@ dm_cancel_deferred_remove (struct multipath *mpp __attribute__((unused)))
#endif
-static struct dm_info *
-alloc_dminfo (void)
-{
- return calloc(1, sizeof(struct dm_info));
-}
-
-int
-dm_get_info (const char * mapname, struct dm_info ** dmi)
-{
- if (!mapname)
- return 1;
-
- if (!*dmi)
- *dmi = alloc_dminfo();
-
- if (!*dmi)
- return 1;
-
- if (do_get_info(mapname, *dmi) != 0) {
- free(*dmi);
- *dmi = NULL;
- return 1;
- }
- return 0;
-}
-
struct rename_data {
const char *old;
char *new;
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 45a676d..703f3bf 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -70,7 +70,8 @@ char * dm_mapname(int major, int minor);
int dm_remove_partmaps (const char * mapname, int need_sync,
int deferred_remove);
int dm_get_uuid(const char *name, char *uuid, int uuid_len);
-int dm_get_info (const char * mapname, struct dm_info ** dmi);
+bool has_dm_info(const struct multipath *mpp);
+int dm_get_info (const char * mapname, struct dm_info *dmi);
int dm_rename (const char * old, char * new, char * delim, int skip_kpartx);
int dm_reassign(const char * mapname);
int dm_reassign_table(const char *name, char *old, char *new);
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 7ad9f6e..2af9764 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -512,6 +512,59 @@ snprint_def_find_multipaths(struct config *conf, struct strbuf *buff,
find_multipaths_optvals[conf->find_multipaths]);
}
+static const char * const marginal_pathgroups_optvals[] = {
+ [MARGINAL_PATHGROUP_OFF] = "off",
+ [MARGINAL_PATHGROUP_ON] = "on",
+#ifdef FPIN_EVENT_HANDLER
+ [MARGINAL_PATHGROUP_FPIN] = "fpin",
+#endif
+};
+
+static int
+def_marginal_pathgroups_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
+{
+ char *buff;
+ unsigned int i;
+
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+ for (i = MARGINAL_PATHGROUP_OFF;
+ i < ARRAY_SIZE(marginal_pathgroups_optvals); i++) {
+ if (marginal_pathgroups_optvals[i] != NULL &&
+ !strcmp(buff, marginal_pathgroups_optvals[i])) {
+ conf->marginal_pathgroups = i;
+ break;
+ }
+ }
+
+ if (i >= ARRAY_SIZE(marginal_pathgroups_optvals)) {
+ if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0)
+ conf->marginal_pathgroups = MARGINAL_PATHGROUP_OFF;
+ else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
+ conf->marginal_pathgroups = MARGINAL_PATHGROUP_ON;
+ /* This can only be true if FPIN_EVENT_HANDLER isn't defined,
+ * otherwise this check will have already happened above */
+ else if (strcmp(buff, "fpin") == 0)
+ condlog(1, "%s line %d, support for \"fpin\" is not compiled in for marginal_pathgroups", file, line_nr);
+ else
+ condlog(1, "%s line %d, invalid value for marginal_pathgroups: \"%s\"",
+ file, line_nr, buff);
+ }
+ free(buff);
+ return 0;
+}
+
+static int
+snprint_def_marginal_pathgroups(struct config *conf, struct strbuf *buff,
+ const void *data)
+{
+ return append_strbuf_quoted(buff,
+ marginal_pathgroups_optvals[conf->marginal_pathgroups]);
+}
+
+
declare_def_handler(selector, set_str)
declare_def_snprint_defstr(selector, print_str, DEFAULT_SELECTOR)
declare_hw_handler(selector, set_str)
@@ -1526,9 +1579,6 @@ declare_ovr_snprint(all_tg_pt, print_yes_no_undef)
declare_hw_handler(all_tg_pt, set_yes_no_undef)
declare_hw_snprint(all_tg_pt, print_yes_no_undef)
-declare_def_handler(marginal_pathgroups, set_yes_no)
-declare_def_snprint(marginal_pathgroups, print_yes_no)
-
declare_def_handler(recheck_wwid, set_yes_no_undef)
declare_def_snprint_defint(recheck_wwid, print_yes_no_undef, DEFAULT_RECHECK_WWID)
declare_ovr_handler(recheck_wwid, set_yes_no_undef)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 7d939ae..b969fba 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -475,60 +475,33 @@ sysfs_get_tgt_nodename(struct path *pp, char *node)
return 0;
}
-int sysfs_get_host_adapter_name(const struct path *pp, char *adapter_name)
-{
- int proto_id;
-
- if (!pp || !adapter_name)
- return 1;
-
- proto_id = pp->sg_id.proto_id;
-
- if (proto_id != SCSI_PROTOCOL_FCP &&
- proto_id != SCSI_PROTOCOL_SAS &&
- proto_id != SCSI_PROTOCOL_ISCSI &&
- proto_id != SCSI_PROTOCOL_SRP) {
- return 1;
- }
- /* iscsi doesn't have adapter info in sysfs
- * get ip_address for grouping paths
- */
- if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
- return sysfs_get_iscsi_ip_address(pp, adapter_name);
-
- /* fetch adapter pci name for other protocols
- */
- return sysfs_get_host_pci_name(pp, adapter_name);
-}
-
-int sysfs_get_host_pci_name(const struct path *pp, char *pci_name)
+static int sysfs_get_host_bus_id(const struct path *pp, char *bus_id)
{
struct udev_device *hostdev, *parent;
char host_name[HOST_NAME_LEN];
- const char *driver_name, *value;
+ const char *driver_name, *subsystem_name, *value;
- if (!pp || !pci_name)
+ if (!pp || !bus_id)
return 1;
- sprintf(host_name, "host%d", pp->sg_id.host_no);
+ snprintf(host_name, sizeof(host_name), "host%d", pp->sg_id.host_no);
hostdev = udev_device_new_from_subsystem_sysname(udev,
"scsi_host", host_name);
if (!hostdev)
return 1;
- parent = udev_device_get_parent(hostdev);
- while (parent) {
+ for (parent = udev_device_get_parent(hostdev);
+ parent;
+ parent = udev_device_get_parent(parent)) {
driver_name = udev_device_get_driver(parent);
- if (!driver_name) {
- parent = udev_device_get_parent(parent);
- continue;
- }
- if (!strcmp(driver_name, "pcieport"))
+ subsystem_name = udev_device_get_subsystem(parent);
+ if (driver_name && !strcmp(driver_name, "pcieport"))
+ break;
+ if (subsystem_name && !strcmp(subsystem_name, "ccw"))
break;
- parent = udev_device_get_parent(parent);
}
if (parent) {
- /* pci_device found
+ /* pci_device or ccw fcp device found
*/
value = udev_device_get_sysname(parent);
@@ -537,7 +510,7 @@ int sysfs_get_host_pci_name(const struct path *pp, char *pci_name)
return 1;
}
- strncpy(pci_name, value, SLOT_NAME_SIZE);
+ strlcpy(bus_id, value, SLOT_NAME_SIZE);
udev_device_unref(hostdev);
return 0;
}
@@ -545,6 +518,32 @@ int sysfs_get_host_pci_name(const struct path *pp, char *pci_name)
return 1;
}
+int sysfs_get_host_adapter_name(const struct path *pp, char *adapter_name)
+{
+ int proto_id;
+
+ if (!pp || !adapter_name)
+ return 1;
+
+ proto_id = pp->sg_id.proto_id;
+
+ if (proto_id != SCSI_PROTOCOL_FCP &&
+ proto_id != SCSI_PROTOCOL_SAS &&
+ proto_id != SCSI_PROTOCOL_ISCSI &&
+ proto_id != SCSI_PROTOCOL_SRP) {
+ return 1;
+ }
+ /* iscsi doesn't have adapter info in sysfs
+ * get ip_address for grouping paths
+ */
+ if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
+ return sysfs_get_iscsi_ip_address(pp, adapter_name);
+
+ /* fetch adapter bus-ID for other protocols
+ */
+ return sysfs_get_host_bus_id(pp, adapter_name);
+}
+
int sysfs_get_iscsi_ip_address(const struct path *pp, char *ip_address)
{
struct udev_device *hostdev;
@@ -844,6 +843,7 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
int i;
unsigned int dev_loss_tmo = mpp->dev_loss;
struct path *err_path = NULL;
+ STATIC_BITFIELD(bf, LAST_BUS_PROTOCOL_ID + 1);
if (mpp->no_path_retry > 0) {
uint64_t no_path_retry_tmo =
@@ -898,12 +898,13 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
sysfs_set_eh_deadline(mpp, pp);
}
- if (err_path) {
+ if (err_path && !is_bit_set_in_bitfield(bus_protocol_id(pp), bf)) {
STRBUF_ON_STACK(proto_buf);
snprint_path_protocol(&proto_buf, err_path);
condlog(2, "%s: setting dev_loss_tmo is unsupported for protocol %s",
mpp->alias, get_strbuf_str(&proto_buf));
+ set_bit_in_bitfield(bus_protocol_id(pp), bf);
}
return 0;
}
@@ -2345,7 +2346,10 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
* Avoid any IO on the device itself.
* simply use the path_offline() return as its state
*/
- pp->chkrstate = pp->state = path_state;
+ if (path_state != PATH_PENDING ||
+ pp->state == PATH_UNCHECKED ||
+ pp->state == PATH_WILD)
+ pp->chkrstate = pp->state = path_state;
return PATHINFO_OK;
}
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
index 095657b..466af34 100644
--- a/libmultipath/discovery.h
+++ b/libmultipath/discovery.h
@@ -44,7 +44,6 @@ int store_pathinfo (vector pathvec, struct config *conf,
struct path **pp_ptr);
int sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint);
int sysfs_get_timeout(const struct path *pp, unsigned int *timeout);
-int sysfs_get_host_pci_name(const struct path *pp, char *pci_name);
int sysfs_get_iscsi_ip_address(const struct path *pp, char *ip_address);
int sysfs_get_host_adapter_name(const struct path *pp,
char *adapter_name);
diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c
index 74c9215..50d13c0 100644
--- a/libmultipath/dmparser.c
+++ b/libmultipath/dmparser.c
@@ -102,7 +102,7 @@ err:
}
/*
- * Caution callers: If this function encounters yet unkown path devices, it
+ * Caution callers: If this function encounters yet unknown path devices, it
* adds them uninitialized to the mpp.
* Call update_pathvec_from_dm() after this function to make sure
* all data structures are in a sane state.
@@ -436,9 +436,19 @@ int disassemble_status(const char *params, struct multipath *mpp)
free(word);
/*
- * PG Status (discarded, would be '0' anyway)
+ * Path Selector Group Arguments
*/
- p += get_word(p, NULL);
+ p += get_word(p, &word);
+
+ if (!word)
+ return 1;
+
+ num_pg_args = atoi(word);
+ free(word);
+
+ /* Ignore ps group arguments */
+ for (j = 0; j < num_pg_args; j++)
+ p += get_word(p, NULL);
p += get_word(p, &word);
diff --git a/libmultipath/foreign.h b/libmultipath/foreign.h
index cf8f570..f547c14 100644
--- a/libmultipath/foreign.h
+++ b/libmultipath/foreign.h
@@ -42,7 +42,7 @@ struct foreign {
/**
* method: init(api, name)
* Initialize foreign library, and check API compatibility
- * return pointer to opaque internal data strucure if successful,
+ * return pointer to opaque internal data structure if successful,
* NULL otherwise.
*
* @param[in] api: API version
diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c
index 499b881..838e116 100644
--- a/libmultipath/foreign/nvme.c
+++ b/libmultipath/foreign/nvme.c
@@ -337,7 +337,7 @@ static int snprint_nvme_pg(const struct gen_pathgroup *gmp,
static int nvme_style(__attribute__((unused)) const struct gen_multipath* gm,
struct strbuf *buf, __attribute__((unused)) int verbosity)
{
- return append_strbuf_str(buf, "%%w [%%G]:%%d %%s");
+ return append_strbuf_str(buf, "%w [%G]:%d %s");
}
static const struct gen_multipath_ops nvme_map_ops = {
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index c65e5e1..bd15710 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -1039,7 +1039,7 @@ static struct hwentry default_hw[] = {
{
/* Linux-IO Target */
.vendor = "(LIO-ORG|SUSE)",
- .product = "RBD",
+ .product = ".",
.hwhandler = "1 alua",
.pgpolicy = GROUP_BY_PRIO,
.pgfailback = -FAILBACK_IMMEDIATE,
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 9c7ffa7..216f0ee 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -31,7 +31,7 @@
* The new version inherits the previous ones.
*/
-LIBMULTIPATH_13.0.0 {
+LIBMULTIPATH_14.0.0 {
global:
/* symbols referenced by multipath and multipathd */
add_foreign;
@@ -56,6 +56,7 @@ global:
check_foreign;
cleanup_charp;
cleanup_lock;
+ cleanup_mutex;
cleanup_ucharp;
close_fd;
coalesce_paths;
@@ -121,6 +122,7 @@ global:
get_used_hwes;
get_vpd_sgio;
group_by_prio;
+ has_dm_info;
init_checkers;
init_config;
init_foreign;
@@ -175,7 +177,7 @@ global:
select_reservation_key;
send_packet;
set_max_fds;
- __set_no_path_retry;
+ set_no_path_retry;
set_path_removed;
set_prkey;
setup_map;
@@ -209,6 +211,7 @@ global:
sysfs_is_multipathed;
timespeccmp;
timespecsub;
+ trigger_path_udev_change;
trigger_paths_udev_change;
truncate_strbuf;
udev;
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 221b515..bf88f30 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -8,7 +8,6 @@
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
-#include <string.h>
#include <errno.h>
#include <assert.h>
#include <libudev.h>
@@ -96,6 +95,7 @@
" \"host_wwpn\" : \"%R\",\n" \
" \"target_wwpn\" : \"%r\",\n" \
" \"host_adapter\" : \"%a\",\n" \
+ " \"lun_hex\" : \"%L\",\n" \
" \"marginal_st\" : \"%M\""
#define PROGRESS_LEN 10
@@ -171,8 +171,8 @@ snprint_name (struct strbuf *buff, const struct multipath * mpp)
static int
snprint_sysfs (struct strbuf *buff, const struct multipath * mpp)
{
- if (mpp->dmi)
- return print_strbuf(buff, "dm-%i", mpp->dmi->minor);
+ if (has_dm_info(mpp))
+ return print_strbuf(buff, "dm-%i", mpp->dmi.minor);
else
return append_strbuf_str(buff, "undef");
}
@@ -180,9 +180,9 @@ snprint_sysfs (struct strbuf *buff, const struct multipath * mpp)
static int
snprint_ro (struct strbuf *buff, const struct multipath * mpp)
{
- if (!mpp->dmi)
+ if (!has_dm_info(mpp))
return append_strbuf_str(buff, "undef");
- if (mpp->dmi->read_only)
+ if (mpp->dmi.read_only)
return append_strbuf_str(buff, "ro");
else
return append_strbuf_str(buff, "rw");
@@ -256,7 +256,9 @@ snprint_nb_paths (struct strbuf *buff, const struct multipath * mpp)
static int
snprint_dm_map_state (struct strbuf *buff, const struct multipath * mpp)
{
- if (mpp->dmi && mpp->dmi->suspended)
+ if (!has_dm_info(mpp))
+ return append_strbuf_str(buff, "undef");
+ else if (mpp->dmi.suspended)
return append_strbuf_str(buff, "suspend");
else
return append_strbuf_str(buff, "active");
@@ -451,6 +453,24 @@ snprint_hcil (struct strbuf *buff, const struct path * pp)
pp->sg_id.lun);
}
+
+static int
+snprint_path_lunhex (struct strbuf *buff, const struct path * pp)
+{
+ uint64_t lunhex = SCSI_INVALID_LUN, scsilun;
+
+ if (!pp || pp->sg_id.host_no < 0)
+ return print_strbuf(buff, "0x%016" PRIx64, lunhex);
+
+ scsilun = pp->sg_id.lun;
+ /* cf. Linux kernel function int_to_scsilun() */
+ lunhex = ((scsilun & 0x000000000000ffffULL) << 48) |
+ ((scsilun & 0x00000000ffff0000ULL) << 16) |
+ ((scsilun & 0x0000ffff00000000ULL) >> 16) |
+ ((scsilun & 0xffff000000000000ULL) >> 48);
+ return print_strbuf(buff, "0x%016" PRIx64, lunhex);
+}
+
static int
snprint_dev (struct strbuf *buff, const struct path * pp)
{
@@ -734,43 +754,27 @@ snprint_path_failures(struct strbuf *buff, const struct path * pp)
int
snprint_path_protocol(struct strbuf *buff, const struct path * pp)
{
- switch (pp->bus) {
- case SYSFS_BUS_SCSI:
- switch (pp->sg_id.proto_id) {
- case SCSI_PROTOCOL_FCP:
- return append_strbuf_str(buff, "scsi:fcp");
- case SCSI_PROTOCOL_SPI:
- return append_strbuf_str(buff, "scsi:spi");
- case SCSI_PROTOCOL_SSA:
- return append_strbuf_str(buff, "scsi:ssa");
- case SCSI_PROTOCOL_SBP:
- return append_strbuf_str(buff, "scsi:sbp");
- case SCSI_PROTOCOL_SRP:
- return append_strbuf_str(buff, "scsi:srp");
- case SCSI_PROTOCOL_ISCSI:
- return append_strbuf_str(buff, "scsi:iscsi");
- case SCSI_PROTOCOL_SAS:
- return append_strbuf_str(buff, "scsi:sas");
- case SCSI_PROTOCOL_ADT:
- return append_strbuf_str(buff, "scsi:adt");
- case SCSI_PROTOCOL_ATA:
- return append_strbuf_str(buff, "scsi:ata");
- case SCSI_PROTOCOL_USB:
- return append_strbuf_str(buff, "scsi:usb");
- case SCSI_PROTOCOL_UNSPEC:
- default:
- return append_strbuf_str(buff, "scsi:unspec");
- }
- case SYSFS_BUS_CCW:
- return append_strbuf_str(buff, "ccw");
- case SYSFS_BUS_CCISS:
- return append_strbuf_str(buff, "cciss");
- case SYSFS_BUS_NVME:
- return append_strbuf_str(buff, "nvme");
- case SYSFS_BUS_UNDEF:
- default:
- return append_strbuf_str(buff, "undef");
- }
+ static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
+ [SYSFS_BUS_UNDEF] = "undef",
+ [SYSFS_BUS_CCW] = "ccw",
+ [SYSFS_BUS_CCISS] = "cciss",
+ [SYSFS_BUS_NVME] = "nvme",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
+ };
+ const char *pn = protocol_name[bus_protocol_id(pp)];
+
+ assert(pn != NULL);
+ return append_strbuf_str(buff, pn);
}
static int
@@ -842,6 +846,7 @@ static const struct path_data pd[] = {
{'0', "failures", snprint_path_failures},
{'P', "protocol", snprint_path_protocol},
{'I', "init_st", snprint_initialized},
+ {'L', "LUN hex", snprint_path_lunhex},
};
static const struct pathgroup_data pgd[] = {
diff --git a/libmultipath/prioritizers/Makefile b/libmultipath/prioritizers/Makefile
index 8d34ae3..16c6397 100644
--- a/libmultipath/prioritizers/Makefile
+++ b/libmultipath/prioritizers/Makefile
@@ -23,7 +23,7 @@ LIBS = \
libpriopath_latency.so \
libpriosysfs.so
-ifneq ($(call check_file,/usr/include/linux/nvme_ioctl.h),0)
+ifneq ($(call check_file,$(LINUX_HEADERS_INCDIR)/linux/nvme_ioctl.h),0)
LIBS += libprioana.so
CFLAGS += -I../nvme
endif
diff --git a/libmultipath/prioritizers/alua_spc3.h b/libmultipath/prioritizers/alua_spc3.h
index f0a4bc4..08e992b 100644
--- a/libmultipath/prioritizers/alua_spc3.h
+++ b/libmultipath/prioritizers/alua_spc3.h
@@ -286,7 +286,7 @@ struct rtpg_tp_dscr {
struct rtpg_tpg_dscr {
unsigned char b0; /* x....... = pref(ered) port */
/* .xxx.... = reserved */
- /* ....xxxx = asymetric access state */
+ /* ....xxxx = asymmetric access state*/
unsigned char b1; /* xxx..... = reserved */
/* ...x.... = LBA dependent support */
/* ....x... = unavailable support */
diff --git a/libmultipath/prioritizers/path_latency.c b/libmultipath/prioritizers/path_latency.c
index 078226d..e155f6d 100644
--- a/libmultipath/prioritizers/path_latency.c
+++ b/libmultipath/prioritizers/path_latency.c
@@ -284,7 +284,7 @@ int getprio(struct path *pp, char *args, unsigned int timeout)
if (lg_avglatency > lg_maxavglatency) {
pp_pl_log(2,
- "%s: average latency (%lld us) is outside the thresold (%lld us)",
+ "%s: average latency (%lld us) is outside the threshold (%lld us)",
pp->dev, (long long)pow(base_num, lg_avglatency),
(long long)MAX_AVG_LATENCY);
return DEFAULT_PRIORITY;
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index a842fc3..1419ec6 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -83,6 +83,8 @@ static const char cmdline_origin[] =
"(setting: multipath command line [-p] flag)";
static const char autodetect_origin[] =
"(setting: storage device autodetected)";
+static const char fpin_marginal_path_origin[] =
+ "(setting: overridden by marginal_path_fpin)";
static const char marginal_path_origin[] =
"(setting: implied by marginal_path check)";
static const char delay_watch_origin[] =
@@ -1035,9 +1037,12 @@ int select_san_path_err_threshold(struct config *conf, struct multipath *mp)
const char *origin;
STRBUF_ON_STACK(buff);
- if (marginal_path_check_enabled(mp)) {
+ if (marginal_path_check_enabled(mp) || (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)) {
mp->san_path_err_threshold = NU_NO;
- origin = marginal_path_origin;
+ if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)
+ origin = fpin_marginal_path_origin;
+ else
+ origin = marginal_path_origin;
goto out;
}
mp_set_mpe(san_path_err_threshold);
@@ -1058,9 +1063,12 @@ int select_san_path_err_forget_rate(struct config *conf, struct multipath *mp)
const char *origin;
STRBUF_ON_STACK(buff);
- if (marginal_path_check_enabled(mp)) {
+ if (marginal_path_check_enabled(mp) || (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)) {
mp->san_path_err_forget_rate = NU_NO;
- origin = marginal_path_origin;
+ if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)
+ origin = fpin_marginal_path_origin;
+ else
+ origin = marginal_path_origin;
goto out;
}
mp_set_mpe(san_path_err_forget_rate);
@@ -1082,9 +1090,12 @@ int select_san_path_err_recovery_time(struct config *conf, struct multipath *mp)
const char *origin;
STRBUF_ON_STACK(buff);
- if (marginal_path_check_enabled(mp)) {
+ if (marginal_path_check_enabled(mp) || (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)) {
mp->san_path_err_recovery_time = NU_NO;
- origin = marginal_path_origin;
+ if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)
+ origin = fpin_marginal_path_origin;
+ else
+ origin = marginal_path_origin;
goto out;
}
mp_set_mpe(san_path_err_recovery_time);
@@ -1106,6 +1117,12 @@ int select_marginal_path_err_sample_time(struct config *conf, struct multipath *
const char *origin;
STRBUF_ON_STACK(buff);
+ if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) {
+ mp->marginal_path_err_sample_time = NU_NO;
+ origin = fpin_marginal_path_origin;
+ goto out;
+ }
+
mp_set_mpe(marginal_path_err_sample_time);
mp_set_ovr(marginal_path_err_sample_time);
mp_set_hwe(marginal_path_err_sample_time);
@@ -1129,6 +1146,12 @@ int select_marginal_path_err_rate_threshold(struct config *conf, struct multipat
const char *origin;
STRBUF_ON_STACK(buff);
+ if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) {
+ mp->marginal_path_err_rate_threshold = NU_NO;
+ origin = fpin_marginal_path_origin;
+ goto out;
+ }
+
mp_set_mpe(marginal_path_err_rate_threshold);
mp_set_ovr(marginal_path_err_rate_threshold);
mp_set_hwe(marginal_path_err_rate_threshold);
@@ -1146,6 +1169,12 @@ int select_marginal_path_err_recheck_gap_time(struct config *conf, struct multip
const char *origin;
STRBUF_ON_STACK(buff);
+ if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) {
+ mp->marginal_path_err_recheck_gap_time = NU_NO;
+ origin = fpin_marginal_path_origin;
+ goto out;
+ }
+
mp_set_mpe(marginal_path_err_recheck_gap_time);
mp_set_ovr(marginal_path_err_recheck_gap_time);
mp_set_hwe(marginal_path_err_recheck_gap_time);
@@ -1164,6 +1193,12 @@ int select_marginal_path_double_failed_time(struct config *conf, struct multipat
const char *origin;
STRBUF_ON_STACK(buff);
+ if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) {
+ mp->marginal_path_double_failed_time = NU_NO;
+ origin = fpin_marginal_path_origin;
+ goto out;
+ }
+
mp_set_mpe(marginal_path_double_failed_time);
mp_set_ovr(marginal_path_double_failed_time);
mp_set_hwe(marginal_path_double_failed_time);
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index d1b8aa3..4b62da5 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -18,6 +18,7 @@
#include "prio.h"
#include "prioritizers/alua_spc3.h"
#include "dm-generic.h"
+#include "devmapper.h"
struct adapter_group *
alloc_adaptergroup(void)
@@ -278,11 +279,6 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths)
mpp->alias = NULL;
}
- if (mpp->dmi) {
- free(mpp->dmi);
- mpp->dmi = NULL;
- }
-
if (!free_paths && mpp->pg) {
struct pathgroup *pgp;
struct path *pp;
@@ -407,10 +403,10 @@ find_mp_by_minor (const struct _vector *mpvec, unsigned int minor)
return NULL;
vector_foreach_slot (mpvec, mpp, i) {
- if (!mpp->dmi)
+ if (!has_dm_info(mpp))
continue;
- if (mpp->dmi->minor == minor)
+ if (mpp->dmi.minor == minor)
return mpp;
}
return NULL;
@@ -757,3 +753,13 @@ out:
return 0;
}
+
+unsigned int bus_protocol_id(const struct path *pp) {
+ if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_SCSI)
+ return SYSFS_BUS_UNDEF;
+ if (pp->bus != SYSFS_BUS_SCSI)
+ return pp->bus;
+ if ((int)pp->sg_id.proto_id < 0 || pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC)
+ return SYSFS_BUS_UNDEF;
+ return SYSFS_BUS_SCSI + pp->sg_id.proto_id;
+}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index c0f8929..d94f93a 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -4,6 +4,7 @@
#include <sys/types.h>
#include <inttypes.h>
#include <stdbool.h>
+#include <libdevmapper.h>
#include "prio.h"
#include "byteorder.h"
@@ -56,12 +57,13 @@ enum failback_mode {
FAILBACK_FOLLOWOVER
};
+/* SYSFS_BUS_SCSI should be last, see bus_protocol_id() */
enum sysfs_buses {
SYSFS_BUS_UNDEF,
- SYSFS_BUS_SCSI,
SYSFS_BUS_CCW,
SYSFS_BUS_CCISS,
SYSFS_BUS_NVME,
+ SYSFS_BUS_SCSI,
};
enum pathstates {
@@ -110,6 +112,12 @@ enum find_multipaths_states {
__FIND_MULTIPATHS_LAST,
};
+enum marginal_pathgroups_mode {
+ MARGINAL_PATHGROUP_OFF = YN_NO,
+ MARGINAL_PATHGROUP_ON = YN_YES,
+ MARGINAL_PATHGROUP_FPIN,
+};
+
enum flush_states {
FLUSH_UNDEF = YNU_UNDEF,
FLUSH_DISABLED = YNU_NO,
@@ -174,9 +182,17 @@ enum scsi_protocol {
SCSI_PROTOCOL_ADT = 7, /* Media Changers */
SCSI_PROTOCOL_ATA = 8,
SCSI_PROTOCOL_USB = 9, /* USB Attached SCSI (UAS), and others */
- SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */
+ SCSI_PROTOCOL_UNSPEC = 0xa, /* No specific protocol */
};
+/*
+ * Linear ordering of bus/protocol
+ * This assumes that SYSFS_BUS_SCSI is last in enum sysfs_buses
+ * SCSI is the only bus type for which we distinguish protocols.
+ */
+#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC)
+unsigned int bus_protocol_id(const struct path *pp);
+
#define SCSI_INVALID_LUN ~0ULL
enum no_undef_states {
@@ -386,7 +402,7 @@ struct multipath {
unsigned long long size;
vector paths;
vector pg;
- struct dm_info * dmi;
+ struct dm_info dmi;
/* configlet pointers */
char * alias;
@@ -418,6 +434,7 @@ struct multipath {
unsigned char prflag;
int all_tg_pt;
struct gen_multipath generic_mp;
+ bool fpin_must_reload;
};
static inline int marginal_path_check_enabled(const struct multipath *mpp)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index cb0ebae..6c23df8 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -588,23 +588,22 @@ static void leave_recovery_mode(struct multipath *mpp)
}
}
-void __set_no_path_retry(struct multipath *mpp, bool check_features)
+void set_no_path_retry(struct multipath *mpp)
{
bool is_queueing = false; /* assign a value to make gcc happy */
- check_features = check_features && mpp->features != NULL;
- if (check_features)
+ if (mpp->features)
is_queueing = strstr(mpp->features, "queue_if_no_path");
switch (mpp->no_path_retry) {
case NO_PATH_RETRY_UNDEF:
break;
case NO_PATH_RETRY_FAIL:
- if (!check_features || is_queueing)
+ if (!mpp->features || is_queueing)
dm_queue_if_no_path(mpp->alias, 0);
break;
case NO_PATH_RETRY_QUEUE:
- if (!check_features || !is_queueing)
+ if (!mpp->features || !is_queueing)
dm_queue_if_no_path(mpp->alias, 1);
break;
default:
@@ -613,11 +612,11 @@ void __set_no_path_retry(struct multipath *mpp, bool check_features)
* If in_recovery is set, leave_recovery_mode() takes
* care of dm_queue_if_no_path. Otherwise, do it here.
*/
- if ((!check_features || !is_queueing) &&
+ if ((!mpp->features || !is_queueing) &&
!mpp->in_recovery)
dm_queue_if_no_path(mpp->alias, 1);
leave_recovery_mode(mpp);
- } else
+ } else if (pathcount(mpp, PATH_PENDING) == 0)
enter_recovery_mode(mpp);
break;
}
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index d33fe98..3253f1b 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -11,8 +11,7 @@ struct vectors {
struct mutex_lock lock; /* defined in lock.h */
};
-void __set_no_path_retry(struct multipath *mpp, bool check_features);
-#define set_no_path_retry(mpp) __set_no_path_retry(mpp, true)
+void set_no_path_retry(struct multipath *mpp);
int adopt_paths (vector pathvec, struct multipath * mpp);
void orphan_path (struct path * pp, const char *reason);
diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
index 70ad217..29e2557 100644
--- a/libmultipath/uevent.c
+++ b/libmultipath/uevent.c
@@ -41,7 +41,6 @@
#include <sys/mman.h>
#include <sys/time.h>
#include <libudev.h>
-#include <errno.h>
#include "debug.h"
#include "list.h"
@@ -292,7 +291,7 @@ static bool
uevent_can_merge(struct uevent *earlier, struct uevent *later)
{
/* merge paths uevents
- * whose wwids exsit and are same
+ * whose wwids exist and are same
* and actions are same,
* and actions are addition or deletion
*/
diff --git a/libmultipath/util.h b/libmultipath/util.h
index 79d9f32..5a44018 100644
--- a/libmultipath/util.h
+++ b/libmultipath/util.h
@@ -82,6 +82,16 @@ struct bitfield {
bitfield_t bits[];
};
+#define STATIC_BITFIELD(name, length) \
+ static struct { \
+ unsigned int len; \
+ bitfield_t bits[((length) - 1) / bits_per_slot + 1]; \
+ } __static__ ## name = { \
+ .len = (length), \
+ .bits = { 0, }, \
+ }; \
+ struct bitfield *name = (struct bitfield *)& __static__ ## name
+
struct bitfield *alloc_bitfield(unsigned int maxbit);
void _log_bitfield_overflow(const char *f, unsigned int bit, unsigned int len);
diff --git a/libmultipath/version.h b/libmultipath/version.h
index e86a3cc..66c6cf3 100644
--- a/libmultipath/version.h
+++ b/libmultipath/version.h
@@ -20,8 +20,8 @@
#ifndef _VERSION_H
#define _VERSION_H
-#define VERSION_CODE 0x000808
-#define DATE_CODE 0x030c15
+#define VERSION_CODE 0x000809
+#define DATE_CODE 0x100216
#define PROG "multipath-tools"