diff mbox series

libmultipath: ignore nvme devices if nvme native multipath is enabled

Message ID 20230630181407.14302-1-mwilck@suse.com (mailing list archive)
State Not Applicable, archived
Delegated to: christophe varoqui
Headers show
Series libmultipath: ignore nvme devices if nvme native multipath is enabled | expand

Commit Message

Martin Wilck June 30, 2023, 6:14 p.m. UTC
From: Martin Wilck <mwilck@suse.com>

If the nvme native multipath driver is enabled, blacklist nvme devices
for dm-multipath by default. This is particularly useful with
"find_multipaths greedy".

Signed-off-by: Martin Wilck <mwilck@suse.com>
---
 libmultipath/blacklist.c | 35 ++++++++++++++++++++++++++++++++---
 tests/blacklist.c        | 30 ++++++++++++++++++++++++++++--
 2 files changed, 60 insertions(+), 5 deletions(-)

Comments

Benjamin Marzinski June 30, 2023, 10:16 p.m. UTC | #1
On Fri, Jun 30, 2023 at 08:14:07PM +0200, mwilck@suse.com wrote:
> From: Martin Wilck <mwilck@suse.com>
> 
> If the nvme native multipath driver is enabled, blacklist nvme devices
> for dm-multipath by default. This is particularly useful with
> "find_multipaths greedy".
> 
> Signed-off-by: Martin Wilck <mwilck@suse.com>

This looks good. I have two small questions below.

> ---
>  libmultipath/blacklist.c | 35 ++++++++++++++++++++++++++++++++---
>  tests/blacklist.c        | 30 ++++++++++++++++++++++++++++--
>  2 files changed, 60 insertions(+), 5 deletions(-)
> 
> diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
> index 8d15d2e..75100b2 100644
> --- a/libmultipath/blacklist.c
> +++ b/libmultipath/blacklist.c
> @@ -2,6 +2,8 @@
>   * Copyright (c) 2004, 2005 Christophe Varoqui
>   */
>  #include <stdio.h>
> +#include <unistd.h>
> +#include <fcntl.h>
>  #include <libudev.h>
>  
>  #include "checkers.h"
> @@ -191,6 +193,27 @@ find_blacklist_device (const struct _vector *blist, const char *vendor,
>  	return 0;
>  }
>  
> +/*
> + * Test if nvme native multipath is enabled. If the sysfs file can't
> + * be accessed, multipath is either disabled at compile time, or no
> + * nvme driver is loaded at all. Thus treat errors as "no".
> + */
> +static bool nvme_multipath_enabled(void)
> +{
> +	static const char fn[] = "/sys/module/nvme_core/parameters/multipath";

Is there some benefit that I don't understand to using "static const",
instead of just "const"?  Obviously, the amount of memory necessary to
keep storing this string outside of the function is very small, but I
don't see why we need to at all.

> +	int fd, len;
> +	char buf[2];
> +
> +	fd = open(fn, O_RDONLY);
> +	if (fd == -1)
> +		return false;
> +
> +	len = read(fd, buf, sizeof(buf));
> +	close(fd);
> +
> +	return (len >= 1 && buf[0] == 'Y');
> +}
> +
>  int
>  setup_default_blist (struct config * conf)
>  {
> @@ -198,9 +221,15 @@ setup_default_blist (struct config * conf)
>  	struct hwentry *hwe;
>  	int i;
>  
> -	if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])", ORIGIN_DEFAULT))
> -		return 1;
> -
> +	if (nvme_multipath_enabled()) {
> +		if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z])",
> +			      ORIGIN_DEFAULT))
> +			return 1;
> +	} else {
> +		if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])",
> +			      ORIGIN_DEFAULT))
> +			return 1;
> +	}
>  	if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT))
>  		return 1;
>  
> diff --git a/tests/blacklist.c b/tests/blacklist.c
> index 882aa3a..65002eb 100644
> --- a/tests/blacklist.c
> +++ b/tests/blacklist.c
> @@ -17,6 +17,8 @@
>   */
>  #include <stdarg.h>
>  #include <stddef.h>
> +#include <unistd.h>
> +#include <fcntl.h>
>  #include <setjmp.h>
>  #include <cmocka.h>
>  #include "globals.c"
> @@ -220,12 +222,36 @@ static void test_devnode_missing(void **state)
>  			 MATCH_NOTHING);
>  }

