[stgt] [PATCH 2/2] dynamically link libibverbs and librdma

Doron Shoham dorons at voltaire.com
Wed Oct 8 11:19:31 CEST 2008


Pete Wyckoff wrote:
> dorons at Voltaire.COM wrote on Thu, 02 Oct 2008 13:30 +0300:
>> dynamically link libibverbs and librdma for using
>> stgt without having userspace IB (e.g tcp mode).
> 
> A couple of comments.
> 
>> @@ -1,4 +1,6 @@
>>  mandir = /usr/share/man
>> +libdir = /usr/lib64
>> +bindir = /usr/sbin
> 
> Fine for most 64-bit machines, not sure if we are worried about others.
> 
>>  tgtd: $(TGTD_OBJS)
>> -       $(CC) $^ -o $@ $(LIBS)
>> +       $(CC) -Xlinker -E $^ -o $@ $(LIBS)
> 
> You may need to do something like:
> 
>     $(LD) -o $@ -Wl,-whole-archive libtgtrdma.so -Wl,-no-whole-archive $(LIBS)
> 
> to make sure the constructor functions in the .so get called properly.

I've tried to use:
$(CC) -o $@ -Wl,-whole-archive libtgtrdma.so -Wl,-no-whole-archive $(LIBS)
but I received the following errors:
libtgtrdma.so: undefined reference to `ibv_ack_cq_events'
libtgtrdma.so: undefined reference to `rdma_reject'
libtgtrdma.so: undefined reference to `ibv_alloc_pd'
libtgtrdma.so: undefined reference to `ibv_destroy_qp'
libtgtrdma.so: undefined reference to `rdma_create_qp'
libtgtrdma.so: undefined reference to `ibv_dereg_mr'
libtgtrdma.so: undefined reference to `rdma_destroy_id'
libtgtrdma.so: undefined reference to `ibv_query_device'
libtgtrdma.so: undefined reference to `ibv_reg_mr'
libtgtrdma.so: undefined reference to `rdma_bind_addr'
libtgtrdma.so: undefined reference to `rdma_get_cm_event'
libtgtrdma.so: undefined reference to `rdma_create_event_channel'
libtgtrdma.so: undefined reference to `rdma_create_id'
libtgtrdma.so: undefined reference to `ibv_create_comp_channel'
libtgtrdma.so: undefined reference to `rdma_accept'
libtgtrdma.so: undefined reference to `rdma_disconnect'
libtgtrdma.so: undefined reference to `ibv_get_cq_event'
libtgtrdma.so: undefined reference to `rdma_listen'
libtgtrdma.so: undefined reference to `rdma_ack_cm_event'
libtgtrdma.so: undefined reference to `ibv_create_cq'

> 
>> +$(SO_LIBS): $(ISER_OBJS)
>> +       rm -f $@ $(SO_NAME)
>> +       $(LD) -shared -soname $(SO_LIBS) -o $(SO_LIBS) $(ISER_OBJS)
>> +       ln -s $(SO_LIBS) $(SO_NAME)
>> +
> 
> You must put -lrdmacm -libverbs on this $(LD) line.  I learned that
> the hard way once or twice.  Else the symbol versions don't work out
> at runtime.
> 

As far as I've seen it works without the -lrdmacm -libverbs.
Adding this causes the rpm be depended on libibverbs and librdmacm
and this is exactly what we wanted to avoid from.

[root at cumin tgt_with_dynamic]# rpm -qR scsi-target-utils
/bin/sh
/bin/sh
/bin/sh
/usr/bin/perl
libc.so.6()(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.2)(64bit)
libc.so.6(GLIBC_2.3.3)(64bit)
libcrypto.so.6()(64bit)
libdl.so.2()(64bit)
libdl.so.2(GLIBC_2.2.5)(64bit)
libibverbs.so.1()(64bit)
libibverbs.so.1(IBVERBS_1.0)(64bit)
libibverbs.so.1(IBVERBS_1.1)(64bit)
libpthread.so.0()(64bit)
libpthread.so.0(GLIBC_2.2.5)(64bit)
libpthread.so.0(GLIBC_2.3.2)(64bit)
librdmacm.so.1()(64bit)
librdmacm.so.1(RDMACM_1.0)(64bit)
perl(Config::General)
perl(Getopt::Long)
perl(strict)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)

