static int check_abi_version(void) { char value[8]; if ((ibv_read_sysfs_file(ibv_get_sysfs_path(), "class/misc/rdma_cm/abi_version", value, sizeof value) < 0) && (ibv_read_sysfs_file(ibv_get_sysfs_path(), "class/infiniband_ucma/abi_version", value, sizeof value) < 0)) { /* * Older version of Linux do not have class/misc. To support * backports, assume the most recent version of the ABI. If * we're wrong, we'll simply fail later when calling the ABI. */ fprintf(stderr, "librdmacm: couldn't read ABI version.\n"); fprintf(stderr, "librdmacm: assuming: %d\n", abi_ver); return 0; } abi_ver = strtol(value, NULL, 10); if (abi_ver < RDMA_USER_CM_MIN_ABI_VERSION || abi_ver > RDMA_USER_CM_MAX_ABI_VERSION) { fprintf(stderr, "librdmacm: kernel ABI version %d " "doesn't match library version %d.\n", abi_ver, RDMA_USER_CM_MAX_ABI_VERSION); return -1; } return 0; }
bool opal_common_verbs_check_basics(void) { #if defined(__linux__) int rc; char *file; struct stat s; /* Check to see if $sysfsdir/class/infiniband/ exists */ asprintf(&file, "%s/class/infiniband", ibv_get_sysfs_path()); if (NULL == file) { return false; } rc = stat(file, &s); free(file); if (0 != rc || !S_ISDIR(s.st_mode)) { return false; } #endif /* It exists and is a directory -- good enough */ return true; }
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 = vib_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) { 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; }
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; }