All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] nvme-cli: fabrics: remove libudev dependency
@ 2016-12-16  0:05 Keith Busch
  2016-12-16  8:04 ` Christoph Hellwig
  0 siblings, 1 reply; 4+ messages in thread
From: Keith Busch @ 2016-12-16  0:05 UTC (permalink / raw)


I am getting a lot of complaints about portability of the nvme-cli
regarding the libudev dependency. This patch removes the dependency from
the fabrics disconnect command when using the target nqn method. Tested
on nvme loop target.

Signed-off-by: Keith Busch <keith.busch at intel.com>
---
I hadn't tried any of the nvme fabrics or targets before today, and just
want to say that using the nvme loop device was incredibly pleasent to
test with nvmetcli.

Since I'm not involved with the fabrics work, I wanted to send this out
before pushing. It's a pretty straight foward conversion to get rid of
the libudev dependency, and I suspect testing on the loop is probably
good enough, but don't want to break anyone either.

 Makefile  |   7 ----
 fabrics.c | 116 +++++++++++++++++++++++++-------------------------------------
 2 files changed, 46 insertions(+), 77 deletions(-)

diff --git a/Makefile b/Makefile
index 33c7190..13da0b7 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,6 @@ DESTDIR =
 PREFIX ?= /usr/local
 SYSCONFDIR = /etc
 SBINDIR = $(PREFIX)/sbin
-LIBUDEV := $(shell ld -o /dev/null -ludev >/dev/null 2>&1; echo $$?)
 LIB_DEPENDS =
 
 RPMBUILD = rpmbuild
@@ -15,12 +14,6 @@ RM = rm -f
 
 AUTHOR=Keith Busch <keith.busch at intel.com>
 
-ifeq ($(LIBUDEV),0)
-	override LDFLAGS += -ludev
-	override CFLAGS  += -DLIBUDEV_EXISTS
-	override LIB_DEPENDS += udev
-endif
-
 default: $(NVME)
 
 NVME-VERSION-FILE: FORCE
diff --git a/fabrics.c b/fabrics.c
index 2b3caa1..577aa9d 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -26,13 +26,10 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <unistd.h>
+#include <dirent.h>
 #include <sys/ioctl.h>
 #include <asm/byteorder.h>
 #include <inttypes.h>
-#ifdef LIBUDEV_EXISTS
-#include <libudev.h>
-#endif
-
 #include <linux/types.h>
 
 #include "parser.h"
@@ -62,6 +59,7 @@ static struct config {
 #define PATH_NVME_FABRICS	"/dev/nvme-fabrics"
 #define PATH_NVMF_DISC		"/etc/nvme/discovery.conf"
 #define PATH_NVMF_HOSTNQN	"/etc/nvme/hostnqn"
+#define SYS_NVME		"/sys/class/nvme"
 #define MAX_DISC_ARGS		10
 
 enum {
@@ -801,85 +799,63 @@ int connect(const char *desc, int argc, char **argv)
 	return 0;
 }
 
-#ifdef LIBUDEV_EXISTS
-static int disconnect_subsys(struct udev_enumerate *enumerate, char *nqn)
+static int scan_sys_nvme_filter(const struct dirent *d)
 {
-	struct udev_list_entry *list_entry;
-	const char *subsysnqn;
-	char *sysfs_path;
-	int ret = 1;
-
-	udev_list_entry_foreach(list_entry,
-				udev_enumerate_get_list_entry(enumerate)) {
-		struct udev_device *device;
-
-		device = udev_device_new_from_syspath(
-				udev_enumerate_get_udev(enumerate),
-				udev_list_entry_get_name(list_entry));
-		if (device != NULL) {
-			subsysnqn = udev_device_get_sysattr_value(
-					device, "subsysnqn");
-			if (subsysnqn && !strcmp(subsysnqn, nqn)) {
-				if (asprintf(&sysfs_path,
-					"%s/delete_controller",
-					udev_device_get_syspath(device)) < 0) {
-					ret = errno;
-					udev_device_unref(device);
-					break;
-				}
-				udev_device_unref(device);
-				ret = remove_ctrl_by_path(sysfs_path);
-				free(sysfs_path);
-				break;
-			}
-			udev_device_unref(device);
-		}
-	}
-
-	return ret;
+	return !((strcmp(d->d_name, ".") == 0) ||
+		(strcmp(d->d_name, "..") == 0));
 }
 
+
 static int disconnect_by_nqn(char *nqn)
 {
-	struct udev *udev;
-	struct udev_enumerate *udev_enumerate;
-	int ret;
+	struct dirent ** devices = NULL;
+	int i, n, fd, ret = 0;
+	bool done = false;
+	char subsysnqn[NVMF_NQN_SIZE] = {};
 
-	if (strlen(nqn) > NVMF_NQN_SIZE) {
-		ret = -EINVAL;
-		goto exit;
-	}
+	if (strlen(nqn) > NVMF_NQN_SIZE)
+		return -EINVAL;
 
-	udev = udev_new();
-	if (!udev) {
-		fprintf(stderr, "failed to create udev\n");
-		ret = -ENOMEM;
-		goto exit;
-	}
+	n = scandir(SYS_NVME, &devices, scan_sys_nvme_filter, alphasort);
+
+	for (i = 0; i < n; i++) {
+		char *sysfs_nqn_path;
 
-	udev_enumerate = udev_enumerate_new(udev);
-	if (udev_enumerate == NULL) {
-		ret = -ENOMEM;
-		goto free_udev;
+		asprintf(&sysfs_nqn_path, "%s/%s/subsysnqn",
+			SYS_NVME, devices[i]->d_name);
+
+		fd = open(sysfs_nqn_path, O_RDONLY);
+		if (fd > 0) {
+			char *sysfs_del_path;
+
+			if (read(fd, subsysnqn, NVMF_NQN_SIZE) < 0)
+				goto next;
+
+			subsysnqn[strcspn(subsysnqn, "\n")] = '\0';
+			if (strcmp(subsysnqn, nqn))
+				goto next;
+
+			asprintf(&sysfs_del_path, "%s/%s/delete_controller",
+				SYS_NVME, devices[i]->d_name);
+			ret = remove_ctrl_by_path(sysfs_del_path);
+
+			done = true;
+			free(sysfs_del_path);
+ next:
+			close(fd);
+		}
+
+		free(sysfs_nqn_path);
+		if (done)
+			break;
 	}
 
-	udev_enumerate_add_match_subsystem(udev_enumerate, "nvme");
-	udev_enumerate_scan_devices(udev_enumerate);
-	ret = disconnect_subsys(udev_enumerate, nqn);
-	udev_enumerate_unref(udev_enumerate);
+	for (i = 0; i < n; i++)
+		free(devices[i]);
+	free(devices);
 
-free_udev:
-	udev_unref(udev);
-exit:
 	return ret;
 }
-#else
-static int disconnect_by_nqn(char *nqn)
-{
-	fprintf(stderr, "libudev not detected, install and rebuild.\n");
-	return -1;
-}
-#endif
 
 static int disconnect_by_device(char *device)
 {
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH] nvme-cli: fabrics: remove libudev dependency
  2016-12-16  0:05 [PATCH] nvme-cli: fabrics: remove libudev dependency Keith Busch
@ 2016-12-16  8:04 ` Christoph Hellwig
  2016-12-16 15:27   ` Keith Busch
  0 siblings, 1 reply; 4+ messages in thread
From: Christoph Hellwig @ 2016-12-16  8:04 UTC (permalink / raw)


On Thu, Dec 15, 2016@07:05:51PM -0500, Keith Busch wrote:
> I am getting a lot of complaints about portability of the nvme-cli
> regarding the libudev dependency. This patch removes the dependency from
> the fabrics disconnect command when using the target nqn method. Tested
> on nvme loop target.
> 
> Signed-off-by: Keith Busch <keith.busch at intel.com>
> ---
> I hadn't tried any of the nvme fabrics or targets before today, and just
> want to say that using the nvme loop device was incredibly pleasent to
> test with nvmetcli.
> 
> Since I'm not involved with the fabrics work, I wanted to send this out
> before pushing. It's a pretty straight foward conversion to get rid of
> the libudev dependency, and I suspect testing on the loop is probably
> good enough, but don't want to break anyone either.
> 
>  Makefile  |   7 ----
>  fabrics.c | 116 +++++++++++++++++++++++++-------------------------------------
>  2 files changed, 46 insertions(+), 77 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index 33c7190..13da0b7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -6,7 +6,6 @@ DESTDIR =
>  PREFIX ?= /usr/local
>  SYSCONFDIR = /etc
>  SBINDIR = $(PREFIX)/sbin
> -LIBUDEV := $(shell ld -o /dev/null -ludev >/dev/null 2>&1; echo $$?)
>  LIB_DEPENDS =
>  
>  RPMBUILD = rpmbuild
> @@ -15,12 +14,6 @@ RM = rm -f
>  
>  AUTHOR=Keith Busch <keith.busch at intel.com>
>  
> -ifeq ($(LIBUDEV),0)
> -	override LDFLAGS += -ludev
> -	override CFLAGS  += -DLIBUDEV_EXISTS
> -	override LIB_DEPENDS += udev
> -endif
> -
>  default: $(NVME)
>  
>  NVME-VERSION-FILE: FORCE
> diff --git a/fabrics.c b/fabrics.c
> index 2b3caa1..577aa9d 100644
> --- a/fabrics.c
> +++ b/fabrics.c
> @@ -26,13 +26,10 @@
>  #include <stdbool.h>
>  #include <stdint.h>
>  #include <unistd.h>
> +#include <dirent.h>
>  #include <sys/ioctl.h>
>  #include <asm/byteorder.h>
>  #include <inttypes.h>
> -#ifdef LIBUDEV_EXISTS
> -#include <libudev.h>
> -#endif
> -
>  #include <linux/types.h>
>  
>  #include "parser.h"
> @@ -62,6 +59,7 @@ static struct config {
>  #define PATH_NVME_FABRICS	"/dev/nvme-fabrics"
>  #define PATH_NVMF_DISC		"/etc/nvme/discovery.conf"
>  #define PATH_NVMF_HOSTNQN	"/etc/nvme/hostnqn"
> +#define SYS_NVME		"/sys/class/nvme"
>  #define MAX_DISC_ARGS		10
>  
>  enum {
> @@ -801,85 +799,63 @@ int connect(const char *desc, int argc, char **argv)
>  	return 0;
>  }
>  
> +static int scan_sys_nvme_filter(const struct dirent *d)
>  {
> +	return !((strcmp(d->d_name, ".") == 0) ||
> +		(strcmp(d->d_name, "..") == 0));
>  }

I find this a bit hard to read. Why not just:

static int scan_sys_nvme_filter(const struct dirent *d)
{
	if (!strcmp(d->d_name, "."))
		return 0;
	if (!strcmp(d->d_name, ".."))
		return 0;
	return 1;
}

>  
> +
>  static int disconnect_by_nqn(char *nqn)
>  {
> +	struct dirent ** devices = NULL;
> +	int i, n, fd, ret = 0;
> +	bool done = false;
> +	char subsysnqn[NVMF_NQN_SIZE] = {};
>  
> +	if (strlen(nqn) > NVMF_NQN_SIZE)
> +		return -EINVAL;
>  
> +	n = scandir(SYS_NVME, &devices, scan_sys_nvme_filter, alphasort);

Needs to handle an error return from scandir.

> +
> +	for (i = 0; i < n; i++) {
> +		char *sysfs_nqn_path;
>  
> +		asprintf(&sysfs_nqn_path, "%s/%s/subsysnqn",
> +			SYS_NVME, devices[i]->d_name);
> +
> +		fd = open(sysfs_nqn_path, O_RDONLY);

> +		if (fd > 0) {
> +			char *sysfs_del_path;
> +
> +			if (read(fd, subsysnqn, NVMF_NQN_SIZE) < 0)
> +				goto next;
> +
> +			subsysnqn[strcspn(subsysnqn, "\n")] = '\0';
> +			if (strcmp(subsysnqn, nqn))
> +				goto next;
> +
> +			asprintf(&sysfs_del_path, "%s/%s/delete_controller",
> +				SYS_NVME, devices[i]->d_name);
> +			ret = remove_ctrl_by_path(sysfs_del_path);
> +
> +			done = true;
> +			free(sysfs_del_path);
> + next:
> +			close(fd);
> +		}
> +
> +		free(sysfs_nqn_path);
> +		if (done)
> +			break;

We can have multiple controllers with the same nqn, and they should all
be deleted with this option.  Also I think factoring the removal code
in the inner block into a separate function would make this a bit more
readable.


Note that the reason why we used udev is that everyone recommends using
it for sysfs iterations, but I think your patch demonstrates that not
using libsysfs might actually make the code better..

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] nvme-cli: fabrics: remove libudev dependency
  2016-12-16  8:04 ` Christoph Hellwig