>> +install_lib: $(SO_LIBS)
>> +	rm -f $(DESTDIR)$(libdir)/$(SO_NAME)
>> +	install -m 755 $(SO_LIBS) $(DESTDIR)$(libdir)
>> +	ln -s $(DESTDIR)/usr/lib64/$(SO_LIBS) $(DESTDIR)$(libdir)/$(SO_NAME)
> 
> maybe use $(libdir) in here too

Yes, you are correct, it should be $(libdir).

> 
>> +/*
>> + * iSCSI extensions for RDMA (iSER) data path
>> + *
>> + * Copyright (C) 2007 Dennis Dalessandro (dennis at osc.edu)
>> + * Copyright (C) 2007 Ananth Devulapalli (ananth at osc.edu)
>> + * Copyright (C) 2007 Pete Wyckoff (pw at osc.edu)
> 
> Actually you wrote this new file, in 2008.  And it needs a better
> description.
> 
>> +#include <stdio.h>
>> +#include <dlfcn.h>
>> +#include <syslog.h>
>> +
>> +static void *pverbs;
>> +static void *prdma;
>> +static void *ptgtrdma;
>> +
>> +__attribute__((constructor)) static void iser_transport_init(void)
>> +{
>> +	void (*iser_init)(void);
>> +	char *error;
>> +
>> +	pverbs = dlopen("libibverbs.so",RTLD_NOW|RTLD_GLOBAL);
>> +	if (!pverbs) {
>> +		goto Exit; /* do not register iser transport */
>> +	}
>> +
>> +	prdma = dlopen("librdmacm.so",RTLD_NOW|RTLD_GLOBAL);
>> +	if (!prdma) {
>> +		goto Exit; /* do not register iser transport */
>> +	}
>> +
>> +	ptgtrdma = dlopen("libtgtrdma.so",RTLD_NOW|RTLD_GLOBAL);
>> +	if (!ptgtrdma) {
>> +		goto Exit;
>> +	}
>> +
>> +	dlerror();    /* Clear any existing error */
>> +	iser_init = dlsym(ptgtrdma, "iser_transport_init");
>> +	if ((error = dlerror()) != NULL)  {
>> +		syslog(LOG_ERR, "%s\n", error);
>> +		goto Exit;
>> +	}
>> +
>> +	(*iser_init)();
> 
> My understanding is that iser_transport_init() would have been
> called by the dlopen() of libtgtrdma.so, as it is already marked
> ((constructor)).  Did you verify that this doesn't happen?  Maybe
> this requires the whole-archive bit above.
> 
> Also I figured dlopen("libtgtrdma.so") would pull in the other two
> libs on its own.  Please check, as it would be much cleaner just
> to have the single dlopen of libtgtrdma.so, and no dlsym or other
> libs.
> 
>> +__attribute__((destructor)) static void iser_transport_close(void)
>> +{
>> +	syslog(LOG_INFO, "iser transport cleanup");
>> +	if (pverbs)
>> +		dlclose(pverbs);
>> +	if (prdma)
>> +		dlclose(prdma);
>> +	if (ptgtrdma)
>> +		dlclose(ptgtrdma);
>> +}
> 
> Interesting.  I guess tgtd knows how to exit cleanly these days.
> But this stuff isn't strictly necessary; you can just exit and the
> OS will clean it all.
> 
>> diff --git a/usr/iscsi/libtgt_rdma.c b/usr/iscsi/libtgt_rdma.c
>> index d3b5147..d6ba5fa 100644
>> --- a/usr/iscsi/libtgt_rdma.c
>> +++ b/usr/iscsi/libtgt_rdma.c
>> @@ -30,6 +30,8 @@
>>  #include <sys/epoll.h>
>>  #include <infiniband/verbs.h>
>>  #include <rdma/rdma_cma.h>
>> +#include <dlfcn.h>
>> +#include <syslog.h>
>>  
>>  #include "util.h"
>>  #include "iscsid.h"
>> @@ -1754,7 +1756,9 @@ static struct iscsi_transport iscsi_iser = {
>>  	.ep_getpeername		= iscsi_rdma_getpeername,
>>  };
>>  
>> -__attribute__((constructor)) static void iser_transport_init(void)
>> +void iser_transport_init(void)
>>  {
>> +	syslog(LOG_INFO, "iser transport register");
>>  	iscsi_transport_register(&iscsi_iser);
>> +	return;
>>  }
> 
> Oh!  You removed the constructor.  Now I see why it doesn't work.
> Maybe try my suggestion instead?
> 
> 		-- Pete


After reviewing all the patch do you still think that 
all the changes are mandatory?

Thanks,
Doron

--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list