summaryrefslogtreecommitdiff
path: root/libmultipath/pgpolicies.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmultipath/pgpolicies.c')
-rw-r--r--libmultipath/pgpolicies.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
new file mode 100644
index 0000000..10e4515
--- /dev/null
+++ b/libmultipath/pgpolicies.c
@@ -0,0 +1,346 @@
+/*
+ * Here we define the path grouping policies
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+#include "memory.h"
+#include "vector.h"
+#include "structs.h"
+#include "pgpolicies.h"
+
+#include "../libcheckers/path_state.h"
+
+extern int
+get_pgpolicy_id (char * str)
+{
+ if (0 == strncmp(str, "failover", 8))
+ return FAILOVER;
+ if (0 == strncmp(str, "multibus", 8))
+ return MULTIBUS;
+ if (0 == strncmp(str, "group_by_serial", 15))
+ return GROUP_BY_SERIAL;
+ if (0 == strncmp(str, "group_by_prio", 13))
+ return GROUP_BY_PRIO;
+ if (0 == strncmp(str, "group_by_node_name", 18))
+ return GROUP_BY_NODE_NAME;
+
+ return -1;
+}
+
+extern void
+get_pgpolicy_name (char * buff, int id)
+{
+ char * s;
+
+ switch (id) {
+ case FAILOVER:
+ s = "failover";
+ break;
+ case MULTIBUS:
+ s = "multibus";
+ break;
+ case GROUP_BY_SERIAL:
+ s = "group_by_serial";
+ break;
+ case GROUP_BY_PRIO:
+ s = "group_by_prio";
+ break;
+ case GROUP_BY_NODE_NAME:
+ s = "group_by_node_name";
+ break;
+ default:
+ s = "undefined";
+ break;
+ }
+ if(safe_snprintf(buff, POLICY_NAME_SIZE, "%s", s)) {
+ fprintf(stderr, "get_pgpolicy_name: buff too small\n");
+ exit(1);
+ }
+}
+
+/*
+ * One path group per unique tgt_node_name present in the path vector
+ */
+extern int
+group_by_node_name (struct multipath * mp) {
+ int i, j;
+ int * bitmap;
+ struct path * pp;
+ struct pathgroup * pgp;
+ struct path * pp2;
+
+ if (!mp->pg)
+ mp->pg = vector_alloc();
+
+ if (!mp->pg)
+ return 1;
+
+ /* init the bitmap */
+ bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
+
+ if (!bitmap)
+ goto out;
+
+ for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
+
+ if (bitmap[i])
+ continue;
+
+ pp = VECTOR_SLOT(mp->paths, i);
+
+ /* here, we really got a new pg */
+ pgp = alloc_pathgroup();
+
+ if (!pgp)
+ goto out1;
+
+ if (store_pathgroup(mp->pg, pgp))
+ goto out1;
+
+ /* feed the first path */
+ if (store_path(pgp->paths, pp))
+ goto out1;
+
+ bitmap[i] = 1;
+
+ for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
+
+ if (bitmap[j])
+ continue;
+
+ pp2 = VECTOR_SLOT(mp->paths, j);
+
+ if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name,
+ NODE_NAME_SIZE)) {
+ if (store_path(pgp->paths, pp2))
+ goto out1;
+
+ bitmap[j] = 1;
+ }
+ }
+ }
+ FREE(bitmap);
+ free_pathvec(mp->paths, KEEP_PATHS);
+ mp->paths = NULL;
+ return 0;
+out1:
+ FREE(bitmap);
+out:
+ free_pgvec(mp->pg, KEEP_PATHS);
+ return 1;
+}
+
+/*
+ * One path group per unique serial number present in the path vector
+ */
+extern int
+group_by_serial (struct multipath * mp) {
+ int i, j;
+ int * bitmap;
+ struct path * pp;
+ struct pathgroup * pgp;
+ struct path * pp2;
+
+ if (!mp->pg)
+ mp->pg = vector_alloc();
+
+ if (!mp->pg)
+ return 1;
+
+ /* init the bitmap */
+ bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
+
+ if (!bitmap)
+ goto out;
+
+ for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
+
+ if (bitmap[i])
+ continue;
+
+ pp = VECTOR_SLOT(mp->paths, i);
+
+ /* here, we really got a new pg */
+ pgp = alloc_pathgroup();
+
+ if (!pgp)
+ goto out1;
+
+ if (store_pathgroup(mp->pg, pgp))
+ goto out1;
+
+ /* feed the first path */
+ if (store_path(pgp->paths, pp))
+ goto out1;
+
+ bitmap[i] = 1;
+
+ for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
+
+ if (bitmap[j])
+ continue;
+
+ pp2 = VECTOR_SLOT(mp->paths, j);
+
+ if (0 == strcmp(pp->serial, pp2->serial)) {
+ if (store_path(pgp->paths, pp2))
+ goto out1;
+
+ bitmap[j] = 1;
+ }
+ }
+ }
+ FREE(bitmap);
+ free_pathvec(mp->paths, KEEP_PATHS);
+ mp->paths = NULL;
+ return 0;
+out1:
+ FREE(bitmap);
+out:
+ free_pgvec(mp->pg, KEEP_PATHS);
+ return 1;
+}
+
+extern int
+one_path_per_group (struct multipath * mp)
+{
+ int i;
+ struct path * pp;
+ struct pathgroup * pgp;
+
+ if (!mp->pg)
+ mp->pg = vector_alloc();
+
+ if (!mp->pg)
+ return 1;
+
+ for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
+ pp = VECTOR_SLOT(mp->paths, i);
+ pgp = alloc_pathgroup();
+
+ if (!pgp)
+ goto out;
+
+ if (store_pathgroup(mp->pg, pgp))
+ goto out;
+
+ if (store_path(pgp->paths, pp))
+ goto out;
+ }
+ free_pathvec(mp->paths, KEEP_PATHS);
+ mp->paths = NULL;
+ return 0;
+out:
+ free_pgvec(mp->pg, KEEP_PATHS);
+ return 1;
+}
+
+extern int
+one_group (struct multipath * mp) /* aka multibus */
+{
+ struct pathgroup * pgp;
+
+ if (VECTOR_SIZE(pgp->paths) < 0)
+ return 0;
+
+ if (!mp->pg)
+ mp->pg = vector_alloc();
+
+ if (!mp->pg)
+ return 1;
+
+ pgp = alloc_pathgroup();
+
+ if (!pgp)
+ goto out;
+
+ vector_free(pgp->paths);
+ pgp->paths = mp->paths;
+ mp->paths = NULL;
+
+ if (store_pathgroup(mp->pg, pgp))
+ goto out;
+
+ return 0;
+out:
+ free_pgvec(mp->pg, KEEP_PATHS);
+ return 1;
+}
+
+extern int
+group_by_prio (struct multipath * mp)
+{
+ int i;
+ unsigned int prio;
+ struct path * pp;
+ struct pathgroup * pgp;
+
+ if (!mp->pg)
+ mp->pg = vector_alloc();
+
+ if (!mp->pg)
+ return 1;
+
+ while (VECTOR_SIZE(mp->paths) > 0) {
+ pp = VECTOR_SLOT(mp->paths, 0);
+ prio = pp->priority;
+
+ /*
+ * Find the position to insert the new path group. All groups
+ * are ordered by the priority value (higher value first).
+ */
+ vector_foreach_slot(mp->pg, pgp, i) {
+ pp = VECTOR_SLOT(pgp->paths, 0);
+
+ if (prio > pp->priority)
+ break;
+ }
+
+ /*
+ * Initialize the new path group.
+ */
+ pgp = alloc_pathgroup();
+
+ if (!pgp)
+ goto out;
+
+ if (store_path(pgp->paths, VECTOR_SLOT(mp->paths, 0)))
+ goto out;
+
+ vector_del_slot(mp->paths, 0);
+
+ /*
+ * Store the new path group into the vector.
+ */
+ if (i < VECTOR_SIZE(mp->pg)) {
+ if (!vector_insert_slot(mp->pg, i, pgp))
+ goto out;
+ } else {
+ if (store_pathgroup(mp->pg, pgp))
+ goto out;
+ }
+
+ /*
+ * add the other paths with the same prio
+ */
+ vector_foreach_slot(mp->paths, pp, i) {
+ if (pp->priority == prio) {
+ if (store_path(pgp->paths, pp))
+ goto out;
+
+ vector_del_slot(mp->paths, i);
+ i--;
+ }
+ }
+ }
+ free_pathvec(mp->paths, KEEP_PATHS);
+ mp->paths = NULL;
+ return 0;
+out:
+ free_pgvec(mp->pg, KEEP_PATHS);
+ return 1;
+
+}