|
|
f20720 |
---
|
|
|
f20720 |
libmultipath/configure.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
f20720 |
libmultipath/configure.h | 2
|
|
|
f20720 |
libmultipath/discovery.c | 87 +++++++++++++++++
|
|
|
f20720 |
libmultipath/discovery.h | 2
|
|
|
f20720 |
libmultipath/structs.c | 84 +++++++++++++++++
|
|
|
f20720 |
libmultipath/structs.h | 25 ++++-
|
|
|
f20720 |
6 files changed, 427 insertions(+), 2 deletions(-)
|
|
|
f20720 |
|
|
|
f20720 |
Index: multipath-tools-130222/libmultipath/configure.c
|
|
|
f20720 |
===================================================================
|
|
|
f20720 |
--- multipath-tools-130222.orig/libmultipath/configure.c
|
|
|
f20720 |
+++ multipath-tools-130222/libmultipath/configure.c
|
|
|
f20720 |
@@ -39,6 +39,219 @@
|
|
|
f20720 |
#include "uxsock.h"
|
|
|
f20720 |
#include "wwids.h"
|
|
|
f20720 |
|
|
|
f20720 |
+/* group paths in pg by host adapter
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+int group_by_host_adapter(struct pathgroup *pgp, vector adapters)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ struct adapter_group *agp;
|
|
|
f20720 |
+ struct host_group *hgp;
|
|
|
f20720 |
+ struct path *pp, *pp1;
|
|
|
f20720 |
+ char adapter_name1[SLOT_NAME_SIZE];
|
|
|
f20720 |
+ char adapter_name2[SLOT_NAME_SIZE];
|
|
|
f20720 |
+ int i, j;
|
|
|
f20720 |
+ int found_hostgroup = 0;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ while (VECTOR_SIZE(pgp->paths) > 0) {
|
|
|
f20720 |
+
|
|
|
f20720 |
+ pp = VECTOR_SLOT(pgp->paths, 0);
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (sysfs_get_host_adapter_name(pp, adapter_name1))
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+ /* create a new host adapter group
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ agp = alloc_adaptergroup();
|
|
|
f20720 |
+ if (!agp)
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+ agp->pgp = pgp;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ strncpy(agp->adapter_name, adapter_name1, SLOT_NAME_SIZE);
|
|
|
f20720 |
+ store_adaptergroup(adapters, agp);
|
|
|
f20720 |
+
|
|
|
f20720 |
+ /* create a new host port group
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ hgp = alloc_hostgroup();
|
|
|
f20720 |
+ if (!hgp)
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+ if (store_hostgroup(agp->host_groups, hgp))
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ hgp->host_no = pp->sg_id.host_no;
|
|
|
f20720 |
+ agp->num_hosts++;
|
|
|
f20720 |
+ if (store_path(hgp->paths, pp))
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ hgp->num_paths++;
|
|
|
f20720 |
+ /* delete path from path group
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ vector_del_slot(pgp->paths, 0);
|
|
|
f20720 |
+
|
|
|
f20720 |
+ /* add all paths belonging to same host adapter
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ vector_foreach_slot(pgp->paths, pp1, i) {
|
|
|
f20720 |
+ if (sysfs_get_host_adapter_name(pp1, adapter_name2))
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+ if (strcmp(adapter_name1, adapter_name2) == 0) {
|
|
|
f20720 |
+ found_hostgroup = 0;
|
|
|
f20720 |
+ vector_foreach_slot(agp->host_groups, hgp, j) {
|
|
|
f20720 |
+ if (hgp->host_no == pp1->sg_id.host_no) {
|
|
|
f20720 |
+ if (store_path(hgp->paths, pp1))
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+ hgp->num_paths++;
|
|
|
f20720 |
+ found_hostgroup = 1;
|
|
|
f20720 |
+ break;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ if (!found_hostgroup) {
|
|
|
f20720 |
+ /* this path belongs to new host port
|
|
|
f20720 |
+ * within this adapter
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ hgp = alloc_hostgroup();
|
|
|
f20720 |
+ if (!hgp)
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (store_hostgroup(agp->host_groups, hgp))
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ agp->num_hosts++;
|
|
|
f20720 |
+ if (store_path(hgp->paths, pp1))
|
|
|
f20720 |
+ goto out;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ hgp->host_no = pp1->sg_id.host_no;
|
|
|
f20720 |
+ hgp->num_paths++;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ /* delete paths from original path_group
|
|
|
f20720 |
+ * as they are added into adapter group now
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ vector_del_slot(pgp->paths, i);
|
|
|
f20720 |
+ i--;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+
|
|
|
f20720 |
+out: /* add back paths into pg as re-ordering failed
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ vector_foreach_slot(adapters, agp, i) {
|
|
|
f20720 |
+ vector_foreach_slot(agp->host_groups, hgp, j) {
|
|
|
f20720 |
+ while (VECTOR_SIZE(hgp->paths) > 0) {
|
|
|
f20720 |
+ pp = VECTOR_SLOT(hgp->paths, 0);
|
|
|
f20720 |
+ if (store_path(pgp->paths, pp))
|
|
|
f20720 |
+ condlog(3, "failed to restore "
|
|
|
f20720 |
+ "path %s into path group",
|
|
|
f20720 |
+ pp->dev);
|
|
|
f20720 |
+ vector_del_slot(hgp->paths, 0);
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ free_adaptergroup(adapters);
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+/* re-order paths in pg by alternating adapters and host ports
|
|
|
f20720 |
+ * for optimized selection
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+int order_paths_in_pg_by_alt_adapters(struct pathgroup *pgp, vector adapters,
|
|
|
f20720 |
+ int total_paths)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ int next_adapter_index = 0;
|
|
|
f20720 |
+ struct adapter_group *agp;
|
|
|
f20720 |
+ struct host_group *hgp;
|
|
|
f20720 |
+ struct path *pp;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ while (total_paths > 0) {
|
|
|
f20720 |
+ agp = VECTOR_SLOT(adapters, next_adapter_index);
|
|
|
f20720 |
+ if (!agp) {
|
|
|
f20720 |
+ condlog(0, "can't get adapter group %d", next_adapter_index);
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+
|
|
|
f20720 |
+ hgp = VECTOR_SLOT(agp->host_groups, agp->next_host_index);
|
|
|
f20720 |
+ if (!hgp) {
|
|
|
f20720 |
+ condlog(0, "can't get host group %d of adapter group %d", next_adapter_index, agp->next_host_index);
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (!hgp->num_paths) {
|
|
|
f20720 |
+ agp->next_host_index++;
|
|
|
f20720 |
+ agp->next_host_index %= agp->num_hosts;
|
|
|
f20720 |
+ next_adapter_index++;
|
|
|
f20720 |
+ next_adapter_index %= VECTOR_SIZE(adapters);
|
|
|
f20720 |
+ continue;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+
|
|
|
f20720 |
+ pp = VECTOR_SLOT(hgp->paths, 0);
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (store_path(pgp->paths, pp))
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ total_paths--;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ vector_del_slot(hgp->paths, 0);
|
|
|
f20720 |
+
|
|
|
f20720 |
+ hgp->num_paths--;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ agp->next_host_index++;
|
|
|
f20720 |
+ agp->next_host_index %= agp->num_hosts;
|
|
|
f20720 |
+ next_adapter_index++;
|
|
|
f20720 |
+ next_adapter_index %= VECTOR_SIZE(adapters);
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+
|
|
|
f20720 |
+ /* all paths are added into path_group
|
|
|
f20720 |
+ * in crafted child order
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+/* round-robin: order paths in path group to alternate
|
|
|
f20720 |
+ * between all host adapters
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+int rr_optimize_path_order(struct pathgroup *pgp)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ vector adapters;
|
|
|
f20720 |
+ struct path *pp;
|
|
|
f20720 |
+ int total_paths;
|
|
|
f20720 |
+ int i;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ total_paths = VECTOR_SIZE(pgp->paths);
|
|
|
f20720 |
+ vector_foreach_slot(pgp->paths, pp, i) {
|
|
|
f20720 |
+ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP &&
|
|
|
f20720 |
+ pp->sg_id.proto_id != SCSI_PROTOCOL_SAS &&
|
|
|
f20720 |
+ pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI &&
|
|
|
f20720 |
+ pp->sg_id.proto_id != SCSI_PROTOCOL_SRP) {
|
|
|
f20720 |
+ /* return success as default path order
|
|
|
f20720 |
+ * is maintained in path group
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ adapters = vector_alloc();
|
|
|
f20720 |
+ if (!adapters)
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ /* group paths in path group by host adapters
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ if (group_by_host_adapter(pgp, adapters)) {
|
|
|
f20720 |
+ /* already freed adapters */
|
|
|
f20720 |
+ condlog(3, "Failed to group paths by adapters");
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+
|
|
|
f20720 |
+ /* re-order paths in pg to alternate between adapters and host ports
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ if (order_paths_in_pg_by_alt_adapters(pgp, adapters, total_paths)) {
|
|
|
f20720 |
+ condlog(3, "Failed to re-order paths in pg by adapters "
|
|
|
f20720 |
+ "and host ports");
|
|
|
f20720 |
+ free_adaptergroup(adapters);
|
|
|
f20720 |
+ /* return failure as original paths are
|
|
|
f20720 |
+ * removed form pgp
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+
|
|
|
f20720 |
+ free_adaptergroup(adapters);
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
extern int
|
|
|
f20720 |
setup_map (struct multipath * mpp, char * params, int params_size)
|
|
|
f20720 |
{
|
|
|
f20720 |
@@ -101,6 +314,22 @@ setup_map (struct multipath * mpp, char
|
|
|
f20720 |
*/
|
|
|
f20720 |
mpp->bestpg = select_path_group(mpp);
|
|
|
f20720 |
|
|
|
f20720 |
+ /* re-order paths in all path groups in an optimized way
|
|
|
f20720 |
+ * for round-robin path selectors to get maximum throughput.
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ if (!strncmp(mpp->selector, "round-robin", 11)) {
|
|
|
f20720 |
+ vector_foreach_slot(mpp->pg, pgp, i) {
|
|
|
f20720 |
+ if (VECTOR_SIZE(pgp->paths) <= 2)
|
|
|
f20720 |
+ continue;
|
|
|
f20720 |
+ if (rr_optimize_path_order(pgp)) {
|
|
|
f20720 |
+ condlog(2, "cannot re-order paths for "
|
|
|
f20720 |
+ "optimization: %s",
|
|
|
f20720 |
+ mpp->alias);
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+
|
|
|
f20720 |
/*
|
|
|
f20720 |
* transform the mp->pg vector of vectors of paths
|
|
|
f20720 |
* into a mp->params strings to feed the device-mapper
|
|
|
f20720 |
Index: multipath-tools-130222/libmultipath/configure.h
|
|
|
f20720 |
===================================================================
|
|
|
f20720 |
--- multipath-tools-130222.orig/libmultipath/configure.h
|
|
|
f20720 |
+++ multipath-tools-130222/libmultipath/configure.h
|
|
|
f20720 |
@@ -29,4 +29,4 @@ int reinstate_paths (struct multipath *m
|
|
|
f20720 |
int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload);
|
|
|
f20720 |
int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid);
|
|
|
f20720 |
int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh);
|
|
|
f20720 |
-
|
|
|
f20720 |
+int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name);
|
|
|
f20720 |
Index: multipath-tools-130222/libmultipath/discovery.c
|
|
|
f20720 |
===================================================================
|
|
|
f20720 |
--- multipath-tools-130222.orig/libmultipath/discovery.c
|
|
|
f20720 |
+++ multipath-tools-130222/libmultipath/discovery.c
|
|
|
f20720 |
@@ -310,6 +310,93 @@ sysfs_get_tgt_nodename (struct path *pp,
|
|
|
f20720 |
return 1;
|
|
|
f20720 |
}
|
|
|
f20720 |
|
|
|
f20720 |
+int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ int proto_id;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (!pp || !adapter_name)
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ proto_id = pp->sg_id.proto_id;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (proto_id != SCSI_PROTOCOL_FCP &&
|
|
|
f20720 |
+ proto_id != SCSI_PROTOCOL_SAS &&
|
|
|
f20720 |
+ proto_id != SCSI_PROTOCOL_ISCSI &&
|
|
|
f20720 |
+ proto_id != SCSI_PROTOCOL_SRP) {
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ /* iscsi doesn't have adapter info in sysfs
|
|
|
f20720 |
+ * get ip_address for grouping paths
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
|
|
|
f20720 |
+ return sysfs_get_iscsi_ip_address(pp, adapter_name);
|
|
|
f20720 |
+
|
|
|
f20720 |
+ /* fetch adapter pci name for other protocols
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ return sysfs_get_host_pci_name(pp, adapter_name);
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+int sysfs_get_host_pci_name(struct path *pp, char *pci_name)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ struct udev_device *hostdev, *parent;
|
|
|
f20720 |
+ char host_name[HOST_NAME_LEN];
|
|
|
f20720 |
+ const char *driver_name, *value;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (!pp || !pci_name)
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ sprintf(host_name, "host%d", pp->sg_id.host_no);
|
|
|
f20720 |
+ hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
|
|
|
f20720 |
+ "scsi_host", host_name);
|
|
|
f20720 |
+ if (!hostdev)
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ parent = udev_device_get_parent(hostdev);
|
|
|
f20720 |
+ while (parent) {
|
|
|
f20720 |
+ driver_name = udev_device_get_driver(parent);
|
|
|
f20720 |
+ if (!driver_name) {
|
|
|
f20720 |
+ parent = udev_device_get_parent(parent);
|
|
|
f20720 |
+ continue;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ if (!strcmp(driver_name, "pcieport"))
|
|
|
f20720 |
+ break;
|
|
|
f20720 |
+ parent = udev_device_get_parent(parent);
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ if (parent) {
|
|
|
f20720 |
+ /* pci_device found
|
|
|
f20720 |
+ */
|
|
|
f20720 |
+ value = udev_device_get_sysname(parent);
|
|
|
f20720 |
+
|
|
|
f20720 |
+ strncpy(pci_name, value, SLOT_NAME_SIZE);
|
|
|
f20720 |
+ udev_device_unref(hostdev);
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ udev_device_unref(hostdev);
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ struct udev_device *hostdev;
|
|
|
f20720 |
+ char host_name[HOST_NAME_LEN];
|
|
|
f20720 |
+ const char *value;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ sprintf(host_name, "host%d", pp->sg_id.host_no);
|
|
|
f20720 |
+ hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
|
|
|
f20720 |
+ "iscsi_host", host_name);
|
|
|
f20720 |
+ if (hostdev) {
|
|
|
f20720 |
+ value = udev_device_get_sysattr_value(hostdev,
|
|
|
f20720 |
+ "ipaddress");
|
|
|
f20720 |
+ if (value) {
|
|
|
f20720 |
+ strncpy(ip_address, value, SLOT_NAME_SIZE);
|
|
|
f20720 |
+ udev_device_unref(hostdev);
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+ } else
|
|
|
f20720 |
+ udev_device_unref(hostdev);
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
static void
|
|
|
f20720 |
sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
|
|
f20720 |
{
|
|
|
f20720 |
Index: multipath-tools-130222/libmultipath/discovery.h
|
|
|
f20720 |
===================================================================
|
|
|
f20720 |
--- multipath-tools-130222.orig/libmultipath/discovery.h
|
|
|
f20720 |
+++ multipath-tools-130222/libmultipath/discovery.h
|
|
|
f20720 |
@@ -38,6 +38,8 @@ int store_pathinfo (vector pathvec, vect
|
|
|
f20720 |
struct path **pp_ptr);
|
|
|
f20720 |
int sysfs_set_scsi_tmo (struct multipath *mpp);
|
|
|
f20720 |
int sysfs_get_timeout(struct path *pp, unsigned int *timeout);
|
|
|
f20720 |
+int sysfs_get_host_pci_name(struct path *pp, char *pci_name);
|
|
|
f20720 |
+int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address);
|
|
|
f20720 |
|
|
|
f20720 |
/*
|
|
|
f20720 |
* discovery bitmask
|
|
|
f20720 |
Index: multipath-tools-130222/libmultipath/structs.c
|
|
|
f20720 |
===================================================================
|
|
|
f20720 |
--- multipath-tools-130222.orig/libmultipath/structs.c
|
|
|
f20720 |
+++ multipath-tools-130222/libmultipath/structs.c
|
|
|
f20720 |
@@ -18,6 +18,70 @@
|
|
|
f20720 |
#include "blacklist.h"
|
|
|
f20720 |
#include "prio.h"
|
|
|
f20720 |
|
|
|
f20720 |
+struct adapter_group *
|
|
|
f20720 |
+alloc_adaptergroup(void)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ struct adapter_group *agp;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ agp = (struct adapter_group *)MALLOC(sizeof(struct adapter_group));
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (!agp)
|
|
|
f20720 |
+ return NULL;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ agp->host_groups = vector_alloc();
|
|
|
f20720 |
+ if (!agp->host_groups) {
|
|
|
f20720 |
+ FREE(agp);
|
|
|
f20720 |
+ agp = NULL;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ return agp;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+void free_adaptergroup(vector adapters)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ int i;
|
|
|
f20720 |
+ struct adapter_group *agp;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ vector_foreach_slot(adapters, agp, i) {
|
|
|
f20720 |
+ free_hostgroup(agp->host_groups);
|
|
|
f20720 |
+ FREE(agp);
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ vector_free(adapters);
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+void free_hostgroup(vector hostgroups)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ int i;
|
|
|
f20720 |
+ struct host_group *hgp;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (!hostgroups)
|
|
|
f20720 |
+ return;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ vector_foreach_slot(hostgroups, hgp, i) {
|
|
|
f20720 |
+ vector_free(hgp->paths);
|
|
|
f20720 |
+ FREE(hgp);
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ vector_free(hostgroups);
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+struct host_group *
|
|
|
f20720 |
+alloc_hostgroup(void)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ struct host_group *hgp;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ hgp = (struct host_group *)MALLOC(sizeof(struct host_group));
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (!hgp)
|
|
|
f20720 |
+ return NULL;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ hgp->paths = vector_alloc();
|
|
|
f20720 |
+
|
|
|
f20720 |
+ if (!hgp->paths) {
|
|
|
f20720 |
+ FREE(hgp);
|
|
|
f20720 |
+ hgp = NULL;
|
|
|
f20720 |
+ }
|
|
|
f20720 |
+ return hgp;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
struct path *
|
|
|
f20720 |
alloc_path (void)
|
|
|
f20720 |
{
|
|
|
f20720 |
@@ -242,6 +306,26 @@ store_pathgroup (vector pgvec, struct pa
|
|
|
f20720 |
return 0;
|
|
|
f20720 |
}
|
|
|
f20720 |
|
|
|
f20720 |
+int
|
|
|
f20720 |
+store_hostgroup(vector hostgroupvec, struct host_group * hgp)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ if (!vector_alloc_slot(hostgroupvec))
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ vector_set_slot(hostgroupvec, hgp);
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
+int
|
|
|
f20720 |
+store_adaptergroup(vector adapters, struct adapter_group * agp)
|
|
|
f20720 |
+{
|
|
|
f20720 |
+ if (!vector_alloc_slot(adapters))
|
|
|
f20720 |
+ return 1;
|
|
|
f20720 |
+
|
|
|
f20720 |
+ vector_set_slot(adapters, agp);
|
|
|
f20720 |
+ return 0;
|
|
|
f20720 |
+}
|
|
|
f20720 |
+
|
|
|
f20720 |
struct multipath *
|
|
|
f20720 |
find_mp_by_minor (vector mpvec, int minor)
|
|
|
f20720 |
{
|
|
|
f20720 |
Index: multipath-tools-130222/libmultipath/structs.h
|
|
|
f20720 |
===================================================================
|
|
|
f20720 |
--- multipath-tools-130222.orig/libmultipath/structs.h
|
|
|
f20720 |
+++ multipath-tools-130222/libmultipath/structs.h
|
|
|
f20720 |
@@ -15,7 +15,8 @@
|
|
|
f20720 |
#define BLK_DEV_SIZE 33
|
|
|
f20720 |
#define PATH_SIZE 512
|
|
|
f20720 |
#define NAME_SIZE 512
|
|
|
f20720 |
-
|
|
|
f20720 |
+#define HOST_NAME_LEN 8
|
|
|
f20720 |
+#define SLOT_NAME_SIZE 40
|
|
|
f20720 |
|
|
|
f20720 |
#define SCSI_VENDOR_SIZE 9
|
|
|
f20720 |
#define SCSI_PRODUCT_SIZE 17
|
|
|
f20720 |
@@ -251,6 +252,20 @@ struct pathgroup {
|
|
|
f20720 |
char * selector;
|
|
|
f20720 |
};
|
|
|
f20720 |
|
|
|
f20720 |
+struct adapter_group {
|
|
|
f20720 |
+ char adapter_name[SLOT_NAME_SIZE];
|
|
|
f20720 |
+ struct pathgroup *pgp;
|
|
|
f20720 |
+ int num_hosts;
|
|
|
f20720 |
+ vector host_groups;
|
|
|
f20720 |
+ int next_host_index;
|
|
|
f20720 |
+};
|
|
|
f20720 |
+
|
|
|
f20720 |
+struct host_group {
|
|
|
f20720 |
+ int host_no;
|
|
|
f20720 |
+ int num_paths;
|
|
|
f20720 |
+ vector paths;
|
|
|
f20720 |
+};
|
|
|
f20720 |
+
|
|
|
f20720 |
struct path * alloc_path (void);
|
|
|
f20720 |
struct pathgroup * alloc_pathgroup (void);
|
|
|
f20720 |
struct multipath * alloc_multipath (void);
|
|
|
f20720 |
@@ -263,6 +278,14 @@ void free_multipath_attributes (struct m
|
|
|
f20720 |
void drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths);
|
|
|
f20720 |
void free_multipathvec (vector mpvec, enum free_path_mode free_paths);
|
|
|
f20720 |
|
|
|
f20720 |
+struct adapter_group * alloc_adaptergroup(void);
|
|
|
f20720 |
+struct host_group * alloc_hostgroup(void);
|
|
|
f20720 |
+void free_adaptergroup(vector adapters);
|
|
|
f20720 |
+void free_hostgroup(vector hostgroups);
|
|
|
f20720 |
+
|
|
|
f20720 |
+int store_adaptergroup(vector adapters, struct adapter_group *agp);
|
|
|
f20720 |
+int store_hostgroup(vector hostgroupvec, struct host_group *hgp);
|
|
|
f20720 |
+
|
|
|
f20720 |
int store_path (vector pathvec, struct path * pp);
|
|
|
f20720 |
int store_pathgroup (vector pgvec, struct pathgroup * pgp);
|
|
|
f20720 |
|