diff options
Diffstat (limited to 'src/init.c')
-rw-r--r-- | src/init.c | 575 |
1 files changed, 0 insertions, 575 deletions
diff --git a/src/init.c b/src/init.c deleted file mode 100644 index dbdd795..0000000 --- a/src/init.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2006 Cisco Systems, Inc. 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. - */ - -#if HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ - -#include <stdlib.h> -#include <string.h> -#include <glob.h> -#include <stdio.h> -#include <dlfcn.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <dirent.h> -#include <errno.h> - -#include "ibverbs.h" - -HIDDEN int abi_ver; - -struct ibv_sysfs_dev { - char sysfs_name[IBV_SYSFS_NAME_MAX]; - char ibdev_name[IBV_SYSFS_NAME_MAX]; - char sysfs_path[IBV_SYSFS_PATH_MAX]; - char ibdev_path[IBV_SYSFS_PATH_MAX]; - struct ibv_sysfs_dev *next; - int abi_ver; - int have_driver; -}; - -struct ibv_driver_name { - char *name; - struct ibv_driver_name *next; -}; - -struct ibv_driver { - const char *name; - ibv_driver_init_func init_func; - verbs_driver_init_func verbs_init_func; - struct ibv_driver *next; -}; - -static struct ibv_sysfs_dev *sysfs_dev_list; -static struct ibv_driver_name *driver_name_list; -static struct ibv_driver *head_driver, *tail_driver; - -static int find_sysfs_devs(void) -{ - char class_path[IBV_SYSFS_PATH_MAX]; - DIR *class_dir; - struct dirent *dent; - struct ibv_sysfs_dev *sysfs_dev = NULL; - char value[8]; - int ret = 0; - - snprintf(class_path, sizeof class_path, "%s/class/infiniband_verbs", - ibv_get_sysfs_path()); - - class_dir = opendir(class_path); - if (!class_dir) - return ENOSYS; - - while ((dent = readdir(class_dir))) { - struct stat buf; - - if (dent->d_name[0] == '.') - continue; - - if (!sysfs_dev) - sysfs_dev = malloc(sizeof *sysfs_dev); - if (!sysfs_dev) { - ret = ENOMEM; - goto out; - } - - snprintf(sysfs_dev->sysfs_path, sizeof sysfs_dev->sysfs_path, - "%s/%s", class_path, dent->d_name); - - if (stat(sysfs_dev->sysfs_path, &buf)) { - fprintf(stderr, PFX "Warning: couldn't stat '%s'.\n", - sysfs_dev->sysfs_path); - continue; - } - - if (!S_ISDIR(buf.st_mode)) - continue; - - snprintf(sysfs_dev->sysfs_name, sizeof sysfs_dev->sysfs_name, - "%s", dent->d_name); - - if (ibv_read_sysfs_file(sysfs_dev->sysfs_path, "ibdev", - sysfs_dev->ibdev_name, - sizeof sysfs_dev->ibdev_name) < 0) { - fprintf(stderr, PFX "Warning: no ibdev class attr for '%s'.\n", - dent->d_name); - continue; - } - - snprintf(sysfs_dev->ibdev_path, sizeof sysfs_dev->ibdev_path, - "%s/class/infiniband/%s", ibv_get_sysfs_path(), - sysfs_dev->ibdev_name); - - sysfs_dev->next = sysfs_dev_list; - sysfs_dev->have_driver = 0; - if (ibv_read_sysfs_file(sysfs_dev->sysfs_path, "abi_version", - value, sizeof value) > 0) - sysfs_dev->abi_ver = strtol(value, NULL, 10); - else - sysfs_dev->abi_ver = 0; - - sysfs_dev_list = sysfs_dev; - sysfs_dev = NULL; - } - - out: - if (sysfs_dev) - free(sysfs_dev); - - closedir(class_dir); - return ret; -} - -static void register_driver(const char *name, ibv_driver_init_func init_func, - verbs_driver_init_func verbs_init_func) -{ - struct ibv_driver *driver; - - driver = malloc(sizeof *driver); - if (!driver) { - fprintf(stderr, PFX "Warning: couldn't allocate driver for %s\n", name); - return; - } - - driver->name = name; - driver->init_func = init_func; - driver->verbs_init_func = verbs_init_func; - driver->next = NULL; - - if (tail_driver) - tail_driver->next = driver; - else - head_driver = driver; - tail_driver = driver; -} - -void ibv_register_driver(const char *name, ibv_driver_init_func init_func) -{ - register_driver(name, init_func, NULL); -} - -/* New registration symbol with same functionality - used by providers to - * validate that library supports verbs extension. - */ -void verbs_register_driver(const char *name, verbs_driver_init_func init_func) -{ - register_driver(name, NULL, init_func); -} - -static void load_driver(const char *name) -{ - char *so_name; - void *dlhandle; - -#define __IBV_QUOTE(x) #x -#define IBV_QUOTE(x) __IBV_QUOTE(x) - - if (asprintf(&so_name, - name[0] == '/' ? - "%s-" IBV_QUOTE(IBV_DEVICE_LIBRARY_EXTENSION) ".so" : - "lib%s-" IBV_QUOTE(IBV_DEVICE_LIBRARY_EXTENSION) ".so", - name) < 0) { - fprintf(stderr, PFX "Warning: couldn't load driver '%s'.\n", - name); - return; - } - - dlhandle = dlopen(so_name, RTLD_NOW); - if (!dlhandle) { - fprintf(stderr, PFX "Warning: couldn't load driver '%s': %s\n", - name, dlerror()); - goto out; - } - -out: - free(so_name); -} - -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); - } - } - - for (name = driver_name_list, next_name = name ? name->next : NULL; - name; - name = next_name, next_name = name ? name->next : NULL) { - 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; - } - - driver_name->next = driver_name_list; - driver_name_list = driver_name; - } 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 struct ibv_device *try_driver(struct ibv_driver *driver, - struct ibv_sysfs_dev *sysfs_dev) -{ - struct verbs_device *vdev; - struct ibv_device *dev; - char value[8]; - - if (driver->init_func) { - dev = driver->init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver); - if (!dev) - return NULL; - } else { - vdev = driver->verbs_init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver); - if (!vdev) - return NULL; - - dev = &vdev->device; - dev->ops.alloc_context = NULL; - dev->ops.free_context = NULL; - } - - if (ibv_read_sysfs_file(sysfs_dev->ibdev_path, "node_type", value, sizeof value) < 0) { - fprintf(stderr, PFX "Warning: no node_type attr under %s.\n", - sysfs_dev->ibdev_path); - dev->node_type = IBV_NODE_UNKNOWN; - } else { - dev->node_type = strtol(value, NULL, 10); - if (dev->node_type < IBV_NODE_CA || dev->node_type > IBV_NODE_USNIC_UDP) - dev->node_type = IBV_NODE_UNKNOWN; - } - - switch (dev->node_type) { - case IBV_NODE_CA: - case IBV_NODE_SWITCH: - case IBV_NODE_ROUTER: - dev->transport_type = IBV_TRANSPORT_IB; - break; - case IBV_NODE_RNIC: - dev->transport_type = IBV_TRANSPORT_IWARP; - break; - case IBV_NODE_USNIC: - dev->transport_type = IBV_TRANSPORT_USNIC; - break; - case IBV_NODE_USNIC_UDP: - dev->transport_type = IBV_TRANSPORT_USNIC_UDP; - break; - default: - dev->transport_type = IBV_TRANSPORT_UNKNOWN; - break; - } - - strcpy(dev->dev_name, sysfs_dev->sysfs_name); - strcpy(dev->dev_path, sysfs_dev->sysfs_path); - strcpy(dev->name, sysfs_dev->ibdev_name); - strcpy(dev->ibdev_path, sysfs_dev->ibdev_path); - - return dev; -} - -static struct ibv_device *try_drivers(struct ibv_sysfs_dev *sysfs_dev) -{ - struct ibv_driver *driver; - struct ibv_device *dev; - - for (driver = head_driver; driver; driver = driver->next) { - dev = try_driver(driver, sysfs_dev); - if (dev) - return dev; - } - - return NULL; -} - -static int check_abi_version(const char *path) -{ - char value[8]; - - if (ibv_read_sysfs_file(path, "class/infiniband_verbs/abi_version", - value, sizeof value) < 0) { - return ENOSYS; - } - - abi_ver = strtol(value, NULL, 10); - - if (abi_ver < IB_USER_VERBS_MIN_ABI_VERSION || - abi_ver > IB_USER_VERBS_MAX_ABI_VERSION) { - fprintf(stderr, PFX "Fatal: kernel ABI version %d " - "doesn't match library version %d.\n", - abi_ver, IB_USER_VERBS_MAX_ABI_VERSION); - return ENOSYS; - } - - return 0; -} - -static void check_memlock_limit(void) -{ - struct rlimit rlim; - - if (!geteuid()) - return; - - if (getrlimit(RLIMIT_MEMLOCK, &rlim)) { - fprintf(stderr, PFX "Warning: getrlimit(RLIMIT_MEMLOCK) failed."); - return; - } - - if (rlim.rlim_cur <= 32768) - fprintf(stderr, PFX "Warning: RLIMIT_MEMLOCK is %lu bytes.\n" - " This will severely limit memory registrations.\n", - rlim.rlim_cur); -} - -static void add_device(struct ibv_device *dev, - struct ibv_device ***dev_list, - int *num_devices, - int *list_size) -{ - struct ibv_device **new_list; - - if (*list_size <= *num_devices) { - *list_size = *list_size ? *list_size * 2 : 1; - new_list = realloc(*dev_list, *list_size * sizeof (struct ibv_device *)); - if (!new_list) - return; - *dev_list = new_list; - } - - (*dev_list)[(*num_devices)++] = dev; -} - -HIDDEN int ibverbs_init(struct ibv_device ***list) -{ - const char *sysfs_path; - struct ibv_sysfs_dev *sysfs_dev, *next_dev; - struct ibv_device *device; - int num_devices = 0; - int list_size = 0; - int statically_linked = 0; - int no_driver = 0; - int ret; - - *list = NULL; - - if (getenv("RDMAV_FORK_SAFE") || getenv("IBV_FORK_SAFE")) - if (ibv_fork_init()) - fprintf(stderr, PFX "Warning: fork()-safety requested " - "but init failed\n"); - - sysfs_path = ibv_get_sysfs_path(); - if (!sysfs_path) - return -ENOSYS; - - ret = check_abi_version(sysfs_path); - if (ret) - return -ret; - - check_memlock_limit(); - - read_config(); - - ret = find_sysfs_devs(); - if (ret) - return -ret; - - for (sysfs_dev = sysfs_dev_list; sysfs_dev; sysfs_dev = sysfs_dev->next) { - device = try_drivers(sysfs_dev); - if (device) { - add_device(device, list, &num_devices, &list_size); - sysfs_dev->have_driver = 1; - } else - no_driver = 1; - } - - if (!no_driver) - 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(); - - for (sysfs_dev = sysfs_dev_list; sysfs_dev; sysfs_dev = sysfs_dev->next) { - if (sysfs_dev->have_driver) - continue; - - device = try_drivers(sysfs_dev); - if (device) { - add_device(device, list, &num_devices, &list_size); - sysfs_dev->have_driver = 1; - } - } - -out: - for (sysfs_dev = sysfs_dev_list, - next_dev = sysfs_dev ? sysfs_dev->next : NULL; - sysfs_dev; - sysfs_dev = next_dev, next_dev = sysfs_dev ? sysfs_dev->next : NULL) { - if (!sysfs_dev->have_driver && getenv("IBV_SHOW_WARNINGS")) { - 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); - } - - return num_devices; -} |