Perhaps we should just use #include "../libmultipath/blacklist.c" like
we do for tests where we need get at a file's private
variables/functions ("../libmultipath/alias.c" in alias.c for instance).

-Ben

> +/* copy of the same function in libmultipath/blacklist.c */
> +static bool nvme_multipath_enabled(void)
> +{
> +	static const char fn[] = "/sys/module/nvme_core/parameters/multipath";
> +	int fd, len;
> +	char buf[2];
> +
> +	fd = open(fn, O_RDONLY);
> +	if (fd == -1)
> +		return false;
> +
> +	len = read(fd, buf, sizeof(buf));
> +	close(fd);
> +
> +	return (len >= 1 && buf[0] == 'Y');
> +}
> +
>  static void test_devnode_default(void **state)
>  {
>  	assert_int_equal(filter_devnode(blist_devnode_default, NULL, "sdaa"),
>  			 MATCH_NOTHING);
> -	assert_int_equal(filter_devnode(blist_devnode_default, NULL, "nvme0n1"),
> -			 MATCH_NOTHING);
> +	if (nvme_multipath_enabled()) {
> +		expect_condlog(3, "nvme0n1: device node name blacklisted\n");
> +		assert_int_equal(filter_devnode(blist_devnode_default, NULL,
> +						"nvme0n1"),
> +				 MATCH_DEVNODE_BLIST);
> +	} else
> +		assert_int_equal(filter_devnode(blist_devnode_default, NULL,
> +						"nvme0n1"),
> +				 MATCH_NOTHING);
>  	assert_int_equal(filter_devnode(blist_devnode_default, NULL, "dasda"),
>  			 MATCH_NOTHING);
>  	expect_condlog(3, "hda: device node name blacklisted\n");
> -- 
> 2.41.0
--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel
Martin Wilck July 3, 2023, 3:15 p.m. UTC | #2
On Fri, 2023-06-30 at 17:16 -0500, Benjamin Marzinski wrote:
> On Fri, Jun 30, 2023 at 08:14:07PM +0200, mwilck@suse.com wrote:
> > From: Martin Wilck <mwilck@suse.com>
> > 
> > If the nvme native multipath driver is enabled, blacklist nvme
> > devices
> > for dm-multipath by default. This is particularly useful with
> > "find_multipaths greedy".
> > 
> > Signed-off-by: Martin Wilck <mwilck@suse.com>
> 
> This looks good. I have two small questions below.
> 
> > ---
> >  libmultipath/blacklist.c | 35 ++++++++++++++++++++++++++++++++---
> >  tests/blacklist.c        | 30 ++++++++++++++++++++++++++++--
> >  2 files changed, 60 insertions(+), 5 deletions(-)
> > 
> > diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
> > index 8d15d2e..75100b2 100644
> > --- a/libmultipath/blacklist.c
> > +++ b/libmultipath/blacklist.c
> > @@ -2,6 +2,8 @@
> >   * Copyright (c) 2004, 2005 Christophe Varoqui
> >   */
> >  #include <stdio.h>
> > +#include <unistd.h>
> > +#include <fcntl.h>
> >  #include <libudev.h>
> >  
> >  #include "checkers.h"
> > @@ -191,6 +193,27 @@ find_blacklist_device (const struct _vector
> > *blist, const char *vendor,
> >         return 0;
> >  }
> >  
> > +/*
> > + * Test if nvme native multipath is enabled. If the sysfs file
> > can't
> > + * be accessed, multipath is either disabled at compile time, or
> > no
> > + * nvme driver is loaded at all. Thus treat errors as "no".
> > + */
> > +static bool nvme_multipath_enabled(void)
> > +{
> > +       static const char fn[] =
> > "/sys/module/nvme_core/parameters/multipath";
> 
> Is there some benefit that I don't understand to using "static
> const",
> instead of just "const"?  Obviously, the amount of memory necessary
> to
> keep storing this string outside of the function is very small, but I
> don't see why we need to at all.

"static const" and "const" aren't the same thing. "static const" makes
sure the variable's life time is the run time of the program, hence the
compiler can place it in the .rodata section of the output. A "const"
variable in function scope without "static" has "automatic" storage
class, and is thus allocated and initialized on the stack.

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
(§6.2.4 storage durations of objects)

https://stackoverflow.com/questions/3709207/c-semantics-of-static-const-vs-const


You can see this if you compile a program like this

int check(const char *);
int fn(void) {
	/* static */ const char t[] = "0123456789abcdef";
	return check(t);
}

with and without "static".

> > diff --git a/tests/blacklist.c b/tests/blacklist.c
> > index 882aa3a..65002eb 100644
> > --- a/tests/blacklist.c
> > +++ b/tests/blacklist.c
> > @@ -17,6 +17,8 @@
> >   */
> >  #include <stdarg.h>
> >  #include <stddef.h>
> > +#include <unistd.h>
> > +#include <fcntl.h>
> >  #include <setjmp.h>
> >  #include <cmocka.h>
> >  #include "globals.c"
> > @@ -220,12 +222,36 @@ static void test_devnode_missing(void
> > **state)
> >                          MATCH_NOTHING);
> >  }
> 
> Perhaps we should just use #include "../libmultipath/blacklist.c"
> like
> we do for tests where we need get at a file's private
> variables/functions ("../libmultipath/alias.c" in alias.c for
> instance).

