From 227a9fceb8c20f153f4f136caeb28faff5bd80fe Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 12 Jul 2019 15:39:26 -0500 Subject: [PATCH] libmultipath: make group_paths handle marginal paths group_paths() will now create seperate path groups for marginal and normal paths, and place all of the marginal path groups after the normal ones, in order by priority. Signed-off-by: Benjamin Marzinski --- libmultipath/pgpolicies.c | 83 +++++++++++++++++++++++++++++++++----- libmultipath/switchgroup.c | 15 ++++++- 2 files changed, 88 insertions(+), 10 deletions(-) diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c index 2e7c0502..6fb2d28a 100644 --- a/libmultipath/pgpolicies.c +++ b/libmultipath/pgpolicies.c @@ -72,9 +72,11 @@ sort_pathgroups (struct multipath *mp) { pgp2 = VECTOR_SLOT(mp->pg, j); if (!pgp2) continue; - if (pgp2->priority > pgp1->priority || - (pgp2->priority == pgp1->priority && - pgp2->enabled_paths >= pgp1->enabled_paths)) { + if (pgp2->marginal < pgp1->marginal || + (pgp2->marginal == pgp1->marginal && + (pgp2->priority > pgp1->priority || + (pgp2->priority == pgp1->priority && + pgp2->enabled_paths >= pgp1->enabled_paths)))) { vector_move_up(mp->pg, i, j + 1); break; } @@ -84,25 +86,88 @@ sort_pathgroups (struct multipath *mp) { } } +static int +split_marginal_paths(vector paths, vector *normal_p, vector *marginal_p) +{ + int i; + int has_marginal = 0; + int has_normal = 0; + struct path *pp; + vector normal = NULL; + vector marginal = NULL; + + *normal_p = *marginal_p = NULL; + vector_foreach_slot(paths, pp, i) { + if (pp->marginal) + has_marginal = 1; + else + has_normal = 1; + } + + if (!has_marginal || !has_normal) + return -1; + + normal = vector_alloc(); + marginal = vector_alloc(); + if (!normal || !marginal) + goto fail; + + vector_foreach_slot(paths, pp, i) { + if (pp->marginal) { + if (store_path(marginal, pp)) + goto fail; + } + else { + if (store_path(normal, pp)) + goto fail; + } + } + *normal_p = normal; + *marginal_p = marginal; + return 0; +fail: + vector_free(normal); + vector_free(marginal); + return -1; +} int group_paths(struct multipath *mp) { + vector normal, marginal; + if (!mp->pg) mp->pg = vector_alloc(); if (!mp->pg) return 1; - if (VECTOR_SIZE(mp->paths) > 0 && - (!mp->pgpolicyfn || mp->pgpolicyfn(mp, mp->paths))) { - vector_free(mp->pg); - mp->pg = NULL; - return 1; + if (VECTOR_SIZE(mp->paths) == 0) + goto out; + if (!mp->pgpolicyfn) + goto fail; + + if (split_marginal_paths(mp->paths, &normal, &marginal) != 0) { + if (mp->pgpolicyfn(mp, mp->paths) != 0) + goto fail; + } else { + if (mp->pgpolicyfn(mp, normal) != 0) + goto fail_marginal; + if (mp->pgpolicyfn(mp, marginal) != 0) + goto fail_marginal; + vector_free(normal); + vector_free(marginal); } - sort_pathgroups(mp); +out: vector_free(mp->paths); mp->paths = NULL; return 0; +fail_marginal: + vector_free(normal); + vector_free(marginal); +fail: + vector_free(mp->pg); + mp->pg = NULL; + return 1; } typedef bool (path_match_fn)(struct path *pp1, struct path *pp2); diff --git a/libmultipath/switchgroup.c b/libmultipath/switchgroup.c index 9632ce2d..6fdfcfa7 100644 --- a/libmultipath/switchgroup.c +++ b/libmultipath/switchgroup.c @@ -11,6 +11,7 @@ void path_group_prio_update(struct pathgroup *pgp) { int i; int priority = 0; + int marginal = 0; struct path * pp; pgp->enabled_paths = 0; @@ -19,6 +20,8 @@ void path_group_prio_update(struct pathgroup *pgp) return; } vector_foreach_slot (pgp->paths, pp, i) { + if (pp->marginal) + marginal++; if (pp->state == PATH_UP || pp->state == PATH_GHOST) { priority += pp->priority; @@ -29,11 +32,14 @@ void path_group_prio_update(struct pathgroup *pgp) pgp->priority = priority / pgp->enabled_paths; else pgp->priority = 0; + if (marginal && marginal == i) + pgp->marginal = 1; } int select_path_group(struct multipath *mpp) { int i; + int normal_pgp = 0; int max_priority = 0; int bestpg = 1; int max_enabled_paths = 1; @@ -47,8 +53,15 @@ int select_path_group(struct multipath *mpp) continue; path_group_prio_update(pgp); + if (pgp->marginal && normal_pgp) + continue; if (pgp->enabled_paths) { - if (pgp->priority > max_priority) { + if (!pgp->marginal && !normal_pgp) { + normal_pgp = 1; + max_priority = pgp->priority; + max_enabled_paths = pgp->enabled_paths; + bestpg = i + 1; + } else if (pgp->priority > max_priority) { max_priority = pgp->priority; max_enabled_paths = pgp->enabled_paths; bestpg = i + 1; -- 2.17.2