@ 2016-12-16 15:27   ` Keith Busch
  2016-12-17  7:25     ` Christoph Hellwig
  0 siblings, 1 reply; 4+ messages in thread
From: Keith Busch @ 2016-12-16 15:27 UTC (permalink / raw)


On Fri, Dec 16, 2016@12:04:19AM -0800, Christoph Hellwig wrote:
> We can have multiple controllers with the same nqn, and they should all
> be deleted with this option.  Also I think factoring the removal code
> in the inner block into a separate function would make this a bit more
> readable.

I also noticed that the description for the 'nqn' field is LIST, but
we're not splitting that item. Was this supposed to be a comma separated
value of nqn's?

Thanks for the other comments; I'll fix those up.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] nvme-cli: fabrics: remove libudev dependency
  2016-12-16 15:27   ` Keith Busch
@ 2016-12-17  7:25     ` Christoph Hellwig
  0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2016-12-17  7:25 UTC (permalink / raw)


On Fri, Dec 16, 2016@10:27:04AM -0500, Keith Busch wrote:
> On Fri, Dec 16, 2016@12:04:19AM -0800, Christoph Hellwig wrote:
> > We can have multiple controllers with the same nqn, and they should all
> > be deleted with this option.  Also I think factoring the removal code
> > in the inner block into a separate function would make this a bit more
> > readable.
> 
> I also noticed that the description for the 'nqn' field is LIST, but
> we're not splitting that item. Was this supposed to be a comma separated
> value of nqn's?

It wasn't supposed to be a list, but now that you mention it a list
of nqn might actually be useful.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-12-17  7:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-16  0:05 [PATCH] nvme-cli: fabrics: remove libudev dependency Keith Busch
2016-12-16  8:04 ` Christoph Hellwig
2016-12-16 15:27   ` Keith Busch
2016-12-17  7:25     ` Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.