device-mapper-multipath/0065-libmpathpersist-retry-on-conflicts-in-mpath_prout_co.patch
Benjamin Marzinski 695f9436f4 device-mapper-multipath-0.9.9-13
Add 0035-libmpathpersist-fix-memory-leak-in-mpath_prout_rel.patch
Add 0036-libmpathpersist-retry-commands-on-other-paths-in-mpa.patch
Add 0037-libmpathpersist-check-released-key-against-the-reser.patch
Add 0038-multipathd-remove-thread-from-mpath_pr_event_handle.patch
Add 0039-libmpathpersist-remove-uneeded-wrapper-function.patch
Add 0040-libmpathpersist-reduce-log-level-for-persistent-rese.patch
Add 0041-libmpathpersist-remove-pointless-update_map_pr-ret-v.patch
Add 0042-multipathd-use-update_map_pr-in-mpath_pr_event_handl.patch
Add 0043-libmpathpersist-limit-changing-prflag-in-update_map_.patch
Add 0044-multipathd-Don-t-call-update_map_pr-unnecessarily.patch
Add 0045-libmpathpersist-remove-useless-function-send_prout_a.patch
Add 0046-libmpathpersist-redesign-failed-release-workaround.patch
Add 0047-libmpathpersist-fail-the-release-if-all-threads-fail.patch
Add 0048-libmpathpersist-Handle-changing-key-corner-case.patch
Add 0049-libmpathpersist-Handle-REGISTER-AND-IGNORE-changing-.patch
Add 0050-libmultipath-rename-prflag_value-enums.patch
Add 0051-libmpathpersist-use-a-switch-statement-for-prout-com.patch
Add 0052-libmpathpersist-Add-safety-check-for-preempting-on-k.patch
Add 0053-libmpathpersist-remove-update_map_pr-code-for-NULL-p.patch
Add 0054-libmpathpersist-move-update_map_pr-to-multipathd.patch
Add 0055-multipathd-clean-up-update_map_pr-and-mpath_pr_event.patch
Add 0056-libmpathpersist-clean-up-duplicate-function-declarat.patch
Add 0057-multipathd-wrap-setting-and-unsetting-prflag.patch
Add 0058-multipathd-unregister-PR-key-when-path-is-restored-i.patch
Add 0059-libmpathpersist-Fix-up-reservation_key-checking.patch
Add 0060-libmpathpersist-change-how-reservation-conflicts-are.patch
Add 0061-libmpathpersist-Clear-prkey-in-multipathd-before-unr.patch
Add 0062-libmpathpersist-only-clear-the-key-if-we-are-using-t.patch
Add 0063-libmpathpersist-Restore-old-reservation-key-on-failu.patch
Add 0064-libmpathpersist-update-reservation-key-before-checki.patch
Add 0065-libmpathpersist-retry-on-conflicts-in-mpath_prout_co.patch
Add 0066-libmpathpersist-Don-t-always-fail-registrations-for-.patch
Add 0067-libmpathpersist-Don-t-try-release-workaround-for-inv.patch
Add 0068-libmpathpersist-Don-t-fail-RESERVE-commands-unnecess.patch
Add 0069-libmpathpersist-reregister-keys-when-self-preempting.patch
Add 0070-libmpathpersist-handle-updating-key-race-condition.patch
Add 0071-libmpathpersist-handle-preempting-all-registrants-re.patch
Add 0072-libmpathpersist-Fix-REGISTER-AND-IGNORE-while-holdin.patch
Add 0073-libmpathpersist-Handle-RESERVE-with-reservation-held.patch
Add 0074-libmpathpersist-use-check_holding_reservation-in-mpa.patch
Add 0075-libmpathpersist-Fix-unregistering-while-holding-the-.patch
Add 0076-libmpathpersist-Fix-race-between-restoring-a-path-an.patch
Add 0077-multipathd-Fix-tracking-of-old-PR-key.patch
  * Fixes RHEL-118720 ("There are many bugs in multipath's persistent
    reservation handling [rhel-10]")
Resolves: RHEL-118720
2025-10-01 16:53:32 -04:00

80 lines
2.9 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Jul 2025 23:58:54 -0400
Subject: [PATCH] libmpathpersist: retry on conflicts in mpath_prout_common
mpath_prout_common() just needs to execute a prout command down one
path. If it uses a path that was down when the key was changed and has
since been restored, but multipathd hasn't noticed yet, that path will
still be using the old key. This was causing mpath_prout_common() to
fail with MPATH_PR_RESERV_CONFLICT, even if there were other paths that
would work.
Now, if prout command fails with MPATH_PR_RESERV_CONFLICT,
mpath_prout_common() checks if pp->dmstate is PSTATE_FAILED. If it is,
mpath_prout_common() assumes that multipathd has not yet noticed that
the path is back online and it might still have and old key, so it
doesn't immediately return. If it can't successfully send the command
down another path, it will still return MPATH_PR_RESERV_CONFLICT.
Also, make sure prout_do_scsi_ioctl() always returns a MPATH_PR_*
type error.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist_int.c | 14 +++++++++++++-
libmpathpersist/mpath_pr_ioctl.c | 2 +-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index d498e69e..762958e8 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -216,6 +216,7 @@ mpath_prout_common(struct multipath *mpp, int rq_servact, int rq_scope,
struct pathgroup *pgp = NULL;
struct path *pp = NULL;
bool found = false;
+ bool conflict = false;
vector_foreach_slot (mpp->pg, pgp, j) {
vector_foreach_slot (pgp->paths, pp, i) {
@@ -232,12 +233,23 @@ mpath_prout_common(struct multipath *mpp, int rq_servact, int rq_scope,
rq_type, paramp, noisy);
if (ret == MPATH_PR_SUCCESS && pptr)
*pptr = pp;
+ /*
+ * If this path is considered down by the kernel,
+ * it may have just come back up, and multipathd
+ * may not have had time to update the key. Allow
+ * reservation conflicts.
+ */
+ if (ret == MPATH_PR_RESERV_CONFLICT &&
+ pp->dmstate == PSTATE_FAILED) {
+ conflict = true;
+ continue;
+ }
if (ret != MPATH_PR_RETRYABLE_ERROR)
return ret;
}
}
if (found)
- return MPATH_PR_OTHER;
+ return conflict ? MPATH_PR_RESERV_CONFLICT : MPATH_PR_OTHER;
condlog(0, "%s: no path available", mpp->wwid);
return MPATH_PR_DMMP_ERROR;
}
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
index dfdbbb65..6eaec7cd 100644
--- a/libmpathpersist/mpath_pr_ioctl.c
+++ b/libmpathpersist/mpath_pr_ioctl.c
@@ -103,7 +103,7 @@ retry :
{
condlog(0, "%s: ioctl failed %d", dev, ret);
close(fd);
- return ret;
+ return MPATH_PR_OTHER;
}
condlog(4, "%s: Duration=%u (ms)", dev, io_hdr.duration);