Ok.

Regards
Martin

--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel
diff mbox series

Patch

diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 8d15d2e..75100b2 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -2,6 +2,8 @@ 
  * Copyright (c) 2004, 2005 Christophe Varoqui
  */
 #include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <libudev.h>
 
 #include "checkers.h"
@@ -191,6 +193,27 @@  find_blacklist_device (const struct _vector *blist, const char *vendor,
 	return 0;
 }
 
+/*
+ * Test if nvme native multipath is enabled. If the sysfs file can't
+ * be accessed, multipath is either disabled at compile time, or no
+ * nvme driver is loaded at all. Thus treat errors as "no".
+ */
+static bool nvme_multipath_enabled(void)
+{
+	static const char fn[] = "/sys/module/nvme_core/parameters/multipath";
+	int fd, len;
+	char buf[2];
+
+	fd = open(fn, O_RDONLY);
+	if (fd == -1)
+		return false;
+
+	len = read(fd, buf, sizeof(buf));
+	close(fd);
+
+	return (len >= 1 && buf[0] == 'Y');
+}
+
 int
 setup_default_blist (struct config * conf)
 {
@@ -198,9 +221,15 @@  setup_default_blist (struct config * conf)
 	struct hwentry *hwe;
 	int i;
 
-	if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])", ORIGIN_DEFAULT))
-		return 1;
-
+	if (nvme_multipath_enabled()) {
+		if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z])",
+			      ORIGIN_DEFAULT))
+			return 1;
+	} else {
+		if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])",
+			      ORIGIN_DEFAULT))
+			return 1;
+	}
 	if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT))
 		return 1;
 
diff --git a/tests/blacklist.c b/tests/blacklist.c
index 882aa3a..65002eb 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -17,6 +17,8 @@ 
  */
 #include <stdarg.h>
 #include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <setjmp.h>
 #include <cmocka.h>
 #include "globals.c"
@@ -220,12 +222,36 @@  static void test_devnode_missing(void **state)
 			 MATCH_NOTHING);
 }
 
+/* copy of the same function in libmultipath/blacklist.c */
+static bool nvme_multipath_enabled(void)
+{
+	static const char fn[] = "/sys/module/nvme_core/parameters/multipath";
+	int fd, len;
+	char buf[2];
+
+	fd = open(fn, O_RDONLY);
+	if (fd == -1)
+		return false;
+
+	len = read(fd, buf, sizeof(buf));
+	close(fd);
+
+	return (len >= 1 && buf[0] == 'Y');
+}
+
 static void test_devnode_default(void **state)
 {
 	assert_int_equal(filter_devnode(blist_devnode_default, NULL, "sdaa"),
 			 MATCH_NOTHING);
-	assert_int_equal(filter_devnode(blist_devnode_default, NULL, "nvme0n1"),
-			 MATCH_NOTHING);
+	if (nvme_multipath_enabled()) {
+		expect_condlog(3, "nvme0n1: device node name blacklisted\n");
+		assert_int_equal(filter_devnode(blist_devnode_default, NULL,
+						"nvme0n1"),
+				 MATCH_DEVNODE_BLIST);
+	} else
+		assert_int_equal(filter_devnode(blist_devnode_default, NULL,
+						"nvme0n1"),
+				 MATCH_NOTHING);
 	assert_int_equal(filter_devnode(blist_devnode_default, NULL, "dasda"),
 			 MATCH_NOTHING);
 	expect_condlog(3, "hda: device node name blacklisted\n");