|
|
108c2a |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
108c2a |
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
|
108c2a |
Date: Fri, 7 Oct 2022 12:35:40 -0500
|
|
|
108c2a |
Subject: [PATCH] libmultipath: fix queue_mode feature handling
|
|
|
108c2a |
|
|
|
108c2a |
device-mapper is not able to change the queue_mode on a table reload.
|
|
|
108c2a |
Make sure that when multipath sets up the map, both on regular reloads
|
|
|
108c2a |
and reconfigures, it keeps the queue_mode the same.
|
|
|
108c2a |
|
|
|
108c2a |
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
|
108c2a |
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
|
|
108c2a |
---
|
|
|
108c2a |
libmultipath/configure.c | 4 +++
|
|
|
108c2a |
libmultipath/dmparser.c | 2 ++
|
|
|
108c2a |
libmultipath/propsel.c | 55 ++++++++++++++++++++++++++++++++++++++
|
|
|
108c2a |
libmultipath/structs.h | 7 +++++
|
|
|
108c2a |
libmultipath/util.c | 10 +++++++
|
|
|
108c2a |
libmultipath/util.h | 1 +
|
|
|
108c2a |
multipath/multipath.conf.5 | 7 +++--
|
|
|
108c2a |
7 files changed, 84 insertions(+), 2 deletions(-)
|
|
|
108c2a |
|
|
|
108c2a |
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
|
|
108c2a |
index 6cad0468..287289f7 100644
|
|
|
108c2a |
--- a/libmultipath/configure.c
|
|
|
108c2a |
+++ b/libmultipath/configure.c
|
|
|
108c2a |
@@ -1102,6 +1102,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
|
|
108c2a |
uint64_t *size_mismatch_seen;
|
|
|
108c2a |
bool map_processed = false;
|
|
|
108c2a |
bool no_daemon = false;
|
|
|
108c2a |
+ struct multipath * cmpp;
|
|
|
108c2a |
|
|
|
108c2a |
/* ignore refwwid if it's empty */
|
|
|
108c2a |
if (refwwid && !strlen(refwwid))
|
|
|
108c2a |
@@ -1197,6 +1198,9 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
|
|
108c2a |
}
|
|
|
108c2a |
verify_paths(mpp, vecs);
|
|
|
108c2a |
|
|
|
108c2a |
+ cmpp = find_mp_by_wwid(curmp, mpp->wwid);
|
|
|
108c2a |
+ if (cmpp)
|
|
|
108c2a |
+ mpp->queue_mode = cmpp->queue_mode;
|
|
|
108c2a |
params[0] = '\0';
|
|
|
108c2a |
if (setup_map(mpp, params, PARAMS_SIZE, vecs)) {
|
|
|
108c2a |
remove_map(mpp, vecs, 0);
|
|
|
108c2a |
diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c
|
|
|
108c2a |
index b856a07f..b9c4dabc 100644
|
|
|
108c2a |
--- a/libmultipath/dmparser.c
|
|
|
108c2a |
+++ b/libmultipath/dmparser.c
|
|
|
108c2a |
@@ -164,6 +164,8 @@ int disassemble_map(vector pathvec, char *params, struct multipath *mpp,
|
|
|
108c2a |
|
|
|
108c2a |
FREE(word);
|
|
|
108c2a |
}
|
|
|
108c2a |
+ mpp->queue_mode = strstr(mpp->features, "queue_mode bio") ?
|
|
|
108c2a |
+ QUEUE_MODE_BIO : QUEUE_MODE_RQ;
|
|
|
108c2a |
|
|
|
108c2a |
/*
|
|
|
108c2a |
* hwhandler
|
|
|
108c2a |
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
|
|
108c2a |
index be79902f..3f119dd9 100644
|
|
|
108c2a |
--- a/libmultipath/propsel.c
|
|
|
108c2a |
+++ b/libmultipath/propsel.c
|
|
|
108c2a |
@@ -26,6 +26,7 @@
|
|
|
108c2a |
#include "propsel.h"
|
|
|
108c2a |
#include <inttypes.h>
|
|
|
108c2a |
#include <libudev.h>
|
|
|
108c2a |
+#include <ctype.h>
|
|
|
108c2a |
|
|
|
108c2a |
pgpolicyfn *pgpolicies[] = {
|
|
|
108c2a |
NULL,
|
|
|
108c2a |
@@ -413,6 +414,59 @@ void reconcile_features_with_options(const char *id, char **features, int* no_pa
|
|
|
108c2a |
}
|
|
|
108c2a |
}
|
|
|
108c2a |
|
|
|
108c2a |
+static void reconcile_features_with_queue_mode(struct multipath *mp)
|
|
|
108c2a |
+{
|
|
|
108c2a |
+ char *space = NULL, *val = NULL, *mode_str = NULL, *feat;
|
|
|
108c2a |
+ int features_mode = QUEUE_MODE_UNDEF;
|
|
|
108c2a |
+
|
|
|
108c2a |
+ if (!mp->features)
|
|
|
108c2a |
+ return;
|
|
|
108c2a |
+
|
|
|
108c2a |
+ pthread_cleanup_push(cleanup_free_ptr, &space);
|
|
|
108c2a |
+ pthread_cleanup_push(cleanup_free_ptr, &val;;
|
|
|
108c2a |
+ pthread_cleanup_push(cleanup_free_ptr, &mode_str);
|
|
|
108c2a |
+
|
|
|
108c2a |
+ if (!(feat = strstr(mp->features, "queue_mode")) ||
|
|
|
108c2a |
+ feat == mp->features || !isspace(*(feat - 1)) ||
|
|
|
108c2a |
+ sscanf(feat, "queue_mode%m[ \f\n\r\t\v]%ms", &space, &val) != 2)
|
|
|
108c2a |
+ goto sync_mode;
|
|
|
108c2a |
+ if (asprintf(&mode_str, "queue_mode%s%s", space, val) < 0) {
|
|
|
108c2a |
+ condlog(1, "failed to allocate space for queue_mode feature string");
|
|
|
108c2a |
+ mode_str = NULL; /* value undefined on failure */
|
|
|
108c2a |
+ goto exit;
|
|
|
108c2a |
+ }
|
|
|
108c2a |
+
|
|
|
108c2a |
+ if (!strcmp(val, "rq") || !strcmp(val, "mq"))
|
|
|
108c2a |
+ features_mode = QUEUE_MODE_RQ;
|
|
|
108c2a |
+ else if (!strcmp(val, "bio"))
|
|
|
108c2a |
+ features_mode = QUEUE_MODE_BIO;
|
|
|
108c2a |
+ if (features_mode == QUEUE_MODE_UNDEF) {
|
|
|
108c2a |
+ condlog(2, "%s: ignoring invalid feature '%s'",
|
|
|
108c2a |
+ mp->alias, mode_str);
|
|
|
108c2a |
+ goto sync_mode;
|
|
|
108c2a |
+ }
|
|
|
108c2a |
+
|
|
|
108c2a |
+ if (mp->queue_mode == QUEUE_MODE_UNDEF)
|
|
|
108c2a |
+ mp->queue_mode = features_mode;
|
|
|
108c2a |
+ if (mp->queue_mode == features_mode)
|
|
|
108c2a |
+ goto exit;
|
|
|
108c2a |
+
|
|
|
108c2a |
+ condlog(2,
|
|
|
108c2a |
+ "%s: ignoring feature '%s' because queue_mode is set to '%s'",
|
|
|
108c2a |
+ mp->alias, mode_str,
|
|
|
108c2a |
+ (mp->queue_mode == QUEUE_MODE_RQ)? "rq" : "bio");
|
|
|
108c2a |
+
|
|
|
108c2a |
+sync_mode:
|
|
|
108c2a |
+ if (mode_str)
|
|
|
108c2a |
+ remove_feature(&mp->features, mode_str);
|
|
|
108c2a |
+ if (mp->queue_mode == QUEUE_MODE_BIO)
|
|
|
108c2a |
+ add_feature(&mp->features, "queue_mode bio");
|
|
|
108c2a |
+exit:
|
|
|
108c2a |
+ pthread_cleanup_pop(1);
|
|
|
108c2a |
+ pthread_cleanup_pop(1);
|
|
|
108c2a |
+ pthread_cleanup_pop(1);
|
|
|
108c2a |
+}
|
|
|
108c2a |
+
|
|
|
108c2a |
int select_features(struct config *conf, struct multipath *mp)
|
|
|
108c2a |
{
|
|
|
108c2a |
const char *origin;
|
|
|
108c2a |
@@ -428,6 +482,7 @@ out:
|
|
|
108c2a |
reconcile_features_with_options(mp->alias, &mp->features,
|
|
|
108c2a |
&mp->no_path_retry,
|
|
|
108c2a |
&mp->retain_hwhandler);
|
|
|
108c2a |
+ reconcile_features_with_queue_mode(mp);
|
|
|
108c2a |
condlog(3, "%s: features = \"%s\" %s", mp->alias, mp->features, origin);
|
|
|
108c2a |
return 0;
|
|
|
108c2a |
}
|
|
|
108c2a |
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
|
|
108c2a |
index 3ed5cfc1..9a404da7 100644
|
|
|
108c2a |
--- a/libmultipath/structs.h
|
|
|
108c2a |
+++ b/libmultipath/structs.h
|
|
|
108c2a |
@@ -187,6 +187,12 @@ enum max_sectors_kb_states {
|
|
|
108c2a |
MAX_SECTORS_KB_MIN = 4, /* can't be smaller than page size */
|
|
|
108c2a |
};
|
|
|
108c2a |
|
|
|
108c2a |
+enum queue_mode_states {
|
|
|
108c2a |
+ QUEUE_MODE_UNDEF = 0,
|
|
|
108c2a |
+ QUEUE_MODE_BIO,
|
|
|
108c2a |
+ QUEUE_MODE_RQ,
|
|
|
108c2a |
+};
|
|
|
108c2a |
+
|
|
|
108c2a |
enum scsi_protocol {
|
|
|
108c2a |
SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
|
|
|
108c2a |
SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
|
|
|
108c2a |
@@ -397,6 +403,7 @@ struct multipath {
|
|
|
108c2a |
int needs_paths_uevent;
|
|
|
108c2a |
int ghost_delay;
|
|
|
108c2a |
int ghost_delay_tick;
|
|
|
108c2a |
+ int queue_mode;
|
|
|
108c2a |
uid_t uid;
|
|
|
108c2a |
gid_t gid;
|
|
|
108c2a |
mode_t mode;
|
|
|
108c2a |
diff --git a/libmultipath/util.c b/libmultipath/util.c
|
|
|
108c2a |
index dd30a46e..e04d20ab 100644
|
|
|
108c2a |
--- a/libmultipath/util.c
|
|
|
108c2a |
+++ b/libmultipath/util.c
|
|
|
108c2a |
@@ -465,6 +465,16 @@ void free_scandir_result(struct scandir_result *res)
|
|
|
108c2a |
FREE(res->di);
|
|
|
108c2a |
}
|
|
|
108c2a |
|
|
|
108c2a |
+void cleanup_free_ptr(void *arg)
|
|
|
108c2a |
+{
|
|
|
108c2a |
+ void **p = arg;
|
|
|
108c2a |
+
|
|
|
108c2a |
+ if (p && *p) {
|
|
|
108c2a |
+ free(*p);
|
|
|
108c2a |
+ *p = NULL;
|
|
|
108c2a |
+ }
|
|
|
108c2a |
+}
|
|
|
108c2a |
+
|
|
|
108c2a |
void close_fd(void *arg)
|
|
|
108c2a |
{
|
|
|
108c2a |
close((long)arg);
|
|
|
108c2a |
diff --git a/libmultipath/util.h b/libmultipath/util.h
|
|
|
108c2a |
index ce277680..f898c829 100644
|
|
|
108c2a |
--- a/libmultipath/util.h
|
|
|
108c2a |
+++ b/libmultipath/util.h
|
|
|
108c2a |
@@ -44,6 +44,7 @@ void set_max_fds(rlim_t max_fds);
|
|
|
108c2a |
pthread_cleanup_push(((void (*)(void *))&f), (arg))
|
|
|
108c2a |
|
|
|
108c2a |
void close_fd(void *arg);
|
|
|
108c2a |
+void cleanup_free_ptr(void *arg);
|
|
|
108c2a |
void cleanup_mutex(void *arg);
|
|
|
108c2a |
|
|
|
108c2a |
struct scandir_result {
|
|
|
108c2a |
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
|
|
108c2a |
index 8e418372..61d2712b 100644
|
|
|
108c2a |
--- a/multipath/multipath.conf.5
|
|
|
108c2a |
+++ b/multipath/multipath.conf.5
|
|
|
108c2a |
@@ -458,8 +458,11 @@ precedence. See KNOWN ISSUES.
|
|
|
108c2a |
<mode> can be \fIbio\fR, \fIrq\fR or \fImq\fR, which corresponds to
|
|
|
108c2a |
bio-based, request-based, and block-multiqueue (blk-mq) request-based,
|
|
|
108c2a |
respectively.
|
|
|
108c2a |
-The default depends on the kernel parameter \fBdm_mod.use_blk_mq\fR. It is
|
|
|
108c2a |
-\fImq\fR if the latter is set, and \fIrq\fR otherwise.
|
|
|
108c2a |
+Before kernel 4.20 The default depends on the kernel parameter
|
|
|
108c2a |
+\fBdm_mod.use_blk_mq\fR. It is \fImq\fR if the latter is set, and \fIrq\fR
|
|
|
108c2a |
+otherwise. Since kernel 4.20, \fIrq\fR and \fImq\fR both correspond to
|
|
|
108c2a |
+block-multiqueue. Once a multipath device has been created, its queue_mode
|
|
|
108c2a |
+cannot be changed.
|
|
|
108c2a |
.TP
|
|
|
108c2a |
The default is: \fB<unset>\fR
|
|
|
108c2a |
.RE
|