From patchwork Fri Oct 7 17:35:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001284 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2575CC4332F for ; Fri, 7 Oct 2022 17:35:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164155; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=BIgMnY49y+TR0PRm+E9Qfr9Tryex06phIzK7ud5E85k=; b=CmG62iAUFNnMsHHiGmTifUnk59Lq7jlk4RQfQAzDgH60x44n3YfkwkD1NBax/EcK+KS+Cv 4Na8ISouL7npUXA86dT2zFaXEeQWoNSbt7ZtS9r9YLZ87KUuO8yGIBLrn4/EOkN/sxvVYE 4El/R+PM05edcarcjBEyxMgTf35TwWQ= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-561-YV2EWiZSONmxt0ya7SrLvw-1; Fri, 07 Oct 2022 13:35:52 -0400 X-MC-Unique: YV2EWiZSONmxt0ya7SrLvw-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E6322855309; Fri, 7 Oct 2022 17:35:50 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id C879A535D20; Fri, 7 Oct 2022 17:35:49 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 809B51946A51; Fri, 7 Oct 2022 17:35:49 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 185421946595 for ; Fri, 7 Oct 2022 17:35:48 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 0D85220290AE; Fri, 7 Oct 2022 17:35:48 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E0CFE20290A2; Fri, 7 Oct 2022 17:35:47 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZkk2006758; Fri, 7 Oct 2022 12:35:46 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZkTK006757; Fri, 7 Oct 2022 12:35:46 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:37 -0500 Message-Id: <1665164144-6716-2-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Subject: [dm-devel] [PATCH 1/8] libmultipath: cleanup remove_feature X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com remove_feature() didn't correctly handle feature strings that used whitespace other than spaces, which the kernel allows. It also didn't check if the feature string to be removed was part of a larger feature token. Finally, it did a lot of unnecessary work. By failing if the feature string to be removed contains leading or trailing whitespace, the function can be significanly simplified. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- libmultipath/structs.c | 82 +++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 53 deletions(-) diff --git a/libmultipath/structs.c b/libmultipath/structs.c index 49621cb3..1f9945e0 100644 --- a/libmultipath/structs.c +++ b/libmultipath/structs.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "checkers.h" #include "vector.h" @@ -663,7 +664,7 @@ int add_feature(char **f, const char *n) int remove_feature(char **f, const char *o) { - int c = 0, d, l; + int c = 0, d; char *e, *p, *n; const char *q; @@ -674,33 +675,35 @@ int remove_feature(char **f, const char *o) if (!o || *o == '\0') return 0; - /* Check if not present */ - if (!strstr(*f, o)) + d = strlen(o); + if (isspace(*o) || isspace(*(o + d - 1))) { + condlog(0, "internal error: feature \"%s\" has leading or trailing spaces", o); + return 1; + } + + /* Check if present and not part of a larger feature token*/ + p = *f + 1; /* the size must be at the start of the features string */ + while ((p = strstr(p, o)) != NULL) { + if (isspace(*(p - 1)) && + (isspace(*(p + d)) || *(p + d) == '\0')) + break; + p += d; + } + if (!p) return 0; /* Get feature count */ c = strtoul(*f, &e, 10); - if (*f == e) - /* parse error */ + if (*f == e || !isspace(*e)) { + condlog(0, "parse error in feature string \"%s\"", *f); return 1; - - /* Normalize features */ - while (*o == ' ') { - o++; } - /* Just spaces, return */ - if (*o == '\0') - return 0; - q = o + strlen(o); - while (*q == ' ') - q--; - d = (int)(q - o); /* Update feature count */ c--; q = o; - while (q[0] != '\0') { - if (q[0] == ' ' && q[1] != ' ' && q[1] != '\0') + while (*q != '\0') { + if (isspace(*q) && !isspace(*(q + 1)) && *(q + 1) != '\0') c--; q++; } @@ -714,15 +717,8 @@ int remove_feature(char **f, const char *o) goto out; } - /* Search feature to be removed */ - e = strstr(*f, o); - if (!e) - /* Not found, return */ - return 0; - /* Update feature count space */ - l = strlen(*f) - d; - n = malloc(l + 1); + n = malloc(strlen(*f) - d + 1); if (!n) return 1; @@ -732,36 +728,16 @@ int remove_feature(char **f, const char *o) * Copy existing features up to the feature * about to be removed */ - p = strchr(*f, ' '); - if (!p) { - /* Internal error, feature string inconsistent */ - free(n); - return 1; - } - while (*p == ' ') - p++; - p--; - if (e != p) { - do { - e--; - d++; - } while (*e == ' '); - e++; d--; - strncat(n, p, (size_t)(e - p)); - p += (size_t)(e - p); - } + strncat(n, e, (size_t)(p - e)); /* Skip feature to be removed */ p += d; - /* Copy remaining features */ - if (strlen(p)) { - while (*p == ' ') - p++; - if (strlen(p)) { - p--; - strcat(n, p); - } - } + while (isspace(*p)) + p++; + if (*p != '\0') + strcat(n, p); + else + strchop(n); out: free(*f); From patchwork Fri Oct 7 17:35:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001283 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C781BC433FE for ; Fri, 7 Oct 2022 17:35:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164153; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=ZxjdTvu55i6p/X236qxgMXHAMHrRh/kUpW4BxcVWAo0=; b=fKgzsTu6NeYBhtRSP0lLnRvWj+SUHcQQ3FBAzspNZTtwcCmil/ZIEvCLq95lwwQJAGS/p2 M12F5UGhg0BeuLLha0ThcUsL1eRAj4oi+qm+W3jc0//C1rbEhuz6VDNEs0eGKAnCochnCf lr7B63rhTIXFvprgouELYbcPpLJEsno= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-562-cwFf3BTBN4CsReD6j6VyWw-1; Fri, 07 Oct 2022 13:35:52 -0400 X-MC-Unique: cwFf3BTBN4CsReD6j6VyWw-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E5A9C3C0E219; Fri, 7 Oct 2022 17:35:50 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9DB7020290A2; Fri, 7 Oct 2022 17:35:50 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 6CFCD1946A66; Fri, 7 Oct 2022 17:35:50 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 5BEEA1946595 for ; Fri, 7 Oct 2022 17:35:49 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 4CC572166BDE; Fri, 7 Oct 2022 17:35:49 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2F5062166B4D; Fri, 7 Oct 2022 17:35:49 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZlVV006764; Fri, 7 Oct 2022 12:35:47 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZls2006761; Fri, 7 Oct 2022 12:35:47 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:38 -0500 Message-Id: <1665164144-6716-3-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 Subject: [dm-devel] [PATCH 2/8] libmultipath: cleanup add_feature X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com add_feature() didn't correctly handle feature strings that used whitespace other than spaces, which the kernel allows. It also didn't allow adding features with multiple tokens. When it looked to see if the feature string to be added already existed, it didn't check if the match was part of a larger token. Finally, it did unnecessary work. By using asprintf() to create the string, the function can be signifcantly simplified. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- libmultipath/structs.c | 49 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/libmultipath/structs.c b/libmultipath/structs.c index 1f9945e0..0f16c071 100644 --- a/libmultipath/structs.c +++ b/libmultipath/structs.c @@ -602,23 +602,33 @@ int add_feature(char **f, const char *n) { int c = 0, d, l; char *e, *t; + const char *p; if (!f) return 1; /* Nothing to do */ - if (!n || *n == '0') + if (!n || *n == '\0') return 0; - if (strchr(n, ' ') != NULL) { - condlog(0, "internal error: feature \"%s\" contains spaces", n); + l = strlen(n); + if (isspace(*n) || isspace(*(n + l - 1))) { + condlog(0, "internal error: feature \"%s\" has leading or trailing spaces", n); return 1; } + p = n; + d = 1; + while (*p != '\0') { + if (isspace(*p) && !isspace(*(p + 1)) && *(p + 1) != '\0') + d++; + p++; + } + /* default feature is null */ if(!*f) { - l = asprintf(&t, "1 %s", n); + l = asprintf(&t, "%0d %s", d, n); if(l == -1) return 1; @@ -627,35 +637,24 @@ int add_feature(char **f, const char *n) } /* Check if feature is already present */ - if (strstr(*f, n)) - return 0; + e = *f; + while ((e = strstr(e, n)) != NULL) { + if (isspace(*(e - 1)) && + (isspace(*(e + l)) || *(e + l) == '\0')) + return 0; + e += l; + } /* Get feature count */ c = strtoul(*f, &e, 10); - if (*f == e || (*e != ' ' && *e != '\0')) { + if (*f == e || (!isspace(*e) && *e != '\0')) { condlog(0, "parse error in feature string \"%s\"", *f); return 1; } - - /* Add 1 digit and 1 space */ - l = strlen(e) + strlen(n) + 2; - - c++; - /* Check if we need more digits for feature count */ - for (d = c; d >= 10; d /= 10) - l++; - - t = calloc(1, l + 1); - if (!t) + c += d; + if (asprintf(&t, "%0d%s %s", c, e, n) < 0) return 1; - /* e: old feature string with leading space, or "" */ - if (*e == ' ') - while (*(e + 1) == ' ') - e++; - - snprintf(t, l + 1, "%0d%s %s", c, e, n); - free(*f); *f = t; From patchwork Fri Oct 7 17:35:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001285 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1D8A4C43217 for ; Fri, 7 Oct 2022 17:35:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164157; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=2Cu1IFmtDqMBH089pGnr1s6DBcR+Nrhx8BfE1iCyuF0=; b=ilgGc/nlcJlLlHcEe3wvISzs9zvrIsot3Iu0Iwhlj/a8/Uf5vUnYD72XB6ZajNK7jWx6Q5 MyCD4qsTjrj1Ja65zylI/PDlhNAZEq88iRi/QteDbEmnKecrpYk8HPZsWtVUNFQsVSlPJB pvY/y9NYf9GP3SiSqYFlhC5aGNTMR3s= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-278-iBQLCJ1jNQiZE8ZjPyN65A-1; Fri, 07 Oct 2022 13:35:53 -0400 X-MC-Unique: iBQLCJ1jNQiZE8ZjPyN65A-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id EC1F01C08982; Fri, 7 Oct 2022 17:35:51 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id DB03553594D; Fri, 7 Oct 2022 17:35:51 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id B57301946A49; Fri, 7 Oct 2022 17:35:51 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 5E6B51946595 for ; Fri, 7 Oct 2022 17:35:50 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 42F2020290A2; Fri, 7 Oct 2022 17:35:50 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2476920290AE; Fri, 7 Oct 2022 17:35:50 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZnbc006768; Fri, 7 Oct 2022 12:35:49 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZm03006767; Fri, 7 Oct 2022 12:35:48 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:39 -0500 Message-Id: <1665164144-6716-4-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Subject: [dm-devel] [PATCH 3/8] multipath tests: tests for adding and removing features X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Signed-off-by: Benjamin Marzinski --- tests/Makefile | 2 +- tests/features.c | 319 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 tests/features.c diff --git a/tests/Makefile b/tests/Makefile index 109ea75b..ccdfbd15 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -16,7 +16,7 @@ CFLAGS += $(BIN_CFLAGS) -Wno-unused-parameter $(W_MISSING_INITIALIZERS) LIBDEPS += -L. -L $(mpathutildir) -L$(mpathcmddir) -lmultipath -lmpathutil -lmpathcmd -lcmocka TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \ - alias directio valid devt mpathvalid strbuf sysfs + alias directio valid devt mpathvalid strbuf sysfs features HELPERS := test-lib.o test-log.o .SILENT: $(TESTS:%=%.o) diff --git a/tests/features.c b/tests/features.c new file mode 100644 index 00000000..4d8f0860 --- /dev/null +++ b/tests/features.c @@ -0,0 +1,319 @@ +#include +#include +#include +#include + +#include "structs.h" +#include "globals.c" + +static void test_af_null_features_ptr(void **state) +{ + assert_int_equal(add_feature(NULL, "test"), 1); +} + +static void af_helper(const char *features_start, const char *addition, + const char *features_end, int result) +{ + char *f = NULL, *orig = NULL; + + if (features_start) { + f = strdup(features_start); + assert_non_null(f); + orig = f; + } + assert_int_equal(add_feature(&f, addition), result); + if (result != 0 || features_end == NULL) + assert_ptr_equal(orig, f); + else + assert_string_equal(f, features_end); + free(f); +} + +static void test_af_null_addition1(void **state) +{ + af_helper("0", NULL, NULL, 0); +} + +static void test_af_null_addition2(void **state) +{ + af_helper("1 queue_if_no_path", NULL, NULL, 0); +} + +static void test_af_empty_addition(void **state) +{ + af_helper("2 pg_init_retries 5", "", NULL, 0); +} + +static void test_af_invalid_addition1(void **state) +{ + af_helper("2 pg_init_retries 5", " ", NULL, 1); +} + +static void test_af_invalid_addition2(void **state) +{ + af_helper("2 pg_init_retries 5", "\tbad", NULL, 1); +} + +static void test_af_invalid_addition3(void **state) +{ + af_helper("2 pg_init_retries 5", "bad ", NULL, 1); +} + +static void test_af_invalid_addition4(void **state) +{ + af_helper("2 pg_init_retries 5", " bad ", NULL, 1); +} + +static void test_af_null_features1(void **state) +{ + af_helper(NULL, "test", "1 test", 0); +} + +static void test_af_null_features2(void **state) +{ + af_helper(NULL, "test\t more", "2 test\t more", 0); +} + +static void test_af_null_features3(void **state) +{ + af_helper(NULL, "test\neven\tmore", "3 test\neven\tmore", 0); +} + +static void test_af_already_exists1(void **state) +{ + af_helper("4 this is a test", "test", NULL, 0); +} + +static void test_af_already_exists2(void **state) +{ + af_helper("5 contest testy intestine test retest", "test", NULL, 0); +} + +static void test_af_almost_exists(void **state) +{ + af_helper("3 contest testy intestine", "test", + "4 contest testy intestine test", 0); +} + +static void test_af_bad_features1(void **state) +{ + af_helper("bad", "test", NULL, 1); +} + +static void test_af_bad_features2(void **state) +{ + af_helper("1bad", "test", NULL, 1); +} + +static void test_af_add1(void **state) +{ + af_helper("0", "test", "1 test", 0); +} + +static void test_af_add2(void **state) +{ + af_helper("0", "this is a test", "4 this is a test", 0); +} + +static void test_af_add3(void **state) +{ + af_helper("1 features", "more values", "3 features more values", 0); +} + +static void test_af_add4(void **state) +{ + af_helper("2 one\ttwo", "three\t four", "4 one\ttwo three\t four", 0); +} + +static int test_add_features(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_af_null_features_ptr), + cmocka_unit_test(test_af_null_addition1), + cmocka_unit_test(test_af_null_addition2), + cmocka_unit_test(test_af_empty_addition), + cmocka_unit_test(test_af_invalid_addition1), + cmocka_unit_test(test_af_invalid_addition2), + cmocka_unit_test(test_af_invalid_addition3), + cmocka_unit_test(test_af_invalid_addition4), + cmocka_unit_test(test_af_null_features1), + cmocka_unit_test(test_af_null_features2), + cmocka_unit_test(test_af_null_features3), + cmocka_unit_test(test_af_already_exists1), + cmocka_unit_test(test_af_already_exists2), + cmocka_unit_test(test_af_almost_exists), + cmocka_unit_test(test_af_bad_features1), + cmocka_unit_test(test_af_bad_features2), + cmocka_unit_test(test_af_add1), + cmocka_unit_test(test_af_add2), + cmocka_unit_test(test_af_add3), + cmocka_unit_test(test_af_add4), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} + +static void test_rf_null_features_ptr(void **state) +{ + assert_int_equal(remove_feature(NULL, "test"), 1); +} + +static void test_rf_null_features(void **state) +{ + char *f = NULL; + assert_int_equal(remove_feature(&f, "test"), 1); +} + +static void rf_helper(const char *features_start, const char *removal, + const char *features_end, int result) +{ + char *f = strdup(features_start); + char *orig = f; + + assert_non_null(f); + assert_int_equal(remove_feature(&f, removal), result); + if (result != 0 || features_end == NULL) + assert_ptr_equal(orig, f); + else + assert_string_equal(f, features_end); + free(f); +} + +static void test_rf_null_removal(void **state) +{ + rf_helper("1 feature", NULL, NULL, 0); +} + +static void test_rf_empty_removal(void **state) +{ + rf_helper("1 feature", "", NULL, 0); +} + +static void test_rf_invalid_removal1(void **state) +{ + rf_helper("1 feature", " ", NULL, 1); +} + +static void test_rf_invalid_removal2(void **state) +{ + rf_helper("1 feature", " bad", NULL, 1); +} + +static void test_rf_invalid_removal3(void **state) +{ + rf_helper("1 feature", "bad\n", NULL, 1); +} + +static void test_rf_invalid_removal4(void **state) +{ + rf_helper("1 feature", "\tbad \n", NULL, 1); +} + +static void test_rf_bad_features1(void **state) +{ + rf_helper("invalid feature test string", "test", NULL, 1); +} + +static void test_rf_bad_features2(void **state) +{ + rf_helper("2no space test", "test", NULL, 1); +} + +static void test_rf_missing_removal1(void **state) +{ + rf_helper("0", "test", NULL, 0); +} + +static void test_rf_missing_removal2(void **state) +{ + rf_helper("1 detest", "test", NULL, 0); +} + +static void test_rf_missing_removal3(void **state) +{ + rf_helper("4 testing one two three", "test", NULL, 0); +} + +static void test_rf_missing_removal4(void **state) +{ + rf_helper("1 contestant", "test", NULL, 0); +} + +static void test_rf_missing_removal5(void **state) +{ + rf_helper("3 testament protest detestable", "test", NULL, 0); +} + +static void test_rf_remove_all_features1(void **state) +{ + rf_helper("1 test", "test", "0", 0); +} + +static void test_rf_remove_all_features2(void **state) +{ + rf_helper("2 another\t test", "another\t test", "0", 0); +} + +static void test_rf_remove1(void **state) +{ + rf_helper("2 feature1 feature2", "feature2", "1 feature1", 0); +} + +static void test_rf_remove2(void **state) +{ + rf_helper("2 feature1 feature2", "feature1", "1 feature2", 0); +} + +static void test_rf_remove3(void **state) +{ + rf_helper("3 test1 test\ttest2", "test", "2 test1 test2", 0); +} + +static void test_rf_remove4(void **state) +{ + rf_helper("4 this\t is a test", "is a", "2 this\t test", 0); +} + +static void test_rf_remove5(void **state) +{ + rf_helper("3 one more test", "more test", "1 one", 0); +} + +static int test_remove_features(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_rf_null_features_ptr), + cmocka_unit_test(test_rf_null_features), + cmocka_unit_test(test_rf_null_removal), + cmocka_unit_test(test_rf_empty_removal), + cmocka_unit_test(test_rf_invalid_removal1), + cmocka_unit_test(test_rf_invalid_removal2), + cmocka_unit_test(test_rf_invalid_removal3), + cmocka_unit_test(test_rf_invalid_removal4), + cmocka_unit_test(test_rf_bad_features1), + cmocka_unit_test(test_rf_bad_features2), + cmocka_unit_test(test_rf_missing_removal1), + cmocka_unit_test(test_rf_missing_removal2), + cmocka_unit_test(test_rf_missing_removal3), + cmocka_unit_test(test_rf_missing_removal4), + cmocka_unit_test(test_rf_missing_removal5), + cmocka_unit_test(test_rf_remove_all_features1), + cmocka_unit_test(test_rf_remove_all_features2), + cmocka_unit_test(test_rf_remove1), + cmocka_unit_test(test_rf_remove2), + cmocka_unit_test(test_rf_remove3), + cmocka_unit_test(test_rf_remove4), + cmocka_unit_test(test_rf_remove5), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} + +int main(void) +{ + int ret = 0; + + init_test_verbosity(-1); + ret += test_add_features(); + ret += test_remove_features(); + + return ret; +} From patchwork Fri Oct 7 17:35:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001291 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 40834C433FE for ; Fri, 7 Oct 2022 17:37:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164224; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=W+pNuiMhcOUivhVDFmYBfQ8eK6tY5cP/cEMYcOcJJOY=; b=PT0Gyozvj21M77fda8hzzqY2JZ8LosZJxJeOZGWQ0x9ZfhhS92k1KmgYtlu/8oDZm5ytdX RL6CmZD9lfJnd1c4mrp4wIjAyXnAU0r+hgR7/GVCCl4O2tLBIvHlpRR2R/m0FvuKbe24Vo Nmq27c52wLBNDDqyjJFKMC3mVl1Xl30= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-127-QSUDmw7rMbWKasZuRES45Q-1; Fri, 07 Oct 2022 13:36:02 -0400 X-MC-Unique: QSUDmw7rMbWKasZuRES45Q-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 845F186EB20; Fri, 7 Oct 2022 17:35:58 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 740ED145BEE3; Fri, 7 Oct 2022 17:35:58 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 659B21946A49; Fri, 7 Oct 2022 17:35:58 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 095C91946595 for ; Fri, 7 Oct 2022 17:35:57 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id F2BC2AB584; Fri, 7 Oct 2022 17:35:56 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 171BDAB5A9; Fri, 7 Oct 2022 17:35:51 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZnDo006772; Fri, 7 Oct 2022 12:35:50 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZnJN006771; Fri, 7 Oct 2022 12:35:49 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:40 -0500 Message-Id: <1665164144-6716-5-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.5 Subject: [dm-devel] [PATCH 4/8] libmultipath: fix queue_mode feature handling X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com device-mapper is not able to change the queue_mode on a table reload. Make sure that when multipath sets up the map, both on regular reloads and reconfigures, it keeps the queue_mode the same. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- libmultipath/configure.c | 4 +++ libmultipath/dmparser.c | 2 ++ libmultipath/propsel.c | 55 ++++++++++++++++++++++++++++++++++++++ libmultipath/structs.h | 7 +++++ multipath/multipath.conf.5 | 7 +++-- 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/libmultipath/configure.c b/libmultipath/configure.c index 8af7cd79..41641e30 100644 --- a/libmultipath/configure.c +++ b/libmultipath/configure.c @@ -1075,6 +1075,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, struct config *conf = NULL; int allow_queueing; struct bitfield *size_mismatch_seen; + struct multipath * cmpp; /* ignore refwwid if it's empty */ if (refwwid && !strlen(refwwid)) @@ -1184,6 +1185,9 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, } verify_paths(mpp); + cmpp = find_mp_by_wwid(curmp, mpp->wwid); + if (cmpp) + mpp->queue_mode = cmpp->queue_mode; if (setup_map(mpp, ¶ms, vecs)) { remove_map(mpp, vecs->pathvec, NULL); continue; diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c index 50d13c08..3b37a926 100644 --- a/libmultipath/dmparser.c +++ b/libmultipath/dmparser.c @@ -151,6 +151,8 @@ int disassemble_map(const struct _vector *pathvec, free(word); } + mpp->queue_mode = strstr(mpp->features, "queue_mode bio") ? + QUEUE_MODE_BIO : QUEUE_MODE_RQ; /* * hwhandler diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c index 98e3aad1..d4f19897 100644 --- a/libmultipath/propsel.c +++ b/libmultipath/propsel.c @@ -26,6 +26,7 @@ #include "strbuf.h" #include #include +#include pgpolicyfn *pgpolicies[] = { NULL, @@ -413,6 +414,59 @@ void reconcile_features_with_options(const char *id, char **features, int* no_pa } } +static void reconcile_features_with_queue_mode(struct multipath *mp) +{ + char *space = NULL, *val = NULL, *mode_str = NULL, *feat; + int features_mode = QUEUE_MODE_UNDEF; + + if (!mp->features) + return; + + pthread_cleanup_push(cleanup_free_ptr, &space); + pthread_cleanup_push(cleanup_free_ptr, &val); + pthread_cleanup_push(cleanup_free_ptr, &mode_str); + + if (!(feat = strstr(mp->features, "queue_mode")) || + feat == mp->features || !isspace(*(feat - 1)) || + sscanf(feat, "queue_mode%m[ \f\n\r\t\v]%ms", &space, &val) != 2) + goto sync_mode; + if (asprintf(&mode_str, "queue_mode%s%s", space, val) < 0) { + condlog(1, "failed to allocate space for queue_mode feature string"); + mode_str = NULL; /* value undefined on failure */ + goto exit; + } + + if (!strcmp(val, "rq") || !strcmp(val, "mq")) + features_mode = QUEUE_MODE_RQ; + else if (!strcmp(val, "bio")) + features_mode = QUEUE_MODE_BIO; + if (features_mode == QUEUE_MODE_UNDEF) { + condlog(2, "%s: ignoring invalid feature '%s'", + mp->alias, mode_str); + goto sync_mode; + } + + if (mp->queue_mode == QUEUE_MODE_UNDEF) + mp->queue_mode = features_mode; + if (mp->queue_mode == features_mode) + goto exit; + + condlog(2, + "%s: ignoring feature '%s' because queue_mode is set to '%s'", + mp->alias, mode_str, + (mp->queue_mode == QUEUE_MODE_RQ)? "rq" : "bio"); + +sync_mode: + if (mode_str) + remove_feature(&mp->features, mode_str); + if (mp->queue_mode == QUEUE_MODE_BIO) + add_feature(&mp->features, "queue_mode bio"); +exit: + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); +} + int select_features(struct config *conf, struct multipath *mp) { const char *origin; @@ -428,6 +482,7 @@ out: reconcile_features_with_options(mp->alias, &mp->features, &mp->no_path_retry, &mp->retain_hwhandler); + reconcile_features_with_queue_mode(mp); condlog(3, "%s: features = \"%s\" %s", mp->alias, mp->features, origin); return 0; } diff --git a/libmultipath/structs.h b/libmultipath/structs.h index 5a713d46..129bdf0e 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -170,6 +170,12 @@ enum max_sectors_kb_states { MAX_SECTORS_KB_MIN = 4, /* can't be smaller than page size */ }; +enum queue_mode_states { + QUEUE_MODE_UNDEF = 0, + QUEUE_MODE_BIO, + QUEUE_MODE_RQ, +}; + enum scsi_protocol { SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ @@ -396,6 +402,7 @@ struct multipath { int needs_paths_uevent; int ghost_delay; int ghost_delay_tick; + int queue_mode; uid_t uid; gid_t gid; mode_t mode; diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 index e098d555..46a4126c 100644 --- a/multipath/multipath.conf.5 +++ b/multipath/multipath.conf.5 @@ -459,8 +459,11 @@ precedence. See KNOWN ISSUES. can be \fIbio\fR, \fIrq\fR or \fImq\fR, which corresponds to bio-based, request-based, and block-multiqueue (blk-mq) request-based, respectively. -The default depends on the kernel parameter \fBdm_mod.use_blk_mq\fR. It is -\fImq\fR if the latter is set, and \fIrq\fR otherwise. +Before kernel 4.20 The default depends on the kernel parameter +\fBdm_mod.use_blk_mq\fR. It is \fImq\fR if the latter is set, and \fIrq\fR +otherwise. Since kernel 4.20, \fIrq\fR and \fImq\fR both correspond to +block-multiqueue. Once a multipath device has been created, its queue_mode +cannot be changed. .TP The default is: \fB\fR .RE From patchwork Fri Oct 7 17:35:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001286 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3AE5FC43219 for ; Fri, 7 Oct 2022 17:35:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164157; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=/3LZB8nEX308KJ9mVztKt+32oKUcigI0n25tu07Xwfg=; b=AeQoDCm4+7yoZYsLDqXrjAITXKYA1RdHHh+McvENXrnzE9/KlN6U0wXbllBFQdkVRxtsl0 CvH+myj43WI1lasBdFddzZpjo+bdwYQdhJjq1rklY8N0TkOa/b9mCxXCLDrUvmwmRnnO1y YUUYCkgvVCAr7sNF4SgYESHxUTSVQDw= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-659-IdDPax2rOGiTCRZv2xUGLQ-1; Fri, 07 Oct 2022 13:35:56 -0400 X-MC-Unique: IdDPax2rOGiTCRZv2xUGLQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BDC7986EB21; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id AC3272166B4D; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 9BC741946A49; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 411451946595 for ; Fri, 7 Oct 2022 17:35:52 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 2868440F9D40; Fri, 7 Oct 2022 17:35:52 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 07B3640EFB3F; Fri, 7 Oct 2022 17:35:51 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZolT006776; Fri, 7 Oct 2022 12:35:51 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZoGq006775; Fri, 7 Oct 2022 12:35:50 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:41 -0500 Message-Id: <1665164144-6716-6-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Subject: [dm-devel] [PATCH 5/8] multipath tests: tests for reconcile_features_with_queue_mode X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Signed-off-by: Benjamin Marzinski --- tests/Makefile | 2 + tests/features.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 233 insertions(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index ccdfbd15..bc9380f8 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -36,6 +36,7 @@ ifneq ($(DIO_TEST_DEV),) directio-test_FLAGS := -DDIO_TEST_DEV=\"$(DIO_TEST_DEV)\" endif mpathvalid-test_FLAGS := -I$(mpathvaliddir) +features-test_FLAGS := -I$(multipathdir)/nvme # test-specific linker flags # XYZ-test_TESTDEPS: test libraries containing __wrap_xyz functions @@ -73,6 +74,7 @@ strbuf-test_OBJDEPS := $(mpathutildir)/strbuf.o sysfs-test_TESTDEPS := test-log.o sysfs-test_OBJDEPS := $(multipathdir)/sysfs.o $(mpathutildir)/util.o sysfs-test_LIBDEPS := -ludev -lpthread -ldl +features-test_LIBDEPS := -ludev -lpthread %.o: %.c $(CC) $(CPPFLAGS) $(CFLAGS) $($*-test_FLAGS) -c -o $@ $< diff --git a/tests/features.c b/tests/features.c index 4d8f0860..31f978fd 100644 --- a/tests/features.c +++ b/tests/features.c @@ -1,9 +1,10 @@ +#define _GNU_SOURCE #include #include #include #include -#include "structs.h" +#include "../libmultipath/propsel.c" #include "globals.c" static void test_af_null_features_ptr(void **state) @@ -307,6 +308,234 @@ static int test_remove_features(void) return cmocka_run_group_tests(tests, NULL, NULL); } +static void test_cf_null_features(void **state) +{ + struct multipath mp = { + .alias = "test", + }; + reconcile_features_with_queue_mode(&mp); + assert_null(mp.features); +} + +static void cf_helper(const char *features_start, const char *features_end, + int queue_mode_start, int queue_mode_end) +{ + struct multipath mp = { + .alias = "test", + .features = strdup(features_start), + .queue_mode = queue_mode_start, + }; + char *orig = mp.features; + + assert_non_null(orig); + reconcile_features_with_queue_mode(&mp); + if (!features_end) + assert_ptr_equal(orig, mp.features); + else + assert_string_equal(mp.features, features_end); + free(mp.features); + assert_int_equal(mp.queue_mode, queue_mode_end); +} + +static void test_cf_unset_unset1(void **state) +{ + cf_helper("0", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF); +} + +static void test_cf_unset_unset2(void **state) +{ + cf_helper("1 queue_mode", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF); +} + +static void test_cf_unset_unset3(void **state) +{ + cf_helper("queue_mode", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF); +} + +static void test_cf_unset_unset4(void **state) +{ + cf_helper("2 queue_model bio", NULL, QUEUE_MODE_UNDEF, + QUEUE_MODE_UNDEF); +} + +static void test_cf_unset_unset5(void **state) +{ + cf_helper("1 queue_if_no_path", NULL, QUEUE_MODE_UNDEF, + QUEUE_MODE_UNDEF); +} + +static void test_cf_invalid_unset1(void **state) +{ + cf_helper("2 queue_mode biop", "0", QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF); +} + +static void test_cf_invalid_unset2(void **state) +{ + cf_helper("3 queue_mode rqs queue_if_no_path", "1 queue_if_no_path", + QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF); +} + +static void test_cf_rq_unset1(void **state) +{ + cf_helper("2 queue_mode rq", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_RQ); +} + +static void test_cf_rq_unset2(void **state) +{ + cf_helper("2 queue_mode mq", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_RQ); +} + +static void test_cf_bio_unset(void **state) +{ + cf_helper("2 queue_mode bio", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_BIO); +} + +static void test_cf_unset_bio1(void **state) +{ + cf_helper("1 queue_if_no_path", "3 queue_if_no_path queue_mode bio", + QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_unset_bio2(void **state) +{ + cf_helper("0", "2 queue_mode bio", QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_unset_bio3(void **state) +{ + cf_helper("2 pg_init_retries 50", "4 pg_init_retries 50 queue_mode bio", + QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_invalid_bio1(void **state) +{ + cf_helper("2 queue_mode bad", "2 queue_mode bio", + QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_invalid_bio2(void **state) +{ + cf_helper("3 queue_if_no_path queue_mode\tbad", "3 queue_if_no_path queue_mode bio", + QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_bio_bio1(void **state) +{ + cf_helper("2 queue_mode bio", NULL, QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_bio_bio2(void **state) +{ + cf_helper("3 queue_if_no_path queue_mode bio", NULL, QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_bio_bio3(void **state) +{ + cf_helper("3 queue_mode\nbio queue_if_no_path", NULL, QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_bio_rq1(void **state) +{ + cf_helper("2\nqueue_mode\tbio", "0", QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_bio_rq2(void **state) +{ + cf_helper("3 queue_if_no_path\nqueue_mode bio", "1 queue_if_no_path", + QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_bio_rq3(void **state) +{ + cf_helper("4 queue_mode bio pg_init_retries 20", "2 pg_init_retries 20", + QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_unset_rq1(void **state) +{ + cf_helper("0", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_unset_rq2(void **state) +{ + cf_helper("2 pg_init_retries 15", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_invalid_rq1(void **state) +{ + cf_helper("2 queue_mode bionic", "0", QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_invalid_rq2(void **state) +{ + cf_helper("3 queue_mode b\nqueue_if_no_path", "1 queue_if_no_path", + QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_rq_rq1(void **state) +{ + cf_helper("2 queue_mode rq", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_rq_rq2(void **state) +{ + cf_helper("3 queue_mode\t \trq\nqueue_if_no_path", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ); +} + +static void test_cf_rq_bio1(void **state) +{ + cf_helper("2 queue_mode rq", "2 queue_mode bio", QUEUE_MODE_BIO, + QUEUE_MODE_BIO); +} + +static void test_cf_rq_bio2(void **state) +{ + cf_helper("3 queue_if_no_path\nqueue_mode rq", "3 queue_if_no_path queue_mode bio", QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static void test_cf_rq_bio3(void **state) +{ + cf_helper("3 queue_mode rq\nqueue_if_no_path", "3 queue_if_no_path queue_mode bio", QUEUE_MODE_BIO, QUEUE_MODE_BIO); +} + +static int test_reconcile_features(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_cf_null_features), + cmocka_unit_test(test_cf_unset_unset1), + cmocka_unit_test(test_cf_unset_unset2), + cmocka_unit_test(test_cf_unset_unset3), + cmocka_unit_test(test_cf_unset_unset4), + cmocka_unit_test(test_cf_unset_unset5), + cmocka_unit_test(test_cf_invalid_unset1), + cmocka_unit_test(test_cf_invalid_unset2), + cmocka_unit_test(test_cf_rq_unset1), + cmocka_unit_test(test_cf_rq_unset2), + cmocka_unit_test(test_cf_bio_unset), + cmocka_unit_test(test_cf_unset_bio1), + cmocka_unit_test(test_cf_unset_bio2), + cmocka_unit_test(test_cf_unset_bio3), + cmocka_unit_test(test_cf_invalid_bio1), + cmocka_unit_test(test_cf_invalid_bio2), + cmocka_unit_test(test_cf_bio_bio1), + cmocka_unit_test(test_cf_bio_bio2), + cmocka_unit_test(test_cf_bio_bio3), + cmocka_unit_test(test_cf_bio_rq1), + cmocka_unit_test(test_cf_bio_rq2), + cmocka_unit_test(test_cf_bio_rq3), + cmocka_unit_test(test_cf_unset_rq1), + cmocka_unit_test(test_cf_unset_rq2), + cmocka_unit_test(test_cf_invalid_rq1), + cmocka_unit_test(test_cf_invalid_rq2), + cmocka_unit_test(test_cf_rq_rq1), + cmocka_unit_test(test_cf_rq_rq2), + cmocka_unit_test(test_cf_rq_bio1), + cmocka_unit_test(test_cf_rq_bio2), + cmocka_unit_test(test_cf_rq_bio3), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} + int main(void) { int ret = 0; @@ -314,6 +543,7 @@ int main(void) init_test_verbosity(-1); ret += test_add_features(); ret += test_remove_features(); + ret += test_reconcile_features(); return ret; } From patchwork Fri Oct 7 17:35:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001289 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6EAFCC433F5 for ; Fri, 7 Oct 2022 17:36:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164161; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=h2hTSB9udFxYiAu5VpohAzMFkpgJ2CwsUwaiWRCAkGw=; b=DguSLYjDojE6jb9nINw6n9q+gvHnAKggZG9KXOXbxx/Zxa9IdQMQGJOZ5EZ7GtEwC/fcQS 9Hk/jRfLclxIF2hDgLsIIerhxTGvfS7jknZIKgUcCdtj03Yp4z9vBR1dT5AQ+18mxao21U 5yGCh0bMPa2t8r90BDiheXAjvfxV0Ag= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-623-1Q3L4A7DMryQU5J-PQV-fw-1; Fri, 07 Oct 2022 13:35:56 -0400 X-MC-Unique: 1Q3L4A7DMryQU5J-PQV-fw-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 06049857F8F; Fri, 7 Oct 2022 17:35:54 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id E8839535D28; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id D22B11946A66; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 321AB1946595 for ; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 24B86112C06F; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 01705112C069; Fri, 7 Oct 2022 17:35:52 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZpwY006780; Fri, 7 Oct 2022 12:35:51 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZpaG006779; Fri, 7 Oct 2022 12:35:51 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:42 -0500 Message-Id: <1665164144-6716-7-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 Subject: [dm-devel] [PATCH 6/8] libmultipath: prepare proto_id for use by non-scsi devivces X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Make sure that when we are checking for a scsi protocol, we are first checking that we are working with a scsi path. Signed-off-by: Benjamin Marzinski --- libmultipath/configure.c | 9 +++++---- libmultipath/discovery.c | 13 ++++++++----- libmultipath/print.c | 6 ++++-- libmultipath/structs.c | 2 +- libmultipath/structs.h | 4 +++- multipathd/fpin_handlers.c | 2 +- 6 files changed, 22 insertions(+), 14 deletions(-) diff --git a/libmultipath/configure.c b/libmultipath/configure.c index 41641e30..7c7babd9 100644 --- a/libmultipath/configure.c +++ b/libmultipath/configure.c @@ -218,10 +218,11 @@ int rr_optimize_path_order(struct pathgroup *pgp) total_paths = VECTOR_SIZE(pgp->paths); vector_foreach_slot(pgp->paths, pp, i) { - if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP && - pp->sg_id.proto_id != SCSI_PROTOCOL_SAS && - pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI && - pp->sg_id.proto_id != SCSI_PROTOCOL_SRP) { + if (pp->bus != SYSFS_BUS_SCSI || + (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP && + pp->sg_id.proto_id != SCSI_PROTOCOL_SAS && + pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI && + pp->sg_id.proto_id != SCSI_PROTOCOL_SRP)) { /* return success as default path order * is maintained in path group */ diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 15560f8c..e937f090 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -504,10 +504,11 @@ int sysfs_get_host_adapter_name(const struct path *pp, char *adapter_name) proto_id = pp->sg_id.proto_id; - if (proto_id != SCSI_PROTOCOL_FCP && - proto_id != SCSI_PROTOCOL_SAS && - proto_id != SCSI_PROTOCOL_ISCSI && - proto_id != SCSI_PROTOCOL_SRP) { + if (pp->bus != SYSFS_BUS_SCSI || + (proto_id != SCSI_PROTOCOL_FCP && + proto_id != SCSI_PROTOCOL_SAS && + proto_id != SCSI_PROTOCOL_ISCSI && + proto_id != SCSI_PROTOCOL_SRP)) { return 1; } /* iscsi doesn't have adapter info in sysfs @@ -1810,8 +1811,10 @@ sysfs_pathinfo(struct path *pp, const struct _vector *hwtable) pp->bus = SYSFS_BUS_CCISS; if (!strncmp(pp->dev,"dasd", 4)) pp->bus = SYSFS_BUS_CCW; - if (!strncmp(pp->dev,"sd", 2)) + if (!strncmp(pp->dev,"sd", 2)) { pp->bus = SYSFS_BUS_SCSI; + pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC; + } if (!strncmp(pp->dev,"nvme", 4)) pp->bus = SYSFS_BUS_NVME; diff --git a/libmultipath/print.c b/libmultipath/print.c index 68a793e7..d7d522c8 100644 --- a/libmultipath/print.c +++ b/libmultipath/print.c @@ -650,7 +650,8 @@ snprint_host_attr (struct strbuf *buff, const struct path * pp, char *attr) const char *value = NULL; int ret; - if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) + if (pp->bus != SYSFS_BUS_SCSI || + pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) return append_strbuf_str(buff, "[undef]"); sprintf(host_id, "host%d", pp->sg_id.host_no); host_dev = udev_device_new_from_subsystem_sysname(udev, "fc_host", @@ -689,7 +690,8 @@ snprint_tgt_wwpn (struct strbuf *buff, const struct path * pp) const char *value = NULL; int ret; - if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) + if (pp->bus != SYSFS_BUS_SCSI || + pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) return append_strbuf_str(buff, "[undef]"); sprintf(rport_id, "rport-%d:%d-%d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); diff --git a/libmultipath/structs.c b/libmultipath/structs.c index 0f16c071..fb44cd64 100644 --- a/libmultipath/structs.c +++ b/libmultipath/structs.c @@ -116,7 +116,7 @@ alloc_path (void) pp->sg_id.channel = -1; pp->sg_id.scsi_id = -1; pp->sg_id.lun = SCSI_INVALID_LUN; - pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC; + pp->sg_id.proto_id = PROTOCOL_UNSET; pp->fd = -1; pp->tpgs = TPGS_UNDEF; pp->priority = PRIO_UNDEF; diff --git a/libmultipath/structs.h b/libmultipath/structs.h index 129bdf0e..d3054662 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -176,6 +176,8 @@ enum queue_mode_states { QUEUE_MODE_RQ, }; +#define PROTOCOL_UNSET -1 + enum scsi_protocol { SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ @@ -291,7 +293,7 @@ struct sg_id { uint64_t lun; short h_cmd_per_lun; short d_queue_depth; - enum scsi_protocol proto_id; + int proto_id; int transport_id; }; diff --git a/multipathd/fpin_handlers.c b/multipathd/fpin_handlers.c index 03b2b9ad..a2de3011 100644 --- a/multipathd/fpin_handlers.c +++ b/multipathd/fpin_handlers.c @@ -227,7 +227,7 @@ static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *ve vector_foreach_slot(vecs->pathvec, pp, k) { /* Checks the host number and also for the SCSI FCP */ - if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num != pp->sg_id.host_no) + if (pp->bus != SYSFS_BUS_SCSI || pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num != pp->sg_id.host_no) continue; sprintf(rport_id, "rport-%d:%d-%d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); From patchwork Fri Oct 7 17:35:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001287 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 33725C433FE for ; Fri, 7 Oct 2022 17:35:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164158; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=y+5tRMhIgrKHKuxqRkZeG/bXNCs14j4Pqf+Xma5fKos=; b=PShuOmYwt7j2ViRyWZtiA7EorX1DXFNyKQtXs+zRIxwmSF2dMXR7CufiXZnJYsyx3Ww8aC ML3XXmumGlCOUnVwMXVq4Nh+U8A9Obbjfz+hlZvGyX4ib0vFNPCxbnnuYQwQlozf34msxO PJvOe1SUeFFgmW6r52HDux3aDuiUxDk= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-426-MepI2OvTNLa8_O2huNcUlw-1; Fri, 07 Oct 2022 13:35:57 -0400 X-MC-Unique: MepI2OvTNLa8_O2huNcUlw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2C23A855306; Fri, 7 Oct 2022 17:35:55 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1A143145BEE3; Fri, 7 Oct 2022 17:35:55 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 0BC981946A49; Fri, 7 Oct 2022 17:35:55 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 1E53D1946A66 for ; Fri, 7 Oct 2022 17:35:54 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 11C90145BEE9; Fri, 7 Oct 2022 17:35:54 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E5A5E145BEE6; Fri, 7 Oct 2022 17:35:53 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZq5Y006786; Fri, 7 Oct 2022 12:35:52 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZqDf006783; Fri, 7 Oct 2022 12:35:52 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:43 -0500 Message-Id: <1665164144-6716-8-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 Subject: [dm-devel] [PATCH 7/8] libmultipath: get nvme path transport protocol X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Read the transport protocol from /sys/block/nvmeXnY/device/transport. Update protocol_name[] and bus_protocol_id() to store the nvme protocol names after the scsi protocol names. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- libmultipath/discovery.c | 18 ++++++++++++++++-- libmultipath/structs.c | 22 +++++++++++++++++----- libmultipath/structs.h | 33 +++++++++++++++++++++------------ multipath/multipath.conf.5 | 8 ++++++-- 4 files changed, 60 insertions(+), 21 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index e937f090..f3fccedd 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1539,6 +1539,7 @@ nvme_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable) struct udev_device *parent; const char *attr_path = NULL; const char *attr; + int i; if (pp->udev) attr_path = udev_device_get_sysname(pp->udev); @@ -1561,6 +1562,18 @@ nvme_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable) attr = udev_device_get_sysattr_value(parent, "cntlid"); pp->sg_id.channel = attr ? atoi(attr) : 0; + attr = udev_device_get_sysattr_value(parent, "transport"); + if (attr) { + for (i = 0; i < NVME_PROTOCOL_UNSPEC; i++){ + if (protocol_name[SYSFS_BUS_NVME + i] && + !strcmp(attr, + protocol_name[SYSFS_BUS_NVME + i] + 5)) { + pp->sg_id.proto_id = i; + break; + } + } + } + snprintf(pp->vendor_id, SCSI_VENDOR_SIZE, "NVME"); snprintf(pp->product_id, PATH_PRODUCT_SIZE, "%s", udev_device_get_sysattr_value(parent, "model")); @@ -1815,9 +1828,10 @@ sysfs_pathinfo(struct path *pp, const struct _vector *hwtable) pp->bus = SYSFS_BUS_SCSI; pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC; } - if (!strncmp(pp->dev,"nvme", 4)) + if (!strncmp(pp->dev,"nvme", 4)) { pp->bus = SYSFS_BUS_NVME; - + pp->sg_id.proto_id = NVME_PROTOCOL_UNSPEC; + } switch (pp->bus) { case SYSFS_BUS_SCSI: return scsi_sysfs_pathinfo(pp, hwtable); diff --git a/libmultipath/structs.c b/libmultipath/structs.c index fb44cd64..7a2ff589 100644 --- a/libmultipath/structs.c +++ b/libmultipath/structs.c @@ -25,7 +25,6 @@ const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = { [SYSFS_BUS_UNDEF] = "undef", [SYSFS_BUS_CCW] = "ccw", [SYSFS_BUS_CCISS] = "cciss", - [SYSFS_BUS_NVME] = "nvme", [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp", [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi", [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa", @@ -37,6 +36,13 @@ const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = { [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata", [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb", [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec", + [SYSFS_BUS_NVME + NVME_PROTOCOL_PCIE] = "nvme:pcie", + [SYSFS_BUS_NVME + NVME_PROTOCOL_RDMA] = "nvme:rdma", + [SYSFS_BUS_NVME + NVME_PROTOCOL_FC] = "nvme:fc", + [SYSFS_BUS_NVME + NVME_PROTOCOL_TCP] = "nvme:tcp", + [SYSFS_BUS_NVME + NVME_PROTOCOL_LOOP] = "nvme:loop", + [SYSFS_BUS_NVME + NVME_PROTOCOL_APPLE_NVME] = "nvme:apple-nvme", + [SYSFS_BUS_NVME + NVME_PROTOCOL_UNSPEC] = "nvme:unspec", }; struct adapter_group * @@ -746,11 +752,17 @@ out: } unsigned int bus_protocol_id(const struct path *pp) { - if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_SCSI) + if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_NVME) return SYSFS_BUS_UNDEF; - if (pp->bus != SYSFS_BUS_SCSI) + if (pp->bus != SYSFS_BUS_SCSI && pp->bus != SYSFS_BUS_NVME) return pp->bus; - if ((int)pp->sg_id.proto_id < 0 || pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC) + if (pp->sg_id.proto_id < 0) return SYSFS_BUS_UNDEF; - return SYSFS_BUS_SCSI + pp->sg_id.proto_id; + if (pp->bus == SYSFS_BUS_SCSI && + pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC) + return SYSFS_BUS_UNDEF; + if (pp->bus == SYSFS_BUS_NVME && + pp->sg_id.proto_id > NVME_PROTOCOL_UNSPEC) + return SYSFS_BUS_UNDEF; + return pp->bus + pp->sg_id.proto_id; } diff --git a/libmultipath/structs.h b/libmultipath/structs.h index d3054662..9e2c1ab0 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -56,15 +56,6 @@ enum failback_mode { FAILBACK_FOLLOWOVER }; -/* SYSFS_BUS_SCSI should be last, see bus_protocol_id() */ -enum sysfs_buses { - SYSFS_BUS_UNDEF, - SYSFS_BUS_CCW, - SYSFS_BUS_CCISS, - SYSFS_BUS_NVME, - SYSFS_BUS_SCSI, -}; - enum pathstates { PSTATE_UNDEF, PSTATE_FAILED, @@ -190,14 +181,32 @@ enum scsi_protocol { SCSI_PROTOCOL_ATA = 8, SCSI_PROTOCOL_USB = 9, /* USB Attached SCSI (UAS), and others */ SCSI_PROTOCOL_UNSPEC = 0xa, /* No specific protocol */ + SCSI_PROTOCOL_END = 0xb, /* offset of the next sysfs_buses entry */ +}; + +/* values from /sys/class/nvme/nvmeX */ +enum nvme_protocol { + NVME_PROTOCOL_PCIE = 0, + NVME_PROTOCOL_RDMA = 1, + NVME_PROTOCOL_FC = 2, + NVME_PROTOCOL_TCP = 3, + NVME_PROTOCOL_LOOP = 4, + NVME_PROTOCOL_APPLE_NVME = 5, + NVME_PROTOCOL_UNSPEC = 6, /* unknown protocol */ +}; + +enum sysfs_buses { + SYSFS_BUS_UNDEF, + SYSFS_BUS_CCW, + SYSFS_BUS_CCISS, + SYSFS_BUS_SCSI, + SYSFS_BUS_NVME = SYSFS_BUS_SCSI + SCSI_PROTOCOL_END, }; /* * Linear ordering of bus/protocol - * This assumes that SYSFS_BUS_SCSI is last in enum sysfs_buses - * SCSI is the only bus type for which we distinguish protocols. */ -#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC) +#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_NVME + NVME_PROTOCOL_UNSPEC) unsigned int bus_protocol_id(const struct path *pp); extern const char * const protocol_name[]; diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 index 46a4126c..07476497 100644 --- a/multipath/multipath.conf.5 +++ b/multipath/multipath.conf.5 @@ -1377,7 +1377,9 @@ Regular expression for the protocol of a device to be excluded/included. The protocol strings that multipath recognizes are \fIscsi:fcp\fR, \fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR, \fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR, -\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR. +\fIscsi:unspec\fR, \fInvme:pcie\fR, \fInvme:rdma\fR, \fInvme:fc\fR, +\fInvme:tcp\fR, \fInvme:loop\fR, \fInvme:apple-nvme\fR, \fInvme:unspec\fR, +\fIccw\fR, \fIcciss\fR, and \fIundef\fR. The protocol that a path is using can be viewed by running \fBmultipathd show paths format "%d %P"\fR .RE @@ -1773,7 +1775,9 @@ The protocol subsection recognizes the following mandatory attribute: The protocol string of the path device. The possible values are \fIscsi:fcp\fR, \fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR, \fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR, -\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR. This is +\fIscsi:unspec\fR, \fInvme:pcie\fR, \fInvme:rdma\fR, \fInvme:fc\fR, +\fInvme:tcp\fR, \fInvme:loop\fR, \fInvme:apple-nvme\fR, \fInvme:unspec\fR, +\fIccw\fR, \fIcciss\fR, and \fIundef\fR. This is \fBnot\fR a regular expression. the path device protocol string must match exactly. The protocol that a path is using can be viewed by running \fBmultipathd show paths format "%d %P"\fR From patchwork Fri Oct 7 17:35:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Marzinski X-Patchwork-Id: 13001290 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 49DB6C433FE for ; Fri, 7 Oct 2022 17:36:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665164162; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=TEJs8um+hfIPvcA71R3n5eUVzIv2P2SZEJ06H8AcNHc=; b=DxuKJLDOIyJtoebNS8ZL+XonOnsJXhXfDOOdLMhS4CpDxLRcHQkefC4PME8eNJBDaGOXjc i7XXuUR+7d1TEMhoWYZ37i6CxJZ8+HAlOa0CN4ZCvYhbw7p55pwysXtCB49ZeeUaSTEzJx 1dIFhEOu62D8cFyOQWl4x7gykxw8FBs= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-639-gamCMNHvNz6XNpkKTSeOgw-1; Fri, 07 Oct 2022 13:35:58 -0400 X-MC-Unique: gamCMNHvNz6XNpkKTSeOgw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 58700185A7A8; Fri, 7 Oct 2022 17:35:56 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4842C145BEE3; Fri, 7 Oct 2022 17:35:56 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 370FB1946A49; Fri, 7 Oct 2022 17:35:56 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 432321946595 for ; Fri, 7 Oct 2022 17:35:55 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 37A6140F9D76; Fri, 7 Oct 2022 17:35:55 +0000 (UTC) Received: from octiron.msp.redhat.com (octiron.msp.redhat.com [10.15.80.209]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0B15D40EFB3F; Fri, 7 Oct 2022 17:35:55 +0000 (UTC) Received: from octiron.msp.redhat.com (localhost.localdomain [127.0.0.1]) by octiron.msp.redhat.com (8.14.9/8.14.9) with ESMTP id 297HZrtC006790; Fri, 7 Oct 2022 12:35:53 -0500 Received: (from bmarzins@localhost) by octiron.msp.redhat.com (8.14.9/8.14.9/Submit) id 297HZrQe006789; Fri, 7 Oct 2022 12:35:53 -0500 From: Benjamin Marzinski To: Christophe Varoqui Date: Fri, 7 Oct 2022 12:35:44 -0500 Message-Id: <1665164144-6716-9-git-send-email-bmarzins@redhat.com> In-Reply-To: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> References: <1665164144-6716-1-git-send-email-bmarzins@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Subject: [dm-devel] [PATCH 8/8] libmultipath: enforce queue_mode bio for nmve:tcp paths X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: device-mapper development , Martin Wilck MIME-Version: 1.0 Errors-To: dm-devel-bounces@redhat.com Sender: "dm-devel" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com nvme:tcp devices set BLK_MQ_F_BLOCKING (they are the only block devices which multipath supports that do so), meaning that block_mq expects that they can block at certain points while servicing a request. However, due to the way device-mapper sets up its queue, it is not able to set BLK_MQ_F_BLOCKING when it includes paths that set this flag. Patches were written to address this issue but they were rejected upstream https://lore.kernel.org/linux-block/YcH%2FE4JNag0QYYAa@infradead.org/T/#t The proposed solution was to have multipath use the bio queue_mode for multipath devices that include nvme:tcp paths. Multipath devices now automatically add the "queue_mode bio" feature if they include nvme:tcp paths. If a multipath devices was created with "queue_mode rq", it will disallow the addition of nvme:tcp paths. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- libmultipath/configure.c | 17 ++++++++++++++++- libmultipath/structs_vec.c | 7 +++++++ multipath/multipath.conf.5 | 4 +++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libmultipath/configure.c b/libmultipath/configure.c index 7c7babd9..e5249fc1 100644 --- a/libmultipath/configure.c +++ b/libmultipath/configure.c @@ -260,6 +260,7 @@ int rr_optimize_path_order(struct pathgroup *pgp) int setup_map(struct multipath *mpp, char **params, struct vectors *vecs) { struct pathgroup * pgp; + struct path *pp; struct config *conf; int i, marginal_pathgroups; char *save_attr; @@ -275,6 +276,14 @@ int setup_map(struct multipath *mpp, char **params, struct vectors *vecs) if (mpp->disable_queueing && VECTOR_SIZE(mpp->paths) != 0) mpp->disable_queueing = 0; + /* Force QUEUE_MODE_BIO for maps with nvme:tcp paths */ + vector_foreach_slot(mpp->paths, pp, i) { + if (pp->bus == SYSFS_BUS_NVME && + pp->sg_id.proto_id == NVME_PROTOCOL_TCP) { + mpp->queue_mode = QUEUE_MODE_BIO; + break; + } + } /* * If this map was created with add_map_without_path(), * mpp->hwe might not be set yet. @@ -1148,6 +1157,13 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, continue; } + cmpp = find_mp_by_wwid(curmp, pp1->wwid); + if (cmpp && cmpp->queue_mode == QUEUE_MODE_RQ && + pp1->bus == SYSFS_BUS_NVME && pp1->sg_id.proto_id == + NVME_PROTOCOL_TCP) { + orphan_path(pp1, "nvme:tcp path not allowed with request queue_mode multipath device"); + continue; + } /* * at this point, we know we really got a new mp */ @@ -1186,7 +1202,6 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, } verify_paths(mpp); - cmpp = find_mp_by_wwid(curmp, mpp->wwid); if (cmpp) mpp->queue_mode = cmpp->queue_mode; if (setup_map(mpp, ¶ms, vecs)) { diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c index 645896c6..5a618767 100644 --- a/libmultipath/structs_vec.c +++ b/libmultipath/structs_vec.c @@ -264,6 +264,13 @@ int adopt_paths(vector pathvec, struct multipath *mpp) } if (pp->initialized == INIT_REMOVED) continue; + if (mpp->queue_mode == QUEUE_MODE_RQ && + pp->bus == SYSFS_BUS_NVME && + pp->sg_id.proto_id == NVME_PROTOCOL_TCP) { + condlog(2, "%s: mulitpath device %s created with request queue_mode. Unable to add nvme:tcp paths", + pp->dev, mpp->alias); + continue; + } if (!mpp->paths && !(mpp->paths = vector_alloc())) goto err; diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 index 07476497..1fea9d5a 100644 --- a/multipath/multipath.conf.5 +++ b/multipath/multipath.conf.5 @@ -463,7 +463,9 @@ Before kernel 4.20 The default depends on the kernel parameter \fBdm_mod.use_blk_mq\fR. It is \fImq\fR if the latter is set, and \fIrq\fR otherwise. Since kernel 4.20, \fIrq\fR and \fImq\fR both correspond to block-multiqueue. Once a multipath device has been created, its queue_mode -cannot be changed. +cannot be changed. \fInvme:tcp\fR paths are only supported in multipath +devices with queue_mode set to \fIbio\fR. multipath will automatically +set this when creating a device with \fInvme:tcp\fR paths. .TP The default is: \fB\fR .RE