diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2022-01-14 13:50:17 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2022-01-14 13:50:17 +0900 |
commit | 7e244d28c5b51809837b8679e0b547e1432829b4 (patch) | |
tree | 81ea816dca9b2feec6e4e9b674d33660b3357063 /libmultipath | |
parent | 28bc88e5da7ffd00fcdac1d23c729d19e646f3fd (diff) | |
download | multipath-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/Makefile | 2 | ||||
-rw-r--r-- | libmultipath/byteorder.h | 44 | ||||
-rw-r--r-- | libmultipath/checkers.c | 26 | ||||
-rw-r--r-- | libmultipath/checkers.h | 3 | ||||
-rw-r--r-- | libmultipath/checkers/rbd.c | 16 | ||||
-rw-r--r-- | libmultipath/config.c | 9 | ||||
-rw-r--r-- | libmultipath/config.h | 10 | ||||
-rw-r--r-- | libmultipath/configure.c | 58 | ||||
-rw-r--r-- | libmultipath/configure.h | 1 | ||||
-rw-r--r-- | libmultipath/defaults.h | 1 | ||||
-rw-r--r-- | libmultipath/devmapper.c | 87 | ||||
-rw-r--r-- | libmultipath/devmapper.h | 5 | ||||
-rw-r--r-- | libmultipath/dict.c | 105 | ||||
-rw-r--r-- | libmultipath/dict.h | 4 | ||||
-rw-r--r-- | libmultipath/discovery.c | 62 | ||||
-rw-r--r-- | libmultipath/discovery.h | 4 | ||||
-rw-r--r-- | libmultipath/hwtable.c | 54 | ||||
-rw-r--r-- | libmultipath/print.c | 2 | ||||
-rw-r--r-- | libmultipath/prkey.c | 166 | ||||
-rw-r--r-- | libmultipath/prkey.h | 19 | ||||
-rw-r--r-- | libmultipath/propsel.c | 51 | ||||
-rw-r--r-- | libmultipath/structs.c | 77 | ||||
-rw-r--r-- | libmultipath/structs.h | 12 | ||||
-rw-r--r-- | libmultipath/uevent.c | 17 | ||||
-rw-r--r-- | libmultipath/util.c | 33 | ||||
-rw-r--r-- | libmultipath/util.h | 4 | ||||
-rw-r--r-- | libmultipath/version.h | 4 |
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" |