summaryrefslogtreecommitdiff
path: root/libmultipath
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2022-01-14 13:50:17 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2022-01-14 13:50:17 +0900
commit7e244d28c5b51809837b8679e0b547e1432829b4 (patch)
tree81ea816dca9b2feec6e4e9b674d33660b3357063 /libmultipath
parent28bc88e5da7ffd00fcdac1d23c729d19e646f3fd (diff)
downloadmultipath-tools-7e244d28c5b51809837b8679e0b547e1432829b4.tar.gz
multipath-tools-7e244d28c5b51809837b8679e0b547e1432829b4.tar.bz2
multipath-tools-7e244d28c5b51809837b8679e0b547e1432829b4.zip
Imported Upstream version 0.7.3upstream/0.7.3
Diffstat (limited to 'libmultipath')
-rw-r--r--libmultipath/Makefile2
-rw-r--r--libmultipath/byteorder.h44
-rw-r--r--libmultipath/checkers.c26
-rw-r--r--libmultipath/checkers.h3
-rw-r--r--libmultipath/checkers/rbd.c16
-rw-r--r--libmultipath/config.c9
-rw-r--r--libmultipath/config.h10
-rw-r--r--libmultipath/configure.c58
-rw-r--r--libmultipath/configure.h1
-rw-r--r--libmultipath/defaults.h1
-rw-r--r--libmultipath/devmapper.c87
-rw-r--r--libmultipath/devmapper.h5
-rw-r--r--libmultipath/dict.c105
-rw-r--r--libmultipath/dict.h4
-rw-r--r--libmultipath/discovery.c62
-rw-r--r--libmultipath/discovery.h4
-rw-r--r--libmultipath/hwtable.c54
-rw-r--r--libmultipath/print.c2
-rw-r--r--libmultipath/prkey.c166
-rw-r--r--libmultipath/prkey.h19
-rw-r--r--libmultipath/propsel.c51
-rw-r--r--libmultipath/structs.c77
-rw-r--r--libmultipath/structs.h12
-rw-r--r--libmultipath/uevent.c17
-rw-r--r--libmultipath/util.c33
-rw-r--r--libmultipath/util.h4
-rw-r--r--libmultipath/version.h4
27 files changed, 647 insertions, 229 deletions
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index b3244fc..928bc25 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -42,7 +42,7 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
pgpolicies.o debug.o defaults.o uevent.o time-util.o \
switchgroup.o uxsock.o print.o alias.o log_pthread.o \
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
- lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o
+ lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o
all: $(LIBS)
diff --git a/libmultipath/byteorder.h b/libmultipath/byteorder.h
new file mode 100644
index 0000000..5c77146
--- /dev/null
+++ b/libmultipath/byteorder.h
@@ -0,0 +1,44 @@
+#ifndef BYTEORDER_H_INCLUDED
+#define BYTEORDER_H_INCLUDED
+
+#ifdef __linux__
+# include <endian.h>
+# include <byteswap.h>
+#else
+# error unsupported
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define le16_to_cpu(x) (x)
+# define be16_to_cpu(x) bswap_16(x)
+# define le32_to_cpu(x) (x)
+# define le64_to_cpu(x) (x)
+# define be32_to_cpu(x) bswap_32(x)
+# define be64_to_cpu(x) bswap_64(x)
+#elif BYTE_ORDER == BIG_ENDIAN
+# define le16_to_cpu(x) bswap_16(x)
+# define be16_to_cpu(x) (x)
+# define le32_to_cpu(x) bswap_32(x)
+# define le64_to_cpu(x) bswap_64(x)
+# define be32_to_cpu(x) (x)
+# define be64_to_cpu(x) (x)
+#else
+# error unsupported
+#endif
+
+#define cpu_to_le16(x) le16_to_cpu(x)
+#define cpu_to_be16(x) be16_to_cpu(x)
+#define cpu_to_le32(x) le32_to_cpu(x)
+#define cpu_to_be32(x) be32_to_cpu(x)
+#define cpu_to_le64(x) le64_to_cpu(x)
+#define cpu_to_be64(x) be64_to_cpu(x)
+
+struct be64 {
+ uint64_t _v;
+};
+
+#define get_be64(x) be64_to_cpu((x)._v)
+#define put_be64(x, y) do { (x)._v = cpu_to_be64(y); } while (0)
+
+
+#endif /* BYTEORDER_H_INCLUDED */
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index 05e024f..cd6d6a3 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -19,6 +19,7 @@ char *checker_state_names[] = {
"timeout",
"removed",
"delayed",
+ "none",
};
static LIST_HEAD(checkers);
@@ -102,6 +103,8 @@ struct checker * add_checker (char *multipath_dir, char * name)
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",
multipath_dir, name);
if (stat(libname,&stbuf) < 0) {
@@ -145,8 +148,8 @@ struct checker * add_checker (char *multipath_dir, char * name)
condlog(0, "A dynamic linking error occurred: (%s)", errstr);
if (!c->repair)
goto out;
-
- c->fd = 0;
+done:
+ c->fd = -1;
c->sync = 1;
list_add(&c->node, &checkers);
return c;
@@ -195,14 +198,16 @@ int checker_init (struct checker * c, void ** mpctxt_addr)
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 || !dst->check)
+ if (!dst || !strlen(dst->name))
return;
src = checker_lookup(dst->name);
if (dst->free)
@@ -221,11 +226,11 @@ void checker_repair (struct checker * c)
MSG(c, "checker disabled");
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;
@@ -237,7 +242,10 @@ int checker_check (struct checker * c)
MSG(c, "checker disabled");
return PATH_UNCHECKED;
}
- if (c->fd <= 0) {
+ if (!strncmp(c->name, NONE, 4))
+ return path_state;
+
+ if (c->fd < 0) {
MSG(c, "no usable fd");
return PATH_WILD;
}
@@ -250,6 +258,8 @@ int checker_selected (struct checker * c)
{
if (!c)
return 0;
+ if (!strncmp(c->name, NONE, 4))
+ return 1;
return (c->check) ? 1 : 0;
}
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index 1d225de..713399f 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -85,6 +85,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 ASYNC_TIMEOUT_SEC 30
@@ -135,7 +136,7 @@ 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_check (struct checker *, int);
int checker_selected (struct checker *);
char * checker_name (struct checker *);
char * checker_message (struct checker *);
diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c
index 9ea0572..2c18009 100644
--- a/libmultipath/checkers/rbd.c
+++ b/libmultipath/checkers/rbd.c
@@ -28,6 +28,7 @@
#include "../libmultipath/debug.h"
#include "../libmultipath/util.h"
#include "../libmultipath/time-util.h"
+#include "../libmultipath/util.h"
struct rbd_checker_context;
typedef int (thread_fn)(struct rbd_checker_context *ct, char *msg);
@@ -356,21 +357,6 @@ static int rbd_check(struct rbd_checker_context *ct, char *msg)
return PATH_UP;
}
-static 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)
{
diff --git a/libmultipath/config.c b/libmultipath/config.c
index b21a3aa..ea2359a 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -515,6 +515,9 @@ free_config (struct config * conf)
if (conf->wwids_file)
FREE(conf->wwids_file);
+ if (conf->prkeys_file)
+ FREE(conf->prkeys_file);
+
if (conf->prio_name)
FREE(conf->prio_name);
@@ -532,9 +535,6 @@ free_config (struct config * conf)
if (conf->config_dir)
FREE(conf->config_dir);
- if (conf->reservation_key)
- FREE(conf->reservation_key);
-
free_blacklist(conf->blist_devnode);
free_blacklist(conf->blist_wwid);
free_blacklist(conf->blist_property);
@@ -606,6 +606,7 @@ load_config (char * file)
get_sys_max_fds(&conf->max_fds);
conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
+ conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE);
conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
conf->attribute_flags = 0;
conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
@@ -731,7 +732,7 @@ load_config (char * file)
conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
if (!conf->multipath_dir || !conf->bindings_file ||
- !conf->wwids_file)
+ !conf->wwids_file || !conf->prkeys_file)
goto out;
return conf;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index ffc69b5..240730b 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -4,6 +4,8 @@
#include <sys/types.h>
#include <stdint.h>
#include <urcu.h>
+#include <inttypes.h>
+#include "byteorder.h"
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
@@ -34,6 +36,7 @@ enum mpath_cmds {
CMD_REMOVE_WWID,
CMD_RESET_WWIDS,
CMD_ADD_WWID,
+ CMD_USABLE_PATHS,
};
enum force_reload_types {
@@ -90,7 +93,8 @@ struct mpentry {
char * prio_name;
char * prio_args;
- unsigned char * reservation_key;
+ int prkey_source;
+ struct be64 reservation_key;
int pgpolicy;
int pgfailback;
int rr_weight;
@@ -177,13 +181,15 @@ struct config {
char * hwhandler;
char * bindings_file;
char * wwids_file;
+ char * prkeys_file;
char * prio_name;
char * prio_args;
char * checker_name;
char * alias_prefix;
char * partition_delim;
char * config_dir;
- unsigned char * reservation_key;
+ int prkey_source;
+ struct be64 reservation_key;
vector keywords;
vector mptable;
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 74b6f52..7a3db31 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1106,6 +1106,41 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
return 0;
}
+struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type)
+{
+ struct udev_device *ud = NULL;
+ const char *base;
+
+ if (dev == NULL || *dev == '\0')
+ return NULL;
+
+ switch (dev_type) {
+ case DEV_DEVNODE:
+ case DEV_DEVMAP:
+ /* This should be GNU basename, compiler will warn if not */
+ base = basename(dev);
+ if (*base == '\0')
+ break;
+ ud = udev_device_new_from_subsystem_sysname(udev, "block",
+ base);
+ break;
+ case DEV_DEVT:
+ ud = udev_device_new_from_devnum(udev, 'b', parse_devt(dev));
+ break;
+ case DEV_UEVENT:
+ ud = udev_device_new_from_environment(udev);
+ break;
+ default:
+ condlog(0, "Internal error: get_udev_device called with invalid type %d\n",
+ dev_type);
+ break;
+ }
+ if (ud == NULL)
+ condlog(2, "get_udev_device: failed to look up %s with type %d",
+ dev, dev_type);
+ return ud;
+}
+
/*
* returns:
* 0 - success
@@ -1141,12 +1176,12 @@ int get_refwwid(enum mpath_cmds cmd, char *dev, enum devtypes dev_type,
pp = find_path_by_dev(pathvec, buff);
if (!pp) {
- struct udev_device *udevice = udev_device_new_from_subsystem_sysname(udev, "block", buff);
+ struct udev_device *udevice =
+ get_udev_device(buff, dev_type);
- if (!udevice) {
- condlog(2, "%s: can't get udev device", buff);
+ if (!udevice)
return 1;
- }
+
conf = get_multipath_config();
ret = store_pathinfo(pathvec, conf, udevice,
flags, &pp);
@@ -1179,12 +1214,12 @@ int get_refwwid(enum mpath_cmds cmd, char *dev, enum devtypes dev_type,
}
pp = find_path_by_dev(pathvec, buff);
if (!pp) {
- struct udev_device *udevice = udev_device_new_from_devnum(udev, 'b', parse_devt(dev));
+ struct udev_device *udevice =
+ get_udev_device(dev, dev_type);
- if (!udevice) {
- condlog(2, "%s: can't get udev device", dev);
+ if (!udevice)
return 1;
- }
+
conf = get_multipath_config();
ret = store_pathinfo(pathvec, conf, udevice,
flags, &pp);
@@ -1209,12 +1244,11 @@ int get_refwwid(enum mpath_cmds cmd, char *dev, enum devtypes dev_type,
}
if (dev_type == DEV_UEVENT) {
- struct udev_device *udevice = udev_device_new_from_environment(udev);
+ struct udev_device *udevice = get_udev_device(dev, dev_type);
- if (!udevice) {
- condlog(2, "%s: can't get udev device", dev);
+ if (!udevice)
return 1;
- }
+
conf = get_multipath_config();
ret = store_pathinfo(pathvec, conf, udevice,
flags, &pp);
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index fd7f581..0ffc28e 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -36,3 +36,4 @@ int get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type,
vector pathvec, char **wwid);
int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon);
int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name);
+struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index db2b756..740ccf4 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -50,6 +50,7 @@
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
+#define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys"
#define DEFAULT_CONFIG_DIR "/etc/multipath/conf.d"
char * set_default (char * str);
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 3b41a48..fcac6bc 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -300,12 +300,14 @@ dm_device_remove (const char *name, int needsync, int deferred_remove) {
static int
dm_addmap (int task, const char *target, struct multipath *mpp,
- char * params, int ro, int skip_kpartx) {
+ char * params, int ro, uint16_t udev_flags) {
int r = 0;
struct dm_task *dmt;
char *prefixed_uuid = NULL;
uint32_t cookie = 0;
- uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);
+
+ /* Need to add this here to allow 0 to be passed in udev_flags */
+ udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (!(dmt = libmp_dm_task_create (task)))
return 0;
@@ -371,15 +373,27 @@ addout:
return r;
}
+static uint16_t build_udev_flags(const struct multipath *mpp, int reload)
+{
+ /* DM_UDEV_DISABLE_LIBRARY_FALLBACK is added in dm_addmap */
+ return (mpp->skip_kpartx == SKIP_KPARTX_ON ?
+ MPATH_UDEV_NO_KPARTX_FLAG : 0) |
+ (mpp->nr_active == 0 ?
+ MPATH_UDEV_NO_PATHS_FLAG : 0) |
+ (reload && !mpp->force_udev_reload ?
+ MPATH_UDEV_RELOAD_FLAG : 0);
+}
+
int dm_addmap_create (struct multipath *mpp, char * params)
{
int ro;
+ uint16_t udev_flags = build_udev_flags(mpp, 0);
for (ro = 0; ro <= 1; ro++) {
int err;
if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro,
- mpp->skip_kpartx))
+ udev_flags))
return 1;
/*
* DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
@@ -405,11 +419,7 @@ int dm_addmap_create (struct multipath *mpp, char * params)
int dm_addmap_reload(struct multipath *mpp, char *params, int flush)
{
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) |
- ((mpp->nr_active)? 0 : MPATH_UDEV_NO_PATHS_FLAG);
+ uint16_t udev_flags = build_udev_flags(mpp, 1);
/*
* DM_DEVICE_RELOAD cannot wait on a cookie, as
@@ -419,12 +429,12 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush)
*/
if (!mpp->force_readonly)
r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params,
- ADDMAP_RW, SKIP_KPARTX_OFF);
+ ADDMAP_RW, 0);
if (!r) {
if (!mpp->force_readonly && errno != EROFS)
return 0;
r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp,
- params, ADDMAP_RO, SKIP_KPARTX_OFF);
+ params, ADDMAP_RO, 0);
}
if (r)
r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush,
@@ -543,7 +553,7 @@ uuidout:
return r;
}
-int dm_get_uuid(char *name, char *uuid)
+int dm_get_uuid(const char *name, char *uuid)
{
if (dm_get_prefixed_uuid(name, uuid))
return 1;
@@ -994,6 +1004,31 @@ dm_disablegroup(char * mapname, int index)
return dm_groupmsg("disable", mapname, index);
}
+struct multipath *dm_get_multipath(const char *name)
+{
+ struct multipath *mpp = NULL;
+
+ mpp = alloc_multipath();
+ if (!mpp)
+ return NULL;
+
+ mpp->alias = STRDUP(name);
+
+ if (!mpp->alias)
+ goto out;
+
+ if (dm_get_map(name, &mpp->size, NULL))
+ goto out;
+
+ dm_get_uuid(name, mpp->wwid);
+ dm_get_info(name, &mpp->dmi);
+
+ return mpp;
+out:
+ free_multipath(mpp, KEEP_PATHS);
+ return NULL;
+}
+
int
dm_get_maps (vector mp)
{
@@ -1026,24 +1061,12 @@ dm_get_maps (vector mp)
if (!dm_is_mpath(names->name))
goto next;
- mpp = alloc_multipath();
-
+ mpp = dm_get_multipath(names->name);
if (!mpp)
goto out;
- mpp->alias = STRDUP(names->name);
-
- if (!mpp->alias)
- goto out1;
-
- if (dm_get_map(names->name, &mpp->size, NULL))
- goto out1;
-
- dm_get_uuid(names->name, mpp->wwid);
- dm_get_info(names->name, &mpp->dmi);
-
if (!vector_alloc_slot(mp))
- goto out1;
+ goto out;
vector_set_slot(mp, mpp);
mpp = NULL;
@@ -1054,8 +1077,6 @@ next:
r = 0;
goto out;
-out1:
- free_multipath(mpp, KEEP_PATHS);
out:
dm_task_destroy (dmt);
return r;
@@ -1298,7 +1319,7 @@ alloc_dminfo (void)
}
int
-dm_get_info (char * mapname, struct dm_info ** dmi)
+dm_get_info (const char * mapname, struct dm_info ** dmi)
{
if (!mapname)
return 1;
@@ -1351,10 +1372,12 @@ dm_rename_partmaps (const char * old, char * new, char *delim)
if (delim)
rd.delim = delim;
- if (isdigit(new[strlen(new)-1]))
- rd.delim = "p";
- else
- rd.delim = "";
+ else {
+ if (isdigit(new[strlen(new)-1]))
+ rd.delim = "p";
+ else
+ rd.delim = "";
+ }
return do_foreach_partmaps(old, rename_partmap, &rd);
}
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 99a554b..62e14d1 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -59,12 +59,13 @@ int dm_get_major_minor (const char *name, int *major, int *minor);
char * dm_mapname(int major, int minor);
int dm_remove_partmaps (const char * mapname, int need_sync,
int deferred_remove);
-int dm_get_uuid(char *name, char *uuid);
-int dm_get_info (char * mapname, struct dm_info ** dmi);
+int dm_get_uuid(const char *name, char *uuid);
+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);
int dm_setgeometry(struct multipath *mpp);
+struct multipath *dm_get_multipath(const char *name);
#define VERSION_GE(v, minv) ( \
(v[0] > minv[0]) || \
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 9dc1090..36cccc9 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -19,6 +19,7 @@
#include "blacklist.h"
#include "defaults.h"
#include "prio.h"
+#include "util.h"
#include <errno.h>
#include <inttypes.h>
#include "mpath_cmd.h"
@@ -367,6 +368,9 @@ declare_def_snprint(bindings_file, print_str)
declare_def_handler(wwids_file, set_str)
declare_def_snprint(wwids_file, print_str)
+declare_def_handler(prkeys_file, set_str)
+declare_def_snprint(prkeys_file, print_str)
+
declare_def_handler(retain_hwhandler, set_yes_no_undef)
declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef, YNU_NO)
declare_ovr_handler(retain_hwhandler, set_yes_no_undef)
@@ -959,77 +963,75 @@ snprint_def_log_checker_err (struct config *conf, char * buff, int len, void * d
}
static int
-set_reservation_key(vector strvec, void *ptr)
+set_reservation_key(vector strvec, struct be64 *be64_ptr, int *source_ptr)
{
- unsigned char **uchar_ptr = (unsigned char **)ptr;
char *buff;
- char *tbuff;
- int j, k;
- int len;
uint64_t prkey;
buff = set_value(strvec);
if (!buff)
return 1;
- tbuff = buff;
-
- if (!memcmp("0x",buff, 2))
- buff = buff + 2;
-
- len = strlen(buff);
-
- k = strspn(buff, "0123456789aAbBcCdDeEfF");
-
- if (len != k) {
- FREE(tbuff);
- return 1;
+ if (strcmp(buff, "file") == 0) {
+ *source_ptr = PRKEY_SOURCE_FILE;
+ put_be64(*be64_ptr, 0);
+ FREE(buff);
+ return 0;
}
- if (1 != sscanf (buff, "%" SCNx64 "", &prkey))
- {
- FREE(tbuff);
+ if (parse_prkey(buff, &prkey) != 0) {
+ FREE(buff);
return 1;
}
-
- if (!*uchar_ptr)
- *uchar_ptr = (unsigned char *) malloc(8);
-
- memset(*uchar_ptr, 0, 8);
-
- for (j = 7; j >= 0; --j) {
- (*uchar_ptr)[j] = (prkey & 0xff);
- prkey >>= 8;
- }
-
- FREE(tbuff);
+ *source_ptr = PRKEY_SOURCE_CONF;
+ put_be64(*be64_ptr, prkey);
+ FREE(buff);
return 0;
}
int
-print_reservation_key(char * buff, int len, void * ptr)
+print_reservation_key(char * buff, int len, struct be64 key, int source)
{
- unsigned char **uchar_ptr = (unsigned char **)ptr;
- int i;
- unsigned char *keyp;
- uint64_t prkey = 0;
-
- if (!*uchar_ptr)
+ if (source == PRKEY_SOURCE_NONE)
return 0;
- keyp = (unsigned char *)(*uchar_ptr);
- for (i = 0; i < 8; i++) {
- if (i > 0)
- prkey <<= 8;
- prkey |= *keyp;
- keyp++;
- }
- return snprintf(buff, len, "0x%" PRIx64, prkey);
+ if (source == PRKEY_SOURCE_FILE)
+ return snprintf(buff, len, "file");
+ return snprintf(buff, len, "0x%" PRIx64, get_be64(key));
+}
+
+static int
+def_reservation_key_handler(struct config *conf, vector strvec)
+{
+ return set_reservation_key(strvec, &conf->reservation_key,
+ &conf->prkey_source);
+}
+
+static int
+snprint_def_reservation_key (struct config *conf, char * buff, int len,
+ void * data)
+{
+ return print_reservation_key(buff, len, conf->reservation_key,
+ conf->prkey_source);
+}
+
+static int
+mp_reservation_key_handler(struct config *conf, vector strvec)
+{
+ struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable);
+ if (!mpe)
+ return 1;
+ return set_reservation_key(strvec, &mpe->reservation_key,
+ &mpe->prkey_source);
}
-declare_def_handler(reservation_key, set_reservation_key)
-declare_def_snprint(reservation_key, print_reservation_key)
-declare_mp_handler(reservation_key, set_reservation_key)
-declare_mp_snprint(reservation_key, print_reservation_key)
+static int
+snprint_mp_reservation_key (struct config *conf, char * buff, int len,
+ void * data)
+{
+ struct mpentry * mpe = (struct mpentry *)data;
+ return print_reservation_key(buff, len, mpe->reservation_key,
+ mpe->prkey_source);
+}
static int
set_off_int_undef(vector strvec, void *ptr)
@@ -1428,6 +1430,7 @@ init_keywords(vector keywords)
install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file);
install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file);
+ install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file);
install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key);
install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler);
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
index 2d6097d..0442227 100644
--- a/libmultipath/dict.h
+++ b/libmultipath/dict.h
@@ -5,6 +5,8 @@
#include "vector.h"
#endif
+#include "byteorder.h"
+
void init_keywords(vector keywords);
int get_sys_max_fds(int *);
int print_rr_weight (char * buff, int len, void *ptr);
@@ -13,6 +15,6 @@ int print_pgpolicy(char * buff, int len, void *ptr);
int print_no_path_retry(char * buff, int len, void *ptr);
int print_fast_io_fail(char * buff, int len, void *ptr);
int print_dev_loss(char * buff, int len, void *ptr);
-int print_reservation_key(char * buff, int len, void * ptr);
+int print_reservation_key(char * buff, int len, struct be64 key, int source);
int print_off_int_undef(char * buff, int len, void *ptr);
#endif /* _DICT_H */
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 3a912d7..efac824 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1194,28 +1194,37 @@ scsi_sysfs_pathinfo (struct path * pp, vector hwtable)
static int
nvme_sysfs_pathinfo (struct path * pp, vector hwtable)
{
- struct udev_device *parent, *nvme = NULL;
+ struct udev_device *parent;
+ const char *attr_path = NULL;
- parent = pp->udev;
- while (parent) {
- const char *subsys = udev_device_get_subsystem(parent);
+ attr_path = udev_device_get_sysname(pp->udev);
+ if (!attr_path)
+ return 1;
- if (subsys && !strncmp(subsys, "nvme", 4)) {
- nvme = parent;
- break;
- }
- parent = udev_device_get_parent(parent);
- }
- if (!nvme)
+ 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(nvme, "model"));
- snprintf(pp->serial, SERIAL_SIZE, "%s", udev_device_get_sysattr_value(nvme, "serial"));
- snprintf(pp->rev, SCSI_REV_SIZE, "%s", udev_device_get_sysattr_value(nvme, "firmware_rev"));
+ 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);
- condlog(3, "%s: vendor:%s product:%s serial:%s rev:%s", pp->dev,
- pp->vendor_id, pp->product_id, pp->serial, pp->rev);
pp->hwe = find_hwe(hwtable, pp->vendor_id, pp->product_id, NULL);
return 0;
@@ -1440,8 +1449,7 @@ path_offline (struct path * pp)
}
pp->offline = 0;
if (!strncmp(buff, "new", 3) ||
- !strncmp(buff, "reconnecting", 12) ||
- !strncmp(buff, "resetting", 9))
+ !strncmp(buff, "deleting", 8))
return PATH_PENDING;
else if (!strncmp(buff, "live", 4))
return PATH_UP;
@@ -1542,7 +1550,7 @@ cciss_ioctl_pathinfo (struct path * pp, int mask)
}
int
-get_state (struct path * pp, struct config *conf, int daemon)
+get_state (struct path * pp, struct config *conf, int daemon, int oldstate)
{
struct checker * c = &pp->checker;
int state;
@@ -1580,8 +1588,9 @@ get_state (struct path * pp, struct config *conf, int daemon)
if (!conf->checker_timeout &&
sysfs_get_timeout(pp, &(c->timeout)) <= 0)
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\"",
@@ -1926,6 +1935,14 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
path_state = path_offline(pp);
if (path_state == PATH_REMOVED)
goto blank;
+ else if (mask & DI_NOIO) {
+ /*
+ * Avoid any IO on the device itself.
+ * Behave like DI_CHECKER in the "path unavailable" case.
+ */
+ pp->chkrstate = pp->state = path_state;
+ return PATHINFO_OK;
+ }
/*
* fetch info not available through sysfs
@@ -1952,7 +1969,8 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
if (mask & DI_CHECKER) {
if (path_state == PATH_UP) {
- pp->chkrstate = pp->state = get_state(pp, conf, 0);
+ pp->chkrstate = pp->state = get_state(pp, conf, 0,
+ path_state);
if (pp->state == PATH_UNCHECKED ||
pp->state == PATH_WILD)
goto blank;
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
index 51c23d6..b151cc7 100644
--- a/libmultipath/discovery.h
+++ b/libmultipath/discovery.h
@@ -34,7 +34,7 @@ int path_discovery (vector pathvec, int flag);
int do_tur (char *);
int path_offline (struct path *);
-int get_state (struct path * pp, struct config * conf, int daemon);
+int get_state (struct path * pp, struct config * conf, int daemon, int state);
int get_vpd_sgio (int fd, int pg, char * str, int maxlen);
int pathinfo (struct path * pp, struct config * conf, int mask);
int alloc_path_with_pathinfo (struct config *conf, struct udev_device *udevice,
@@ -62,6 +62,7 @@ enum discovery_mode {
__DI_PRIO,
__DI_WWID,
__DI_BLACKLIST,
+ __DI_NOIO,
};
#define DI_SYSFS (1 << __DI_SYSFS)
@@ -70,6 +71,7 @@ enum discovery_mode {
#define DI_PRIO (1 << __DI_PRIO)
#define DI_WWID (1 << __DI_WWID)
#define DI_BLACKLIST (1 << __DI_BLACKLIST)
+#define DI_NOIO (1 << __DI_NOIO) /* Avoid IO on the device */
#define DI_ALL (DI_SYSFS | DI_SERIAL | DI_CHECKER | DI_PRIO | \
DI_WWID)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 9e14ec1..b018ddf 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -796,9 +796,9 @@ static struct hwentry default_hw[] = {
.no_path_retry = 30,
},
{
- /* 3510 / 6020 and 6120 */
+ /* (Dot Hill) 3310, 3320, 3510 and 3511 */
.vendor = "SUN",
- .product = "(StorEdge 3510|T4)",
+ .product = "StorEdge 3",
.pgpolicy = MULTIBUS,
},
{
@@ -964,13 +964,24 @@ static struct hwentry default_hw[] = {
},
/*
* Infinidat
+ *
+ * Maintainer: Arnon Yaari
+ * Mail: arnony@infinidat.com
*/
{
.vendor = "NFINIDAT",
.product = "InfiniBox",
.pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
+ .pgfailback = 30,
.prio_name = PRIO_ALUA,
+ .selector = "round-robin 0",
+ .rr_weight = RR_WEIGHT_PRIO,
+ .no_path_retry = NO_PATH_RETRY_FAIL,
+ .minio = 1,
+ .minio_rq = 1,
+ .flush_on_last_del = FLUSH_ENABLED,
+ .fast_io_fail = 15,
+ .dev_loss = 15,
},
/*
* Nimble Storage
@@ -1045,6 +1056,13 @@ static struct hwentry default_hw[] = {
.pgpolicy = MULTIBUS,
.no_path_retry = 12,
},
+ {
+ /* iglu blaze family */
+ .vendor = "(XIOTECH|XIOtech)",
+ .product = "IGLU DISK",
+ .pgpolicy = MULTIBUS,
+ .no_path_retry = 30,
+ },
/*
* Violin Memory
*/
@@ -1113,10 +1131,38 @@ static struct hwentry default_hw[] = {
.vendor = "NVME",
.product = ".*",
.uid_attribute = "ID_WWN",
- .checker_name = DIRECTIO,
+ .checker_name = NONE,
.retain_hwhandler = RETAIN_HWHANDLER_OFF,
},
/*
+ * Dot Hill Systems - Seagate Technology
+ */
+ {
+ /* SANnet family */
+ .vendor = "DotHill",
+ .product = "SANnet",
+ .pgpolicy = MULTIBUS,
+ .no_path_retry = 30,
+ },
+ {
+ /* R/Evolution family */
+ .vendor = "DotHill",
+ .product = "R/Evo",
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .prio_name = PRIO_ALUA,
+ .no_path_retry = 30,
+ },
+ {
+ /* AssuredSAN family */
+ .vendor = "DotHill",
+ .product = "^DH",
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .prio_name = PRIO_ALUA,
+ .no_path_retry = 30,
+ },
+ /*
* EOL
*/
{
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 95dff90..65a9824 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -1677,7 +1677,7 @@ int snprint_status(char *buff, int len, struct vectors *vecs)
int monitored_count = 0;
vector_foreach_slot(vecs->pathvec, pp, i)
- if (pp->fd != -1)
+ if (pp->fd >= 0)
monitored_count++;
fwd += snprintf(buff + fwd, len - fwd, "\npaths: %d\nbusy: %s\n",
monitored_count, is_uevent_busy()? "True" : "False");
diff --git a/libmultipath/prkey.c b/libmultipath/prkey.c
new file mode 100644
index 0000000..89b90ed
--- /dev/null
+++ b/libmultipath/prkey.c
@@ -0,0 +1,166 @@
+#include "structs.h"
+#include "file.h"
+#include "debug.h"
+#include "config.h"
+#include "util.h"
+#include "propsel.h"
+#include "prkey.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#define PRKEY_READ 0
+#define PRKEY_WRITE 1
+
+static int do_prkey(int fd, char *wwid, char *keystr, int cmd)
+{
+ char buf[4097];
+ char *ptr;
+ off_t start = 0;
+ int bytes;
+
+ while (1) {
+ if (lseek(fd, start, SEEK_SET) < 0) {
+ condlog(0, "prkey file read lseek failed : %s",
+ strerror(errno));
+ return 1;
+ }
+ bytes = read(fd, buf, 4096);
+ if (bytes < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ condlog(0, "failed to read from prkey file : %s",
+ strerror(errno));
+ return 1;
+ }
+ if (!bytes) {
+ ptr = NULL;
+ break;
+ }
+ buf[bytes] = '\0';
+ ptr = strstr(buf, wwid);
+ while (ptr) {
+ if (ptr == buf || *(ptr - 1) != ' ' ||
+ *(ptr + strlen(wwid)) != '\n')
+ ptr = strstr(ptr + strlen(wwid), wwid);
+ else
+ break;
+ }
+ if (ptr) {
+ condlog(3, "found prkey for '%s'", wwid);
+ ptr[strlen(wwid)] = '\0';
+ if (ptr - PRKEY_SIZE < buf ||
+ (ptr - PRKEY_SIZE != buf &&
+ *(ptr - PRKEY_SIZE - 1) != '\n')) {
+ condlog(0, "malformed prkey file line for wwid: '%s'", ptr);
+ return 1;
+ }
+ ptr = ptr - PRKEY_SIZE;
+ break;
+ }
+ ptr = strrchr(buf, '\n');
+ if (ptr == NULL) {
+ condlog(4, "couldn't file newline, assuming end of file");
+ break;
+ }
+ start = start + (ptr - buf) + 1;
+ }
+ if (cmd == PRKEY_READ) {
+ if (!ptr || *ptr == '#')
+ return 1;
+ memcpy(keystr, ptr, PRKEY_SIZE - 1);
+ keystr[PRKEY_SIZE - 1] = '\0';
+ return 0;
+ }
+ if (!ptr && !keystr)
+ return 0;
+ if (ptr) {
+ if (lseek(fd, start + (ptr - buf), SEEK_SET) < 0) {
+ condlog(0, "prkey write lseek failed : %s",
+ strerror(errno));
+ return 1;
+ }
+ }
+ if (!keystr) {
+ if (safe_write(fd, "#", 1) < 0) {
+ condlog(0, "failed to write to prkey file : %s",
+ strerror(errno));
+ return 1;
+ }
+ return 0;
+ }
+ if (!ptr) {
+ if (lseek(fd, 0, SEEK_END) < 0) {
+ condlog(0, "prkey write lseek failed : %s",
+ strerror(errno));
+ return 1;
+ }
+ }
+ bytes = sprintf(buf, "%s %s\n", keystr, wwid);
+ if (safe_write(fd, buf, bytes) < 0) {
+ condlog(0, "failed to write to prkey file: %s",
+ strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
+int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey)
+{
+ int fd;
+ int unused;
+ int ret = 1;
+ char keystr[PRKEY_SIZE];
+
+ if (!strlen(mpp->wwid))
+ goto out;
+
+ fd = open_file(conf->prkeys_file, &unused, PRKEYS_FILE_HEADER);
+ if (fd < 0)
+ goto out;
+ ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ);
+ if (ret)
+ goto out_file;
+ ret = !!parse_prkey(keystr, prkey);
+out_file:
+ close(fd);
+out:
+ return ret;
+}
+
+int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey)
+{
+ int fd;
+ int can_write = 1;
+ int ret = 1;
+ char keystr[PRKEY_SIZE];
+
+ if (!strlen(mpp->wwid))
+ goto out;
+
+ fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER);
+ if (fd < 0)
+ goto out;
+ if (!can_write) {
+ condlog(0, "cannot set prkey, prkeys file is read-only");
+ goto out_file;
+ }
+ if (prkey) {
+ snprintf(keystr, PRKEY_SIZE, "0x%016" PRIx64, prkey);
+ keystr[PRKEY_SIZE - 1] = '\0';
+ ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_WRITE);
+ }
+ else
+ ret = do_prkey(fd, mpp->wwid, NULL, PRKEY_WRITE);
+ if (ret == 0)
+ select_reservation_key(conf, mpp);
+ if (get_be64(mpp->reservation_key) != prkey)
+ ret = 1;
+out_file:
+ close(fd);
+out:
+ return ret;
+}
diff --git a/libmultipath/prkey.h b/libmultipath/prkey.h
new file mode 100644
index 0000000..4028e70
--- /dev/null
+++ b/libmultipath/prkey.h
@@ -0,0 +1,19 @@
+#ifndef _PRKEY_H
+#define _PRKEY_H
+
+#include "structs.h"
+#include <inttypes.h>
+
+#define PRKEYS_FILE_HEADER \
+"# Multipath persistent reservation keys, Version : 1.0\n" \
+"# NOTE: this file is automatically maintained by the multipathd program.\n" \
+"# You should not need to edit this file in normal circumstances.\n" \
+"#\n" \
+"# Format:\n" \
+"# prkey wwid\n" \
+"#\n"
+
+int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey);
+int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey);
+
+#endif /* _PRKEY_H */
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 175fbe1..00adc0d 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -20,6 +20,7 @@
#include "dict.h"
#include "util.h"
#include "prioritizers/alua_rtpg.h"
+#include "prkey.h"
#include <inttypes.h>
pgpolicyfn *pgpolicies[] = {
@@ -48,7 +49,7 @@ do { \
#define mp_set_mpe(var) \
do_set(var, mp->mpe, mp->var, "(setting: multipath.conf multipaths section)")
#define mp_set_hwe(var) \
-do_set(var, mp->hwe, mp->var, "(setting: array configuration)")
+do_set(var, mp->hwe, mp->var, "(setting: storage device configuration)")
#define mp_set_ovr(var) \
do_set(var, conf->overrides, mp->var, "(setting: multipath.conf overrides section)")
#define mp_set_conf(var) \
@@ -59,7 +60,7 @@ do_default(mp->var, value)
#define pp_set_mpe(var) \
do_set(var, mpe, pp->var, "(setting: multipath.conf multipaths section)")
#define pp_set_hwe(var) \
-do_set(var, pp->hwe, pp->var, "(setting: array configuration)")
+do_set(var, pp->hwe, pp->var, "(setting: storage device configuration)")
#define pp_set_conf(var) \
do_set(var, conf, pp->var, "(setting: multipath.conf defaults/devices section)")
#define pp_set_ovr(var) \
@@ -82,6 +83,16 @@ do_attr_set(var, mp->mpe, shift, "(setting: multipath.conf multipaths section)")
#define set_attr_conf(var, shift) \
do_attr_set(var, conf, shift, "(setting: multipath.conf defaults/devices section)")
+#define do_prkey_set(src, msg) \
+do { \
+ if (src && src->prkey_source != PRKEY_SOURCE_NONE) { \
+ mp->prkey_source = src->prkey_source; \
+ mp->reservation_key = src->reservation_key; \
+ origin = msg; \
+ goto out; \
+ } \
+} while (0)
+
int select_mode(struct config *conf, struct multipath *mp)
{
char *origin;
@@ -219,7 +230,7 @@ want_user_friendly_names(struct config *conf, struct multipath * mp)
do_set(user_friendly_names, conf->overrides, user_friendly_names,
"(setting: multipath.conf overrides section)");
do_set(user_friendly_names, mp->hwe, user_friendly_names,
- "(setting: array configuration)");
+ "(setting: storage device configuration)");
do_set(user_friendly_names, conf, user_friendly_names,
"(setting: multipath.conf defaults/devices section)");
do_default(user_friendly_names, DEFAULT_USER_FRIENDLY_NAMES);
@@ -363,11 +374,11 @@ int select_checker(struct config *conf, struct path *pp)
if (pp->detect_checker == DETECT_CHECKER_ON && pp->tpgs > 0) {
checker_name = TUR;
- origin = "(setting: array autodetected)";
+ origin = "(setting: storage device autodetected)";
goto out;
}
do_set(checker_name, conf->overrides, checker_name, "(setting: multipath.conf overrides section)");
- do_set(checker_name, pp->hwe, checker_name, "(setting: array configuration)");
+ do_set(checker_name, pp->hwe, checker_name, "(setting: storage device configuration)");
do_set(checker_name, conf, checker_name, "(setting: multipath.conf defaults/devices section)");
do_default(checker_name, DEFAULT_CHECKER);
out:
@@ -468,14 +479,14 @@ int select_prio(struct config *conf, struct path *pp)
if (pp->detect_prio == DETECT_PRIO_ON) {
detect_prio(conf, pp);
if (prio_selected(p)) {
- origin = "(setting: array autodetected)";
+ origin = "(setting: storage device autodetected)";
goto out;
}
}
mpe = find_mpe(conf->mptable, pp->wwid);
set_prio(conf->multipath_dir, mpe, "(setting: multipath.conf multipaths section)");
set_prio(conf->multipath_dir, conf->overrides, "(setting: multipath.conf overrides section)");
- set_prio(conf->multipath_dir, pp->hwe, "(setting: array configuration)");
+ set_prio(conf->multipath_dir, pp->hwe, "(setting: storage device configuration)");
set_prio(conf->multipath_dir, conf, "(setting: multipath.conf defaults/devices section)");
prio_get(conf->multipath_dir, p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);
origin = "(setting: multipath internal)";
@@ -528,7 +539,7 @@ select_minio_rq (struct config *conf, struct multipath * mp)
do_set(minio_rq, mp->mpe, mp->minio, "(setting: multipath.conf multipaths section)");
do_set(minio_rq, conf->overrides, mp->minio, "(setting: multipath.conf overrides section)");
- do_set(minio_rq, mp->hwe, mp->minio, "(setting: array configuration)");
+ do_set(minio_rq, mp->hwe, mp->minio, "(setting: storage device configuration)");
do_set(minio_rq, conf, mp->minio, "(setting: multipath.conf defaults/devices section)");
do_default(mp->minio, DEFAULT_MINIO_RQ);
out:
@@ -609,15 +620,27 @@ out:
int select_reservation_key(struct config *conf, struct multipath *mp)
{
- char *origin, buff[12];
+ char *origin, buff[PRKEY_SIZE];
+ char *from_file = "";
+ uint64_t prkey = 0;
- mp_set_mpe(reservation_key);
- mp_set_conf(reservation_key);
- mp->reservation_key = NULL;
+ do_prkey_set(mp->mpe, "(setting: multipath.conf multipaths section)");
+ do_prkey_set(conf, "(setting: multipath.conf defaults/devices section)");
+ put_be64(mp->reservation_key, 0);
+ mp->prkey_source = PRKEY_SOURCE_NONE;
return 0;
out:
- print_reservation_key(buff, 12, &mp->reservation_key);
- condlog(3, "%s: reservation_key = %s %s", mp->alias, buff, origin);
+ if (mp->prkey_source == PRKEY_SOURCE_FILE) {
+ from_file = " (from prkeys file)";
+ if (get_prkey(conf, mp, &prkey) != 0)
+ put_be64(mp->reservation_key, 0);
+ else
+ put_be64(mp->reservation_key, prkey);
+ }
+ print_reservation_key(buff, PRKEY_SIZE, mp->reservation_key,
+ mp->prkey_source);
+ condlog(3, "%s: reservation_key = %s %s%s", mp->alias, buff, origin,
+ from_file);
return 0;
}
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 2870467..828e790 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -515,9 +515,8 @@ void setup_feature(struct multipath *mpp, char *feature)
int add_feature(char **f, const char *n)
{
- int c = 0, d, l = 0;
- char *e, *p, *t;
- const char *q;
+ int c = 0, d, l;
+ char *e, *t;
if (!f)
return 1;
@@ -526,6 +525,11 @@ int add_feature(char **f, const char *n)
if (!n || *n == '0')
return 0;
+ if (strchr(n, ' ') != NULL) {
+ condlog(0, "internal error: feature \"%s\" contains spaces", n);
+ return 1;
+ }
+
/* default feature is null */
if(!*f)
{
@@ -538,63 +542,34 @@ int add_feature(char **f, const char *n)
}
/* Check if feature is already present */
- if (*f) {
- if (strstr(*f, n))
- return 0;
-
- /* Get feature count */
- c = strtoul(*f, &e, 10);
- if (*f == e)
- /* parse error */
- return 1;
+ if (strstr(*f, n))
+ return 0;
- /* Check if we need to increase feature count space */
- l = strlen(*f) + strlen(n) + 1;
+ /* Get feature count */
+ c = strtoul(*f, &e, 10);
+ if (*f == e || (*e != ' ' && *e != '\0')) {
+ condlog(0, "parse error in feature string \"%s\"", *f);
+ return 1;
}
- /* Count new features */
- if ((c % 10) == 9)
- l++;
+
+ /* Add 1 digit and 1 space */
+ l = strlen(e) + strlen(n) + 2;
+
c++;
- q = n;
- while (*q != '\0') {
- if (*q == ' ' && q[1] != '\0' && q[1] != ' ') {
- if ((c % 10) == 9)
- l++;
- c++;
- }
- q++;
- }
+ /* Check if we need more digits for feature count */
+ for (d = c; d >= 10; d /= 10)
+ l++;
t = MALLOC(l + 1);
if (!t)
return 1;
- memset(t, 0, l + 1);
-
- /* Update feature count */
- d = c;
- l = 1;
- while (d > 9) {
- d /= 10;
- l++;
- }
- p = t;
- snprintf(p, l + 2, "%0d ", c);
-
- /* Copy the feature string */
- p = NULL;
- if (*f)
- p = strchr(*f, ' ');
+ /* e: old feature string with leading space, or "" */
+ if (*e == ' ')
+ while (*(e + 1) == ' ')
+ e++;
- if (p) {
- while (*p == ' ')
- p++;
- strcat(t, p);
- strcat(t, " ");
- } else {
- p = t + strlen(t);
- }
- strcat(t, n);
+ snprintf(t, l + 1, "%0d%s %s", c, e, n);
FREE(*f);
*f = t;
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 8ea984d..f06824a 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -2,8 +2,10 @@
#define _STRUCTS_H
#include <sys/types.h>
+#include <inttypes.h>
#include "prio.h"
+#include "byteorder.h"
#define WWID_SIZE 128
#define SERIAL_SIZE 65
@@ -17,6 +19,7 @@
#define NAME_SIZE 512
#define HOST_NAME_LEN 16
#define SLOT_NAME_SIZE 40
+#define PRKEY_SIZE 19
#define SCSI_VENDOR_SIZE 9
#define SCSI_PRODUCT_SIZE 17
@@ -171,6 +174,12 @@ enum initialized_states {
INIT_OK,
};
+enum prkey_sources {
+ PRKEY_SOURCE_NONE,
+ PRKEY_SOURCE_CONF,
+ PRKEY_SOURCE_FILE,
+};
+
struct sg_id {
int host_no;
int channel;
@@ -306,7 +315,8 @@ struct multipath {
void * mpcontext;
/* persistent management data*/
- unsigned char * reservation_key;
+ int prkey_source;
+ struct be64 reservation_key;
unsigned char prflag;
};
diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
index eb44da5..0cbcc59 100644
--- a/libmultipath/uevent.c
+++ b/libmultipath/uevent.c
@@ -361,6 +361,14 @@ static void uevent_cleanup(void *arg)
udev_unref(udev);
}
+static void monitor_cleanup(void *arg)
+{
+ struct udev_monitor *monitor = arg;
+
+ condlog(3, "Releasing uevent_monitor() resources");
+ udev_monitor_unref(monitor);
+}
+
/*
* Service the uevent queue.
*/
@@ -749,6 +757,7 @@ int uevent_listen(struct udev *udev)
condlog(2, "failed to create udev monitor");
goto out;
}
+ pthread_cleanup_push(monitor_cleanup, monitor);
#ifdef LIBUDEV_API_RECVBUF
if (udev_monitor_set_receive_buffer_size(monitor, 128 * 1024 * 1024))
condlog(2, "failed to increase buffer size");
@@ -834,7 +843,7 @@ int uevent_listen(struct udev *udev)
need_failback = 0;
out:
if (monitor)
- udev_monitor_unref(monitor);
+ pthread_cleanup_pop(1);
if (need_failback)
err = failback_listen();
pthread_cleanup_pop(1);
@@ -885,7 +894,7 @@ int uevent_get_disk_ro(struct uevent *uev)
int i, ro = -1;
for (i = 0; uev->envp[i] != NULL; i++) {
- if (!strncmp(uev->envp[i], "DISK_RO", 6) && strlen(uev->envp[i]) > 7) {
+ if (!strncmp(uev->envp[i], "DISK_RO", 7) && strlen(uev->envp[i]) > 8) {
p = uev->envp[i] + 8;
ro = strtoul(p, &q, 10);
if (p == q) {
@@ -904,8 +913,8 @@ char *uevent_get_dm_name(struct uevent *uev)
int i;
for (i = 0; uev->envp[i] != NULL; i++) {
- if (!strncmp(uev->envp[i], "DM_NAME", 6) &&
- strlen(uev->envp[i]) > 7) {
+ if (!strncmp(uev->envp[i], "DM_NAME", 7) &&
+ strlen(uev->envp[i]) > 8) {
p = MALLOC(strlen(uev->envp[i] + 8) + 1);
strcpy(p, uev->envp[i] + 8);
break;
diff --git a/libmultipath/util.c b/libmultipath/util.c
index dff2ed3..0800da5 100644
--- a/libmultipath/util.c
+++ b/libmultipath/util.c
@@ -11,6 +11,7 @@
#include <unistd.h>
#include <errno.h>
+#include "util.h"
#include "debug.h"
#include "memory.h"
#include "checkers.h"
@@ -416,3 +417,35 @@ int get_linux_version_code(void)
pthread_once(&_lvc_initialized, _set_linux_version_code);
return _linux_version_code;
}
+
+int parse_prkey(char *ptr, uint64_t *prkey)
+{
+ if (!ptr)
+ return 1;
+ if (*ptr == '0')
+ ptr++;
+ if (*ptr == 'x' || *ptr == 'X')
+ ptr++;
+ if (*ptr == '\0' || strlen(ptr) > 16)
+ return 1;
+ if (strlen(ptr) != strspn(ptr, "0123456789aAbBcCdDeEfF"))
+ return 1;
+ if (sscanf(ptr, "%" SCNx64 "", prkey) != 1)
+ return 1;
+ return 0;
+}
+
+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;
+}
diff --git a/libmultipath/util.h b/libmultipath/util.h
index 45291be..3dc048e 100644
--- a/libmultipath/util.h
+++ b/libmultipath/util.h
@@ -2,6 +2,7 @@
#define _UTIL_H
#include <sys/types.h>
+#include <inttypes.h>
size_t strchop(char *);
int basenamecpy (const char * src, char * dst, int);
@@ -16,6 +17,9 @@ char *parse_uid_attribute_by_attrs(char *uid_attrs, char *path_dev);
void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached);
int systemd_service_enabled(const char *dev);
int get_linux_version_code(void);
+int parse_prkey(char *ptr, uint64_t *prkey);
+int safe_write(int fd, const void *buf, size_t count);
+
#define KERNEL_VERSION(maj, min, ptc) ((((maj) * 256) + (min)) * 256 + (ptc))
#define safe_sprintf(var, format, args...) \
diff --git a/libmultipath/version.h b/libmultipath/version.h
index 777d71a..0a0da9e 100644
--- a/libmultipath/version.h
+++ b/libmultipath/version.h
@@ -20,8 +20,8 @@
#ifndef _VERSION_H
#define _VERSION_H
-#define VERSION_CODE 0x000702
-#define DATE_CODE 0x080511
+#define VERSION_CODE 0x000703
+#define DATE_CODE 0x090514
#define PROG "multipath-tools"