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