diff options
Diffstat (limited to 'libmultipath/pgpolicies.c')
-rw-r--r-- | libmultipath/pgpolicies.c | 346 |
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; + +} |