- Supress fprintf stderr on sundry cases like no verbs drivers loaded - Fix double free in find_sysfs_devs if ibv_read_sysfs_file fails (unlikely) - Update all example programs and man page
Code expecting this behavior linking to old libibverbs will get the old fprint and errno set to garbage (probably ESPIPE). Signed-off-by: Jason Gunthorpe <[email protected]> --- examples/asyncwatch.c | 2 +- examples/device_list.c | 2 +- examples/devinfo.c | 4 ++-- examples/rc_pingpong.c | 2 +- examples/srq_pingpong.c | 2 +- examples/uc_pingpong.c | 2 +- examples/ud_pingpong.c | 2 +- man/ibv_get_device_list.3 | 16 +++++++++++++++- src/device.c | 21 +++++++++++++++------ src/init.c | 38 ++++++++++++++++++-------------------- 10 files changed, 56 insertions(+), 35 deletions(-) The double free thing could be split out if you want, I just caught it while working on this. Works like this: $ build/examples/ibv_devinfo Failed to get IB devices list: Function not implemented $ build/examples/ibv_devinfo No IB devices found diff --git a/examples/asyncwatch.c b/examples/asyncwatch.c index 16aee2c..e56b4dc 100644 --- a/examples/asyncwatch.c +++ b/examples/asyncwatch.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) dev_list = ibv_get_device_list(NULL); if (!dev_list) { - fprintf(stderr, "No IB devices found\n"); + perror("Failed to get IB devices list"); return 1; } diff --git a/examples/device_list.c b/examples/device_list.c index 3ce8cbd..70c3af5 100644 --- a/examples/device_list.c +++ b/examples/device_list.c @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) dev_list = ibv_get_device_list(&num_devices); if (!dev_list) { - fprintf(stderr, "No IB devices found\n"); + perror("Failed to get IB devices list"); return 1; } diff --git a/examples/devinfo.c b/examples/devinfo.c index caa5d5f..33d1a9b 100644 --- a/examples/devinfo.c +++ b/examples/devinfo.c @@ -361,7 +361,7 @@ int main(int argc, char *argv[]) case 'l': dev_list = orig_dev_list = ibv_get_device_list(&num_of_hcas); if (!dev_list) { - fprintf(stderr, "Failed to get IB devices list"); + perror("Failed to get IB devices list"); return -1; } @@ -387,7 +387,7 @@ int main(int argc, char *argv[]) dev_list = orig_dev_list = ibv_get_device_list(NULL); if (!dev_list) { - fprintf(stderr, "Failed to get IB device list\n"); + perror("Failed to get IB devices list"); return -1; } diff --git a/examples/rc_pingpong.c b/examples/rc_pingpong.c index d4115e4..fa969e0 100644 --- a/examples/rc_pingpong.c +++ b/examples/rc_pingpong.c @@ -593,7 +593,7 @@ int main(int argc, char *argv[]) dev_list = ibv_get_device_list(NULL); if (!dev_list) { - fprintf(stderr, "No IB devices found\n"); + perror("Failed to get IB devices list"); return 1; } diff --git a/examples/srq_pingpong.c b/examples/srq_pingpong.c index e47bae6..1e36c57 100644 --- a/examples/srq_pingpong.c +++ b/examples/srq_pingpong.c @@ -682,7 +682,7 @@ int main(int argc, char *argv[]) dev_list = ibv_get_device_list(NULL); if (!dev_list) { - fprintf(stderr, "No IB devices found\n"); + perror("Failed to get IB devices list"); return 1; } diff --git a/examples/uc_pingpong.c b/examples/uc_pingpong.c index 404b059..6f31247 100644 --- a/examples/uc_pingpong.c +++ b/examples/uc_pingpong.c @@ -581,7 +581,7 @@ int main(int argc, char *argv[]) dev_list = ibv_get_device_list(NULL); if (!dev_list) { - fprintf(stderr, "No IB devices found\n"); + perror("Failed to get IB devices list"); return 1; } diff --git a/examples/ud_pingpong.c b/examples/ud_pingpong.c index 8f3d50b..6f10212 100644 --- a/examples/ud_pingpong.c +++ b/examples/ud_pingpong.c @@ -580,7 +580,7 @@ int main(int argc, char *argv[]) dev_list = ibv_get_device_list(NULL); if (!dev_list) { - fprintf(stderr, "No IB devices found\n"); + perror("Failed to get IB devices list"); return 1; } diff --git a/man/ibv_get_device_list.3 b/man/ibv_get_device_list.3 index 003fffb..16cc1a0 100644 --- a/man/ibv_get_device_list.3 +++ b/man/ibv_get_device_list.3 @@ -25,10 +25,24 @@ returned by .B ibv_get_device_list()\fR. .SH "RETURN VALUE" .B ibv_get_device_list() -returns the array of available RDMA devices, or NULL if the request fails. +returns the array of available RDMA devices, or sets +.I errno +and returns NULL if the request fails. If no devices are found then +.I num_devices +is set to 0, and non-NULL is returned. .PP .B ibv_free_device_list() returns no value. +.SH "ERRORS" +.TP +.B EPERM +Permission denied. +.TP +.B ENOSYS +No kernel support for RDMA. +.TP +.B ENOMEM +Insufficient memory to complete the operation. .SH "NOTES" Client code should open all the devices it intends to use with .B ibv_open_device()\fR before calling diff --git a/src/device.c b/src/device.c index 3abc1eb..6759c26 100644 --- a/src/device.c +++ b/src/device.c @@ -43,6 +43,7 @@ #include <unistd.h> #include <stdlib.h> #include <alloca.h> +#include <errno.h> #include <infiniband/arch.h> @@ -54,27 +55,35 @@ static struct ibv_device **device_list; struct ibv_device **__ibv_get_device_list(int *num) { - struct ibv_device **l; + struct ibv_device **l = 0; int i; + if (num) + *num = 0; + pthread_mutex_lock(&device_list_lock); if (!num_devices) num_devices = ibverbs_init(&device_list); + if (num_devices < 0) { + errno = -1*num_devices; + goto out; + } + l = calloc(num_devices + 1, sizeof (struct ibv_device *)); - if (!l) + if (!l) { + errno = ENOMEM; goto out; + } for (i = 0; i < num_devices; ++i) l[i] = device_list[i]; + if (num) + *num = num_devices; out: pthread_mutex_unlock(&device_list_lock); - - if (num) - *num = l ? num_devices : 0; - return l; } default_symver(__ibv_get_device_list, ibv_get_device_list); diff --git a/src/init.c b/src/init.c index 90d4292..bd8071f 100644 --- a/src/init.c +++ b/src/init.c @@ -46,6 +46,7 @@ #include <sys/time.h> #include <sys/resource.h> #include <dirent.h> +#include <errno.h> #include "ibverbs.h" @@ -76,23 +77,21 @@ 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 void find_sysfs_devs(void) +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 res = 0; snprintf(class_path, sizeof class_path, "%s/class/infiniband_verbs", ibv_get_sysfs_path()); class_dir = opendir(class_path); - if (!class_dir) { - fprintf(stderr, PFX "Fatal: couldn't open sysfs class " - "directory '%s'.\n", class_path); - return; - } + if (!class_dir) + return ENOSYS; while ((dent = readdir(class_dir))) { struct stat buf; @@ -103,9 +102,8 @@ static void find_sysfs_devs(void) if (!sysfs_dev) sysfs_dev = malloc(sizeof *sysfs_dev); if (!sysfs_dev) { - fprintf(stderr, PFX "Warning: couldn't allocate sysfs dev " - "for '%s'.\n", dent->d_name); - continue; + res = ENOMEM; + goto out; } snprintf(sysfs_dev->sysfs_path, sizeof sysfs_dev->sysfs_path, @@ -128,7 +126,6 @@ static void find_sysfs_devs(void) sizeof sysfs_dev->ibdev_name) < 0) { fprintf(stderr, PFX "Warning: no ibdev class attr for '%s'.\n", dent->d_name); - free(sysfs_dev); continue; } @@ -148,10 +145,12 @@ static void find_sysfs_devs(void) sysfs_dev = NULL; } + out: if (sysfs_dev) free(sysfs_dev); closedir(class_dir); + return res; } void ibv_register_driver(const char *name, ibv_driver_init_func init_func) @@ -392,8 +391,7 @@ static int check_abi_version(const char *path) if (ibv_read_sysfs_file(path, "class/infiniband_verbs/abi_version", value, sizeof value) < 0) { - fprintf(stderr, PFX "Fatal: couldn't read uverbs ABI version.\n"); - return -1; + return ENOSYS; } abi_ver = strtol(value, NULL, 10); @@ -403,7 +401,7 @@ static int check_abi_version(const char *path) fprintf(stderr, PFX "Fatal: kernel ABI version %d " "doesn't match library version %d.\n", abi_ver, IB_USER_VERBS_MAX_ABI_VERSION); - return -1; + return ENOSYS; } return 0; @@ -454,6 +452,7 @@ HIDDEN int ibverbs_init(struct ibv_device ***list) int list_size = 0; int statically_linked = 0; int no_driver = 0; + int rc; *list = NULL; @@ -463,19 +462,18 @@ HIDDEN int ibverbs_init(struct ibv_device ***list) "but init failed\n"); sysfs_path = ibv_get_sysfs_path(); - if (!sysfs_path) { - fprintf(stderr, PFX "Fatal: couldn't find sysfs mount.\n"); - return 0; - } + if (!sysfs_path) + return -ENOSYS; - if (check_abi_version(sysfs_path)) - return 0; + if ((rc = check_abi_version(sysfs_path))) + return -1*rc; check_memlock_limit(); read_config(); - find_sysfs_devs(); + if ((rc = find_sysfs_devs())) + return -1*rc; for (sysfs_dev = sysfs_dev_list; sysfs_dev; sysfs_dev = sysfs_dev->next) { device = try_drivers(sysfs_dev); -- 1.5.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
