From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 20 Dec 2022 17:41:10 -0600 Subject: [PATCH] multipathd: make pr registration consistent multipathd was inconsistent on what it did with persistent reservations when a multipath device was created. If a multipath device with a configured reservation key was created during configure(), multipathd would try to read the registered keys using an active path. If it saw a matching key, it would set the prflag, but not attempt to register the key on any of the other paths. This means that if a new path had appeared while multipathd was not running, it wouldn't register the key on this path. If the multipath device was created during ev_add_path(), multipathd would used the added path to check if there was a matching key and if there was, register the key only on the added path and then set the prflag. This could be problematic if the device was created with multiple paths, for instance because find_mutipaths was set to "yes" and a second path just appeared. In this case, if the device happened to be only registered on the second path, it would not get registered on the first path. If the multipath device was added to multipathd during a call to ev_add_map(), multipathd wouldn't set the prflag or register the key on any paths. After a device was created with the prflag set, if a new path appeared before the creation uevent, and multipathd was forced to delay adding it, when it finally updated the multipath device, the key would be registered on all paths, fixing any paths missed during creation. However, if a new path appeared after the creation uevent, the key would only be registered on that new path. Any paths that were missed on creation would stay missed. persistent key registration needs to be handled consistently. This patch does so by making sure that however a multipath device is added to multipathd, it will check to see if the configured key is registered. If it is, multipathd will set the prflag and register the key on all the currently active paths. When a new path is added, multipathd will use it to check for active keys, as before. But if it finds a matching key and prflag isn't currently set, it will register the key on all paths. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- multipathd/main.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/multipathd/main.c b/multipathd/main.c index 1e1b254f..f7212d7b 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -586,13 +586,26 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) { return false; } +static void +pr_register_active_paths(struct multipath *mpp) +{ + unsigned int i, j; + struct path *pp; + struct pathgroup *pgp; + + vector_foreach_slot (mpp->pg, pgp, i) { + vector_foreach_slot (pgp->paths, pp, j) { + if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST)) + mpath_pr_event_handle(pp); + } + } +} + static int update_map (struct multipath *mpp, struct vectors *vecs, int new_map) { int retries = 3; char *params __attribute__((cleanup(cleanup_charp))) = NULL; - struct path *pp; - int i; retry: condlog(4, "%s: updating new map", mpp->alias); @@ -609,15 +622,6 @@ retry: mpp->action = ACT_RELOAD; - if (mpp->prflag) { - vector_foreach_slot(mpp->paths, pp, i) { - if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST)) { - /* persistent reservation check*/ - mpath_pr_event_handle(pp); - } - } - } - if (setup_map(mpp, ¶ms, vecs)) { condlog(0, "%s: failed to setup new map in update", mpp->alias); retries = -1; @@ -643,6 +647,11 @@ fail: sync_map_state(mpp); + if (!mpp->prflag) + update_map_pr(mpp); + if (mpp->prflag) + pr_register_active_paths(mpp); + if (retries < 0) condlog(0, "%s: failed reload in new map update", mpp->alias); return 0; @@ -1191,6 +1200,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) int start_waiter = 0; int ret; int ro; + unsigned char prflag = 0; /* * need path UID to go any further @@ -1234,6 +1244,8 @@ rescan: verify_paths(mpp); mpp->action = ACT_RELOAD; + prflag = mpp->prflag; + mpath_pr_event_handle(pp); } else { if (!should_multipath(pp, vecs->pathvec, vecs->mpvec)) { orphan_path(pp, "only one path"); @@ -1252,9 +1264,6 @@ rescan: goto fail; /* leave path added to pathvec */ } - /* persistent reservation check*/ - mpath_pr_event_handle(pp); - /* ro check - if new path is ro, force map to be ro as well */ ro = sysfs_get_ro(pp); if (ro == 1) @@ -1319,6 +1328,10 @@ rescan: sync_map_state(mpp); if (retries >= 0) { + if (start_waiter) + update_map_pr(mpp); + if (mpp->prflag && !prflag) + pr_register_active_paths(mpp); condlog(2, "%s [%s]: path added to devmap %s", pp->dev, pp->dev_t, mpp->alias); return 0; @@ -2852,6 +2865,8 @@ configure (struct vectors * vecs, enum force_reload_types reload_type) if (remember_wwid(mpp->wwid) == 1) trigger_paths_udev_change(mpp, true); update_map_pr(mpp); + if (mpp->prflag) + pr_register_active_paths(mpp); } /*