[PATCH rdma-core 1/9] verbs: Move all dynamic driver opening code to dynamic_driver.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jason Gunthorpe <jgg@xxxxxxxxxxxx>

This is preparation for removing this code when statically linking.

Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
---
 libibverbs/CMakeLists.txt   |   1 +
 libibverbs/dynamic_driver.c | 239 ++++++++++++++++++++++++++++++++++++
 libibverbs/ibverbs.h        |   1 +
 libibverbs/init.c           | 206 -------------------------------
 4 files changed, 241 insertions(+), 206 deletions(-)
 create mode 100644 libibverbs/dynamic_driver.c

diff --git a/libibverbs/CMakeLists.txt b/libibverbs/CMakeLists.txt
index 738e5e15aaf00e..33e86a409708b0 100644
--- a/libibverbs/CMakeLists.txt
+++ b/libibverbs/CMakeLists.txt
@@ -38,6 +38,7 @@ rdma_library(ibverbs "${CMAKE_CURRENT_BINARY_DIR}/libibverbs.map"
   compat-1_0.c
   device.c
   dummy_ops.c
+  dynamic_driver.c
   enum_strs.c
   init.c
   marshall.c
diff --git a/libibverbs/dynamic_driver.c b/libibverbs/dynamic_driver.c
new file mode 100644
index 00000000000000..7a8f95b9e74f32
--- /dev/null
+++ b/libibverbs/dynamic_driver.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2006 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2018 Mellanox Technologies, Ltd.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#define _GNU_SOURCE
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <ccan/list.h>
+
+#include "ibverbs.h"
+
+struct ibv_driver_name {
+	struct list_node entry;
+	char *name;
+};
+
+static LIST_HEAD(driver_name_list);
+
+static void read_config_file(const char *path)
+{
+	FILE *conf;
+	char *line = NULL;
+	char *config;
+	char *field;
+	size_t buflen = 0;
+	ssize_t len;
+
+	conf = fopen(path, "r" STREAM_CLOEXEC);
+	if (!conf) {
+		fprintf(stderr, PFX "Warning: couldn't read config file %s.\n",
+			path);
+		return;
+	}
+
+	while ((len = getline(&line, &buflen, conf)) != -1) {
+		config = line + strspn(line, "\t ");
+		if (config[0] == '\n' || config[0] == '#')
+			continue;
+
+		field = strsep(&config, "\n\t ");
+
+		if (strcmp(field, "driver") == 0 && config != NULL) {
+			struct ibv_driver_name *driver_name;
+
+			config += strspn(config, "\t ");
+			field = strsep(&config, "\n\t ");
+
+			driver_name = malloc(sizeof(*driver_name));
+			if (!driver_name) {
+				fprintf(stderr,
+					PFX
+					"Warning: couldn't allocate driver name '%s'.\n",
+					field);
+				continue;
+			}
+
+			driver_name->name = strdup(field);
+			if (!driver_name->name) {
+				fprintf(stderr,
+					PFX
+					"Warning: couldn't allocate driver name '%s'.\n",
+					field);
+				free(driver_name);
+				continue;
+			}
+
+			list_add(&driver_name_list, &driver_name->entry);
+		} else
+			fprintf(stderr,
+				PFX
+				"Warning: ignoring bad config directive '%s' in file '%s'.\n",
+				field, path);
+	}
+
+	if (line)
+		free(line);
+	fclose(conf);
+}
+
+static void read_config(void)
+{
+	DIR *conf_dir;
+	struct dirent *dent;
+	char *path;
+
+	conf_dir = opendir(IBV_CONFIG_DIR);
+	if (!conf_dir) {
+		fprintf(stderr,
+			PFX "Warning: couldn't open config directory '%s'.\n",
+			IBV_CONFIG_DIR);
+		return;
+	}
+
+	while ((dent = readdir(conf_dir))) {
+		struct stat buf;
+
+		if (asprintf(&path, "%s/%s", IBV_CONFIG_DIR, dent->d_name) <
+		    0) {
+			fprintf(stderr,
+				PFX
+				"Warning: couldn't read config file %s/%s.\n",
+				IBV_CONFIG_DIR, dent->d_name);
+			goto out;
+		}
+
+		if (stat(path, &buf)) {
+			fprintf(stderr,
+				PFX
+				"Warning: couldn't stat config file '%s'.\n",
+				path);
+			goto next;
+		}
+
+		if (!S_ISREG(buf.st_mode))
+			goto next;
+
+		read_config_file(path);
+next:
+		free(path);
+	}
+
+out:
+	closedir(conf_dir);
+}
+
+static void load_driver(const char *name)
+{
+	char *so_name;
+	void *dlhandle;
+
+	/* If the name is an absolute path then open that path after appending
+	 * the trailer suffix
+	 */
+	if (name[0] == '/') {
+		if (asprintf(&so_name, "%s" VERBS_PROVIDER_SUFFIX, name) < 0)
+			goto out_asprintf;
+		dlhandle = dlopen(so_name, RTLD_NOW);
+		if (!dlhandle)
+			goto out_dlopen;
+		free(so_name);
+		return;
+	}
+
+	/* If configured with a provider plugin path then try that next */
+	if (sizeof(VERBS_PROVIDER_DIR) > 1) {
+		if (asprintf(&so_name,
+			     VERBS_PROVIDER_DIR "/lib%s" VERBS_PROVIDER_SUFFIX,
+			     name) < 0)
+			goto out_asprintf;
+		dlhandle = dlopen(so_name, RTLD_NOW);
+		free(so_name);
+		if (dlhandle)
+			return;
+	}
+
+	/* Otherwise use the system library search path. This is the historical
+	 * behavior of libibverbs
+	 */
+	if (asprintf(&so_name, "lib%s" VERBS_PROVIDER_SUFFIX, name) < 0)
+		goto out_asprintf;
+	dlhandle = dlopen(so_name, RTLD_NOW);
+	if (!dlhandle)
+		goto out_dlopen;
+	free(so_name);
+	return;
+
+out_asprintf:
+	fprintf(stderr, PFX "Warning: couldn't load driver '%s'.\n", name);
+	return;
+out_dlopen:
+	fprintf(stderr, PFX "Warning: couldn't load driver '%s': %s\n", so_name,
+		dlerror());
+	free(so_name);
+}
+
+void load_drivers(void)
+{
+	struct ibv_driver_name *name, *next_name;
+	const char *env;
+	char *list, *env_name;
+
+	read_config();
+
+	/* Only use drivers passed in through the calling user's environment
+	 * if we're not running setuid.
+	 */
+	if (getuid() == geteuid()) {
+		if ((env = getenv("RDMAV_DRIVERS"))) {
+			list = strdupa(env);
+			while ((env_name = strsep(&list, ":;")))
+				load_driver(env_name);
+		} else if ((env = getenv("IBV_DRIVERS"))) {
+			list = strdupa(env);
+			while ((env_name = strsep(&list, ":;")))
+				load_driver(env_name);
+		}
+	}
+
+	list_for_each_safe (&driver_name_list, name, next_name, entry) {
+		load_driver(name->name);
+		free(name->name);
+		free(name);
+	}
+}
diff --git a/libibverbs/ibverbs.h b/libibverbs/ibverbs.h
index 56be3627c81bdd..4ff4dc588410e6 100644
--- a/libibverbs/ibverbs.h
+++ b/libibverbs/ibverbs.h
@@ -61,6 +61,7 @@ int ibverbs_get_device_list(struct list_head *list);
 int ibverbs_init(void);
 void ibverbs_device_put(struct ibv_device *dev);
 void ibverbs_device_hold(struct ibv_device *dev);
+void load_drivers(void);
 
 struct verbs_ex_private {
 	BITMAP_DECLARE(unsupported_ioctls, VERBS_OPS_NUM);
diff --git a/libibverbs/init.c b/libibverbs/init.c
index a4c5f9e6e65d40..930d91811ca978 100644
--- a/libibverbs/init.c
+++ b/libibverbs/init.c
@@ -37,7 +37,6 @@
 #include <string.h>
 #include <glob.h>
 #include <stdio.h>
-#include <dlfcn.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -54,17 +53,11 @@
 
 int abi_ver;
 
-struct ibv_driver_name {
-	struct list_node	entry;
-	char		       *name;
-};
-
 struct ibv_driver {
 	struct list_node	entry;
 	const struct verbs_device_ops *ops;
 };
 
-static LIST_HEAD(driver_name_list);
 static LIST_HEAD(driver_list);
 
 static int try_access_device(const struct verbs_sysfs_dev *sysfs_dev)
@@ -192,179 +185,6 @@ void verbs_register_driver(const struct verbs_device_ops *ops)
 	list_add_tail(&driver_list, &driver->entry);
 }
 
-static void load_driver(const char *name)
-{
-	char *so_name;
-	void *dlhandle;
-
-	/* If the name is an absolute path then open that path after appending
-	   the trailer suffix */
-	if (name[0] == '/') {
-		if (asprintf(&so_name, "%s" VERBS_PROVIDER_SUFFIX, name) < 0)
-			goto out_asprintf;
-		dlhandle = dlopen(so_name, RTLD_NOW);
-		if (!dlhandle)
-			goto out_dlopen;
-		free(so_name);
-		return;
-	}
-
-	/* If configured with a provider plugin path then try that next */
-	if (sizeof(VERBS_PROVIDER_DIR) > 1) {
-		if (asprintf(&so_name,
-			     VERBS_PROVIDER_DIR "/lib%s" VERBS_PROVIDER_SUFFIX,
-			     name) < 0)
-			goto out_asprintf;
-		dlhandle = dlopen(so_name, RTLD_NOW);
-		free(so_name);
-		if (dlhandle)
-			return;
-	}
-
-	/* Otherwise use the system libary search path. This is the historical
-	   behavior of libibverbs */
-	if (asprintf(&so_name, "lib%s" VERBS_PROVIDER_SUFFIX, name) < 0)
-		goto out_asprintf;
-	dlhandle = dlopen(so_name, RTLD_NOW);
-	if (!dlhandle)
-		goto out_dlopen;
-	free(so_name);
-	return;
-
-out_asprintf:
-	fprintf(stderr, PFX "Warning: couldn't load driver '%s'.\n", name);
-	return;
-out_dlopen:
-	fprintf(stderr, PFX "Warning: couldn't load driver '%s': %s\n", so_name,
-		dlerror());
-	free(so_name);
-	return;
-}
-
-static void load_drivers(void)
-{
-	struct ibv_driver_name *name, *next_name;
-	const char *env;
-	char *list, *env_name;
-
-	/*
-	 * Only use drivers passed in through the calling user's
-	 * environment if we're not running setuid.
-	 */
-	if (getuid() == geteuid()) {
-		if ((env = getenv("RDMAV_DRIVERS"))) {
-			list = strdupa(env);
-			while ((env_name = strsep(&list, ":;")))
-				load_driver(env_name);
-		} else if ((env = getenv("IBV_DRIVERS"))) {
-			list = strdupa(env);
-			while ((env_name = strsep(&list, ":;")))
-				load_driver(env_name);
-		}
-	}
-
-	list_for_each_safe(&driver_name_list, name, next_name, entry) {
-		load_driver(name->name);
-		free(name->name);
-		free(name);
-	}
-}
-
-static void read_config_file(const char *path)
-{
-	FILE *conf;
-	char *line = NULL;
-	char *config;
-	char *field;
-	size_t buflen = 0;
-	ssize_t len;
-
-	conf = fopen(path, "r" STREAM_CLOEXEC);
-	if (!conf) {
-		fprintf(stderr, PFX "Warning: couldn't read config file %s.\n",
-			path);
-		return;
-	}
-
-	while ((len = getline(&line, &buflen, conf)) != -1) {
-		config = line + strspn(line, "\t ");
-		if (config[0] == '\n' || config[0] == '#')
-			continue;
-
-		field = strsep(&config, "\n\t ");
-
-		if (strcmp(field, "driver") == 0 && config != NULL) {
-			struct ibv_driver_name *driver_name;
-
-			config += strspn(config, "\t ");
-			field = strsep(&config, "\n\t ");
-
-			driver_name = malloc(sizeof *driver_name);
-			if (!driver_name) {
-				fprintf(stderr, PFX "Warning: couldn't allocate "
-					"driver name '%s'.\n", field);
-				continue;
-			}
-
-			driver_name->name = strdup(field);
-			if (!driver_name->name) {
-				fprintf(stderr, PFX "Warning: couldn't allocate "
-					"driver name '%s'.\n", field);
-				free(driver_name);
-				continue;
-			}
-
-			list_add(&driver_name_list, &driver_name->entry);
-		} else
-			fprintf(stderr, PFX "Warning: ignoring bad config directive "
-				"'%s' in file '%s'.\n", field, path);
-	}
-
-	if (line)
-		free(line);
-	fclose(conf);
-}
-
-static void read_config(void)
-{
-	DIR *conf_dir;
-	struct dirent *dent;
-	char *path;
-
-	conf_dir = opendir(IBV_CONFIG_DIR);
-	if (!conf_dir) {
-		fprintf(stderr, PFX "Warning: couldn't open config directory '%s'.\n",
-			IBV_CONFIG_DIR);
-		return;
-	}
-
-	while ((dent = readdir(conf_dir))) {
-		struct stat buf;
-
-		if (asprintf(&path, "%s/%s", IBV_CONFIG_DIR, dent->d_name) < 0) {
-			fprintf(stderr, PFX "Warning: couldn't read config file %s/%s.\n",
-				IBV_CONFIG_DIR, dent->d_name);
-			goto out;
-		}
-
-		if (stat(path, &buf)) {
-			fprintf(stderr, PFX "Warning: couldn't stat config file '%s'.\n",
-				path);
-			goto next;
-		}
-
-		if (!S_ISREG(buf.st_mode))
-			goto next;
-
-		read_config_file(path);
-next:
-		free(path);
-	}
-
-out:
-	closedir(conf_dir);
-}
-
 /* Match a single modalias value */
 static bool match_modalias(const struct verbs_match_ent *ent, const char *value)
 {
@@ -616,7 +436,6 @@ int ibverbs_get_device_list(struct list_head *device_list)
 	struct verbs_device *vdev, *tmp;
 	static int drivers_loaded;
 	unsigned int num_devices = 0;
-	int statically_linked = 0;
 	int ret;
 
 	ret = find_sysfs_devs(&sysfs_list);
@@ -652,26 +471,6 @@ int ibverbs_get_device_list(struct list_head *device_list)
 	if (list_empty(&sysfs_list) || drivers_loaded)
 		goto out;
 
-	/*
-	 * Check if we can dlopen() ourselves.  If this fails,
-	 * libibverbs is probably statically linked into the
-	 * executable, and we should just give up, since trying to
-	 * dlopen() a driver module will fail spectacularly (loading a
-	 * driver .so will bring in dynamic copies of libibverbs and
-	 * libdl to go along with the static copies the executable
-	 * has, which quickly leads to a crash.
-	 */
-	{
-		void *hand = dlopen(NULL, RTLD_NOW);
-		if (!hand) {
-			fprintf(stderr, PFX "Warning: dlopen(NULL) failed, "
-				"assuming static linking.\n");
-			statically_linked = 1;
-			goto out;
-		}
-		dlclose(hand);
-	}
-
 	load_drivers();
 	drivers_loaded = 1;
 
@@ -686,9 +485,6 @@ out:
 			fprintf(stderr, PFX
 				"Warning: no userspace device-specific driver found for %s\n",
 				sysfs_dev->sysfs_path);
-			if (statically_linked)
-				fprintf(stderr,
-					"	When linking libibverbs statically, driver must be statically linked too.\n");
 		}
 		free(sysfs_dev);
 	}
@@ -725,8 +521,6 @@ int ibverbs_init(void)
 
 	check_memlock_limit();
 
-	read_config();
-
 	return 0;
 }
 
-- 
2.19.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux