Make ibv_get_device_list return codes via errno
PATCH 1/1 Make ibv_get_device_list return codes via errno
- 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).
--- 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
examples/asyncwatch.c +1 -1
@@ -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 ; }
examples/device_list.c +1 -1
@@ -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 ; }
examples/devinfo.c +2 -2
@@ -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 ; }
examples/rc_pingpong.c +1 -1
@@ -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 ; }
examples/srq_pingpong.c +1 -1
@@ -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 ; }
examples/uc_pingpong.c +1 -1
@@ -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 ; }
examples/ud_pingpong.c +1 -1
@@ -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 ; }
man/ibv_get_device_list.3 +15 -1
@@ -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
src/device.c +15 -6
@@ -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);
src/init.c +18 -20
@@ -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);
Signature · 6 lines
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